/* * linux/drivers/davinci/i2c_davinci_client.c * * Copyright (C) 2004 Texas Instruments Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* i2c_davinci_client.c */ #include #include #include #include #include #include #include #include #include struct davinci_bus_ops { unsigned char version; int (*init) (void); void (*cleanup) (void); int (*read) (u8 size, u8 * val, u16 addr); int (*write) (u8 size, u8 * val, u16 addr); }; struct davinci_i2c_param { /* I2C parameters */ struct i2c_client client; struct i2c_driver driver; }; static struct davinci_i2c_param davinci_i2c_dev; int davinci_i2c_read(u8 size, u8 * val, u16 client_addr) { int err; struct i2c_client *client = &davinci_i2c_dev.client; struct i2c_msg msg[1]; if (!client->adapter) return -ENODEV; msg->addr = client_addr; msg->flags = I2C_M_RD; msg->len = size; msg->buf = val; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { return 0; } return err; } int davinci_i2c_write(u8 size, u8 * val, u16 client_addr) { int err; struct i2c_client *client = &davinci_i2c_dev.client; struct i2c_msg msg[1]; if (!client->adapter) return -ENODEV; msg->addr = client_addr; msg->flags = 0; msg->len = size; msg->buf = val; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) return 0; return err; } EXPORT_SYMBOL(davinci_i2c_read); EXPORT_SYMBOL(davinci_i2c_write); static int davinci_i2c_attach_client(struct i2c_adapter *adap, int addr) { struct davinci_i2c_param *davinci_i2c_if = &davinci_i2c_dev; struct i2c_client *client = &davinci_i2c_if->client; int err; if (client->adapter) return -EBUSY; /* our client is already attached */ client->addr = addr; client->flags = I2C_CLIENT_ALLOW_USE; client->driver = &davinci_i2c_if->driver; client->adapter = adap; err = i2c_attach_client(client); if (err) { client->adapter = NULL; return err; } return 0; } static int davinci_i2c_detach_client(struct i2c_client *client) { int err; if (!client->adapter) return -ENODEV; /* our client isn't attached */ err = i2c_detach_client(client); client->adapter = NULL; return err; } static int davinci_i2c_probe_adapter(struct i2c_adapter *adap) { return davinci_i2c_attach_client(adap, 0x3A); } static int davinci_i2c_init(void) { int err; struct i2c_driver *driver = &davinci_i2c_dev.driver; driver->owner = THIS_MODULE; strlcpy(driver->name, "Davinci I2C driver", sizeof(driver->name)); driver->id = I2C_DRIVERID_EXP0; driver->flags = I2C_DF_NOTIFY; driver->attach_adapter = davinci_i2c_probe_adapter; driver->detach_client = davinci_i2c_detach_client; err = i2c_add_driver(driver); if (err) { printk(KERN_ERR "Failed to register Davinci I2C client.\n"); return err; } return 0; } static void davinci_i2c_cleanup(void) { i2c_detach_client(&davinci_i2c_dev.client); davinci_i2c_dev.client.adapter = NULL; return; } struct davinci_bus_ops davinci_i2c_fops = { .version = 0x01, .init = davinci_i2c_init, .cleanup = davinci_i2c_cleanup, .read = davinci_i2c_read, .write = davinci_i2c_write, }; static int __init davinci_i2c_perienable(void) { char value = 0; #ifdef CONFIG_DAVINCI_BLK_DEV_CF char cmd[4] = { 4, 6, 0x00, 0x09 }; #endif davinci_i2c_fops.init(); #ifdef CONFIG_DAVINCI_I2C_EXPANDER #ifdef CONFIG_DAVINCI_BLK_DEV_CF davinci_i2c_write(4, cmd, 0x23); value = 0x6f; #else value = 0xa7; #endif davinci_i2c_write(1, &value, 0x3A); #endif return 0; } module_init(davinci_i2c_perienable);