diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-tiny-usb.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-tiny-usb.c | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index b1c050ff311..0ed77eeff31 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -13,6 +13,8 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/module.h> +#include <linux/slab.h> +#include <linux/types.h> /* include interfaces to usb layer */ #include <linux/usb.h> @@ -30,11 +32,13 @@ #define CMD_I2C_IO_BEGIN (1<<0) #define CMD_I2C_IO_END (1<<1) -/* i2c bit delay, default is 10us -> 100kHz */ -static int delay = 10; -module_param(delay, int, 0); -MODULE_PARM_DESC(delay, "bit delay in microseconds, " - "e.g. 10 for 100kHz (default is 100kHz)"); +/* i2c bit delay, default is 10us -> 100kHz max + (in practice, due to additional delays in the i2c bitbanging + code this results in a i2c clock of about 50kHz) */ +static unsigned short delay = 10; +module_param(delay, ushort, 0); +MODULE_PARM_DESC(delay, "bit delay in microseconds " + "(default is 10us for 100kHz max)"); static int usb_read(struct i2c_adapter *adapter, int cmd, int value, int index, void *data, int len); @@ -50,12 +54,16 @@ static int usb_write(struct i2c_adapter *adapter, int cmd, static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - unsigned char status; + unsigned char *pstatus; struct i2c_msg *pmsg; - int i; + int i, ret; dev_dbg(&adapter->dev, "master xfer %d messages:\n", num); + pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL); + if (!pstatus) + return -ENOMEM; + for (i = 0 ; i < num ; i++) { int cmd = CMD_I2C_IO; @@ -80,7 +88,8 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) pmsg->buf, pmsg->len) != pmsg->len) { dev_err(&adapter->dev, "failure reading data\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } } else { /* write data */ @@ -89,36 +98,50 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) pmsg->buf, pmsg->len) != pmsg->len) { dev_err(&adapter->dev, "failure writing data\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } } /* read status */ - if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) { + if (usb_read(adapter, CMD_GET_STATUS, 0, 0, pstatus, 1) != 1) { dev_err(&adapter->dev, "failure reading status\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } - dev_dbg(&adapter->dev, " status = %d\n", status); - if (status == STATUS_ADDRESS_NAK) - return -EREMOTEIO; + dev_dbg(&adapter->dev, " status = %d\n", *pstatus); + if (*pstatus == STATUS_ADDRESS_NAK) { + ret = -EREMOTEIO; + goto out; + } } - return i; + ret = i; +out: + kfree(pstatus); + return ret; } static u32 usb_func(struct i2c_adapter *adapter) { - u32 func; + __le32 *pfunc; + u32 ret; + + pfunc = kmalloc(sizeof(*pfunc), GFP_KERNEL); /* get functionality from adapter */ - if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != - sizeof(func)) { + if (!pfunc || usb_read(adapter, CMD_GET_FUNC, 0, 0, pfunc, + sizeof(*pfunc)) != sizeof(*pfunc)) { dev_err(&adapter->dev, "failure reading functionality\n"); - return 0; + ret = 0; + goto out; } - return func; + ret = le32_to_cpup(pfunc); +out: + kfree(pfunc); + return ret; } /* This is the actual algorithm we define */ @@ -136,7 +159,7 @@ static const struct i2c_algorithm usb_algorithm = { * Future Technology Devices International Ltd., later a pair was * bought from EZPrototypes */ -static struct usb_device_id i2c_tiny_usb_table [] = { +static const struct usb_device_id i2c_tiny_usb_table[] = { { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ { } /* Terminating entry */ @@ -216,8 +239,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, "i2c-tiny-usb at bus %03d device %03d", dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - if (usb_write(&dev->adapter, CMD_SET_DELAY, - cpu_to_le16(delay), 0, NULL, 0) != 0) { + if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) { dev_err(&dev->adapter.dev, "failure setting delay to %dus\n", delay); retval = -EIO; @@ -259,20 +281,7 @@ static struct usb_driver i2c_tiny_usb_driver = { .id_table = i2c_tiny_usb_table, }; -static int __init usb_i2c_tiny_usb_init(void) -{ - /* register this driver with the USB subsystem */ - return usb_register(&i2c_tiny_usb_driver); -} - -static void __exit usb_i2c_tiny_usb_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&i2c_tiny_usb_driver); -} - -module_init(usb_i2c_tiny_usb_init); -module_exit(usb_i2c_tiny_usb_exit); +module_usb_driver(i2c_tiny_usb_driver); /* ----- end of usb layer ------------------------------------------------ */ |
