Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for the Diolan u2c-12 USB-I2C adapter
0004  *
0005  * Copyright (c) 2010-2011 Ericsson AB
0006  *
0007  * Derived from:
0008  *  i2c-tiny-usb.c
0009  *  Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org)
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/errno.h>
0014 #include <linux/module.h>
0015 #include <linux/types.h>
0016 #include <linux/slab.h>
0017 #include <linux/usb.h>
0018 #include <linux/i2c.h>
0019 
0020 #define DRIVER_NAME     "i2c-diolan-u2c"
0021 
0022 #define USB_VENDOR_ID_DIOLAN        0x0abf
0023 #define USB_DEVICE_ID_DIOLAN_U2C    0x3370
0024 
0025 
0026 /* commands via USB, must match command ids in the firmware */
0027 #define CMD_I2C_READ        0x01
0028 #define CMD_I2C_WRITE       0x02
0029 #define CMD_I2C_SCAN        0x03    /* Returns list of detected devices */
0030 #define CMD_I2C_RELEASE_SDA 0x04
0031 #define CMD_I2C_RELEASE_SCL 0x05
0032 #define CMD_I2C_DROP_SDA    0x06
0033 #define CMD_I2C_DROP_SCL    0x07
0034 #define CMD_I2C_READ_SDA    0x08
0035 #define CMD_I2C_READ_SCL    0x09
0036 #define CMD_GET_FW_VERSION  0x0a
0037 #define CMD_GET_SERIAL      0x0b
0038 #define CMD_I2C_START       0x0c
0039 #define CMD_I2C_STOP        0x0d
0040 #define CMD_I2C_REPEATED_START  0x0e
0041 #define CMD_I2C_PUT_BYTE    0x0f
0042 #define CMD_I2C_GET_BYTE    0x10
0043 #define CMD_I2C_PUT_ACK     0x11
0044 #define CMD_I2C_GET_ACK     0x12
0045 #define CMD_I2C_PUT_BYTE_ACK    0x13
0046 #define CMD_I2C_GET_BYTE_ACK    0x14
0047 #define CMD_I2C_SET_SPEED   0x1b
0048 #define CMD_I2C_GET_SPEED   0x1c
0049 #define CMD_I2C_SET_CLK_SYNC    0x24
0050 #define CMD_I2C_GET_CLK_SYNC    0x25
0051 #define CMD_I2C_SET_CLK_SYNC_TO 0x26
0052 #define CMD_I2C_GET_CLK_SYNC_TO 0x27
0053 
0054 #define RESP_OK         0x00
0055 #define RESP_FAILED     0x01
0056 #define RESP_BAD_MEMADDR    0x04
0057 #define RESP_DATA_ERR       0x05
0058 #define RESP_NOT_IMPLEMENTED    0x06
0059 #define RESP_NACK       0x07
0060 #define RESP_TIMEOUT        0x09
0061 
0062 #define U2C_I2C_SPEED_FAST  0   /* 400 kHz */
0063 #define U2C_I2C_SPEED_STD   1   /* 100 kHz */
0064 #define U2C_I2C_SPEED_2KHZ  242 /* 2 kHz, minimum speed */
0065 #define U2C_I2C_SPEED(f)    ((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1)
0066 
0067 #define U2C_I2C_FREQ(s)     (1000000 / (2 * (s - 1) + 10))
0068 
0069 #define DIOLAN_USB_TIMEOUT  100 /* in ms */
0070 #define DIOLAN_SYNC_TIMEOUT 20  /* in ms */
0071 
0072 #define DIOLAN_OUTBUF_LEN   128
0073 #define DIOLAN_FLUSH_LEN    (DIOLAN_OUTBUF_LEN - 4)
0074 #define DIOLAN_INBUF_LEN    256 /* Maximum supported receive length */
0075 
0076 /* Structure to hold all of our device specific stuff */
0077 struct i2c_diolan_u2c {
0078     u8 obuffer[DIOLAN_OUTBUF_LEN];  /* output buffer */
0079     u8 ibuffer[DIOLAN_INBUF_LEN];   /* input buffer */
0080     int ep_in, ep_out;              /* Endpoints    */
0081     struct usb_device *usb_dev; /* the usb device for this device */
0082     struct usb_interface *interface;/* the interface for this device */
0083     struct i2c_adapter adapter; /* i2c related things */
0084     int olen;           /* Output buffer length */
0085     int ocount;         /* Number of enqueued messages */
0086 };
0087 
0088 static uint frequency = I2C_MAX_STANDARD_MODE_FREQ; /* I2C clock frequency in Hz */
0089 
0090 module_param(frequency, uint, S_IRUGO | S_IWUSR);
0091 MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz");
0092 
0093 /* usb layer */
0094 
0095 /* Send command to device, and get response. */
0096 static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
0097 {
0098     int ret = 0;
0099     int actual;
0100     int i;
0101 
0102     if (!dev->olen || !dev->ocount)
0103         return -EINVAL;
0104 
0105     ret = usb_bulk_msg(dev->usb_dev,
0106                usb_sndbulkpipe(dev->usb_dev, dev->ep_out),
0107                dev->obuffer, dev->olen, &actual,
0108                DIOLAN_USB_TIMEOUT);
0109     if (!ret) {
0110         for (i = 0; i < dev->ocount; i++) {
0111             int tmpret;
0112 
0113             tmpret = usb_bulk_msg(dev->usb_dev,
0114                           usb_rcvbulkpipe(dev->usb_dev,
0115                                   dev->ep_in),
0116                           dev->ibuffer,
0117                           sizeof(dev->ibuffer), &actual,
0118                           DIOLAN_USB_TIMEOUT);
0119             /*
0120              * Stop command processing if a previous command
0121              * returned an error.
0122              * Note that we still need to retrieve all messages.
0123              */
0124             if (ret < 0)
0125                 continue;
0126             ret = tmpret;
0127             if (ret == 0 && actual > 0) {
0128                 switch (dev->ibuffer[actual - 1]) {
0129                 case RESP_NACK:
0130                     /*
0131                      * Return ENXIO if NACK was received as
0132                      * response to the address phase,
0133                      * EIO otherwise
0134                      */
0135                     ret = i == 1 ? -ENXIO : -EIO;
0136                     break;
0137                 case RESP_TIMEOUT:
0138                     ret = -ETIMEDOUT;
0139                     break;
0140                 case RESP_OK:
0141                     /* strip off return code */
0142                     ret = actual - 1;
0143                     break;
0144                 default:
0145                     ret = -EIO;
0146                     break;
0147                 }
0148             }
0149         }
0150     }
0151     dev->olen = 0;
0152     dev->ocount = 0;
0153     return ret;
0154 }
0155 
0156 static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush)
0157 {
0158     if (flush || dev->olen >= DIOLAN_FLUSH_LEN)
0159         return diolan_usb_transfer(dev);
0160     return 0;
0161 }
0162 
0163 /* Send command (no data) */
0164 static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush)
0165 {
0166     dev->obuffer[dev->olen++] = command;
0167     dev->ocount++;
0168     return diolan_write_cmd(dev, flush);
0169 }
0170 
0171 /* Send command with one byte of data */
0172 static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data,
0173                    bool flush)
0174 {
0175     dev->obuffer[dev->olen++] = command;
0176     dev->obuffer[dev->olen++] = data;
0177     dev->ocount++;
0178     return diolan_write_cmd(dev, flush);
0179 }
0180 
0181 /* Send command with two bytes of data */
0182 static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1,
0183                 u8 d2, bool flush)
0184 {
0185     dev->obuffer[dev->olen++] = command;
0186     dev->obuffer[dev->olen++] = d1;
0187     dev->obuffer[dev->olen++] = d2;
0188     dev->ocount++;
0189     return diolan_write_cmd(dev, flush);
0190 }
0191 
0192 /*
0193  * Flush input queue.
0194  * If we don't do this at startup and the controller has queued up
0195  * messages which were not retrieved, it will stop responding
0196  * at some point.
0197  */
0198 static void diolan_flush_input(struct i2c_diolan_u2c *dev)
0199 {
0200     int i;
0201 
0202     for (i = 0; i < 10; i++) {
0203         int actual = 0;
0204         int ret;
0205 
0206         ret = usb_bulk_msg(dev->usb_dev,
0207                    usb_rcvbulkpipe(dev->usb_dev, dev->ep_in),
0208                    dev->ibuffer, sizeof(dev->ibuffer), &actual,
0209                    DIOLAN_USB_TIMEOUT);
0210         if (ret < 0 || actual == 0)
0211             break;
0212     }
0213     if (i == 10)
0214         dev_err(&dev->interface->dev, "Failed to flush input buffer\n");
0215 }
0216 
0217 static int diolan_i2c_start(struct i2c_diolan_u2c *dev)
0218 {
0219     return diolan_usb_cmd(dev, CMD_I2C_START, false);
0220 }
0221 
0222 static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev)
0223 {
0224     return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false);
0225 }
0226 
0227 static int diolan_i2c_stop(struct i2c_diolan_u2c *dev)
0228 {
0229     return diolan_usb_cmd(dev, CMD_I2C_STOP, true);
0230 }
0231 
0232 static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack,
0233                    u8 *byte)
0234 {
0235     int ret;
0236 
0237     ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true);
0238     if (ret > 0)
0239         *byte = dev->ibuffer[0];
0240     else if (ret == 0)
0241         ret = -EIO;
0242 
0243     return ret;
0244 }
0245 
0246 static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte)
0247 {
0248     return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false);
0249 }
0250 
0251 static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed)
0252 {
0253     return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true);
0254 }
0255 
0256 /* Enable or disable clock synchronization (stretching) */
0257 static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable)
0258 {
0259     return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true);
0260 }
0261 
0262 /* Set clock synchronization timeout in ms */
0263 static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms)
0264 {
0265     int to_val = ms * 10;
0266 
0267     return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO,
0268                     to_val & 0xff, (to_val >> 8) & 0xff, true);
0269 }
0270 
0271 static void diolan_fw_version(struct i2c_diolan_u2c *dev)
0272 {
0273     int ret;
0274 
0275     ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true);
0276     if (ret >= 2)
0277         dev_info(&dev->interface->dev,
0278              "Diolan U2C firmware version %u.%u\n",
0279              (unsigned int)dev->ibuffer[0],
0280              (unsigned int)dev->ibuffer[1]);
0281 }
0282 
0283 static void diolan_get_serial(struct i2c_diolan_u2c *dev)
0284 {
0285     int ret;
0286     u32 serial;
0287 
0288     ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true);
0289     if (ret >= 4) {
0290         serial = le32_to_cpu(*(u32 *)dev->ibuffer);
0291         dev_info(&dev->interface->dev,
0292              "Diolan U2C serial number %u\n", serial);
0293     }
0294 }
0295 
0296 static int diolan_init(struct i2c_diolan_u2c *dev)
0297 {
0298     int speed, ret;
0299 
0300     if (frequency >= 2 * I2C_MAX_STANDARD_MODE_FREQ) {
0301         speed = U2C_I2C_SPEED_FAST;
0302         frequency = I2C_MAX_FAST_MODE_FREQ;
0303     } else if (frequency >= I2C_MAX_STANDARD_MODE_FREQ || frequency == 0) {
0304         speed = U2C_I2C_SPEED_STD;
0305         frequency = I2C_MAX_STANDARD_MODE_FREQ;
0306     } else {
0307         speed = U2C_I2C_SPEED(frequency);
0308         if (speed > U2C_I2C_SPEED_2KHZ)
0309             speed = U2C_I2C_SPEED_2KHZ;
0310         frequency = U2C_I2C_FREQ(speed);
0311     }
0312 
0313     dev_info(&dev->interface->dev,
0314          "Diolan U2C at USB bus %03d address %03d speed %d Hz\n",
0315          dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency);
0316 
0317     diolan_flush_input(dev);
0318     diolan_fw_version(dev);
0319     diolan_get_serial(dev);
0320 
0321     /* Set I2C speed */
0322     ret = diolan_set_speed(dev, speed);
0323     if (ret < 0)
0324         return ret;
0325 
0326     /* Configure I2C clock synchronization */
0327     ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST);
0328     if (ret < 0)
0329         return ret;
0330 
0331     if (speed != U2C_I2C_SPEED_FAST)
0332         ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT);
0333 
0334     return ret;
0335 }
0336 
0337 /* i2c layer */
0338 
0339 static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
0340                int num)
0341 {
0342     struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter);
0343     struct i2c_msg *pmsg;
0344     int i, j;
0345     int ret, sret;
0346 
0347     ret = diolan_i2c_start(dev);
0348     if (ret < 0)
0349         return ret;
0350 
0351     for (i = 0; i < num; i++) {
0352         pmsg = &msgs[i];
0353         if (i) {
0354             ret = diolan_i2c_repeated_start(dev);
0355             if (ret < 0)
0356                 goto abort;
0357         }
0358         ret = diolan_i2c_put_byte_ack(dev,
0359                           i2c_8bit_addr_from_msg(pmsg));
0360         if (ret < 0)
0361             goto abort;
0362         if (pmsg->flags & I2C_M_RD) {
0363             for (j = 0; j < pmsg->len; j++) {
0364                 u8 byte;
0365                 bool ack = j < pmsg->len - 1;
0366 
0367                 /*
0368                  * Don't send NACK if this is the first byte
0369                  * of a SMBUS_BLOCK message.
0370                  */
0371                 if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN))
0372                     ack = true;
0373 
0374                 ret = diolan_i2c_get_byte_ack(dev, ack, &byte);
0375                 if (ret < 0)
0376                     goto abort;
0377                 /*
0378                  * Adjust count if first received byte is length
0379                  */
0380                 if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) {
0381                     if (byte == 0
0382                         || byte > I2C_SMBUS_BLOCK_MAX) {
0383                         ret = -EPROTO;
0384                         goto abort;
0385                     }
0386                     pmsg->len += byte;
0387                 }
0388                 pmsg->buf[j] = byte;
0389             }
0390         } else {
0391             for (j = 0; j < pmsg->len; j++) {
0392                 ret = diolan_i2c_put_byte_ack(dev,
0393                                   pmsg->buf[j]);
0394                 if (ret < 0)
0395                     goto abort;
0396             }
0397         }
0398     }
0399     ret = num;
0400 abort:
0401     sret = diolan_i2c_stop(dev);
0402     if (sret < 0 && ret >= 0)
0403         ret = sret;
0404     return ret;
0405 }
0406 
0407 /*
0408  * Return list of supported functionality.
0409  */
0410 static u32 diolan_usb_func(struct i2c_adapter *a)
0411 {
0412     return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
0413            I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
0414 }
0415 
0416 static const struct i2c_algorithm diolan_usb_algorithm = {
0417     .master_xfer = diolan_usb_xfer,
0418     .functionality = diolan_usb_func,
0419 };
0420 
0421 /* device layer */
0422 
0423 static const struct usb_device_id diolan_u2c_table[] = {
0424     { USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) },
0425     { }
0426 };
0427 
0428 MODULE_DEVICE_TABLE(usb, diolan_u2c_table);
0429 
0430 static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
0431 {
0432     usb_put_dev(dev->usb_dev);
0433     kfree(dev);
0434 }
0435 
0436 static int diolan_u2c_probe(struct usb_interface *interface,
0437                 const struct usb_device_id *id)
0438 {
0439     struct usb_host_interface *hostif = interface->cur_altsetting;
0440     struct i2c_diolan_u2c *dev;
0441     int ret;
0442 
0443     if (hostif->desc.bInterfaceNumber != 0
0444         || hostif->desc.bNumEndpoints < 2)
0445         return -ENODEV;
0446 
0447     /* allocate memory for our device state and initialize it */
0448     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0449     if (dev == NULL) {
0450         ret = -ENOMEM;
0451         goto error;
0452     }
0453     dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
0454     dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
0455 
0456     dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
0457     dev->interface = interface;
0458 
0459     /* save our data pointer in this interface device */
0460     usb_set_intfdata(interface, dev);
0461 
0462     /* setup i2c adapter description */
0463     dev->adapter.owner = THIS_MODULE;
0464     dev->adapter.class = I2C_CLASS_HWMON;
0465     dev->adapter.algo = &diolan_usb_algorithm;
0466     i2c_set_adapdata(&dev->adapter, dev);
0467     snprintf(dev->adapter.name, sizeof(dev->adapter.name),
0468          DRIVER_NAME " at bus %03d device %03d",
0469          dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
0470 
0471     dev->adapter.dev.parent = &dev->interface->dev;
0472 
0473     /* initialize diolan i2c interface */
0474     ret = diolan_init(dev);
0475     if (ret < 0) {
0476         dev_err(&interface->dev, "failed to initialize adapter\n");
0477         goto error_free;
0478     }
0479 
0480     /* and finally attach to i2c layer */
0481     ret = i2c_add_adapter(&dev->adapter);
0482     if (ret < 0)
0483         goto error_free;
0484 
0485     dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
0486 
0487     return 0;
0488 
0489 error_free:
0490     usb_set_intfdata(interface, NULL);
0491     diolan_u2c_free(dev);
0492 error:
0493     return ret;
0494 }
0495 
0496 static void diolan_u2c_disconnect(struct usb_interface *interface)
0497 {
0498     struct i2c_diolan_u2c *dev = usb_get_intfdata(interface);
0499 
0500     i2c_del_adapter(&dev->adapter);
0501     usb_set_intfdata(interface, NULL);
0502     diolan_u2c_free(dev);
0503 
0504     dev_dbg(&interface->dev, "disconnected\n");
0505 }
0506 
0507 static struct usb_driver diolan_u2c_driver = {
0508     .name = DRIVER_NAME,
0509     .probe = diolan_u2c_probe,
0510     .disconnect = diolan_u2c_disconnect,
0511     .id_table = diolan_u2c_table,
0512 };
0513 
0514 module_usb_driver(diolan_u2c_driver);
0515 
0516 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
0517 MODULE_DESCRIPTION(DRIVER_NAME " driver");
0518 MODULE_LICENSE("GPL");