root/drivers/i2c/busses/i2c-dln2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dln2_i2c_enable
  2. dln2_i2c_write
  3. dln2_i2c_read
  4. dln2_i2c_xfer
  5. dln2_i2c_func
  6. dln2_i2c_probe
  7. dln2_i2c_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Driver for the Diolan DLN-2 USB-I2C adapter
   4  *
   5  * Copyright (c) 2014 Intel Corporation
   6  *
   7  * Derived from:
   8  *  i2c-diolan-u2c.c
   9  *  Copyright (c) 2010-2011 Ericsson AB
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/types.h>
  15 #include <linux/slab.h>
  16 #include <linux/i2c.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/mfd/dln2.h>
  19 #include <linux/acpi.h>
  20 
  21 #define DLN2_I2C_MODULE_ID              0x03
  22 #define DLN2_I2C_CMD(cmd)               DLN2_CMD(cmd, DLN2_I2C_MODULE_ID)
  23 
  24 /* I2C commands */
  25 #define DLN2_I2C_GET_PORT_COUNT         DLN2_I2C_CMD(0x00)
  26 #define DLN2_I2C_ENABLE                 DLN2_I2C_CMD(0x01)
  27 #define DLN2_I2C_DISABLE                DLN2_I2C_CMD(0x02)
  28 #define DLN2_I2C_IS_ENABLED             DLN2_I2C_CMD(0x03)
  29 #define DLN2_I2C_WRITE                  DLN2_I2C_CMD(0x06)
  30 #define DLN2_I2C_READ                   DLN2_I2C_CMD(0x07)
  31 #define DLN2_I2C_SCAN_DEVICES           DLN2_I2C_CMD(0x08)
  32 #define DLN2_I2C_PULLUP_ENABLE          DLN2_I2C_CMD(0x09)
  33 #define DLN2_I2C_PULLUP_DISABLE         DLN2_I2C_CMD(0x0A)
  34 #define DLN2_I2C_PULLUP_IS_ENABLED      DLN2_I2C_CMD(0x0B)
  35 #define DLN2_I2C_TRANSFER               DLN2_I2C_CMD(0x0C)
  36 #define DLN2_I2C_SET_MAX_REPLY_COUNT    DLN2_I2C_CMD(0x0D)
  37 #define DLN2_I2C_GET_MAX_REPLY_COUNT    DLN2_I2C_CMD(0x0E)
  38 
  39 #define DLN2_I2C_MAX_XFER_SIZE          256
  40 #define DLN2_I2C_BUF_SIZE               (DLN2_I2C_MAX_XFER_SIZE + 16)
  41 
  42 struct dln2_i2c {
  43         struct platform_device *pdev;
  44         struct i2c_adapter adapter;
  45         u8 port;
  46         /*
  47          * Buffer to hold the packet for read or write transfers. One is enough
  48          * since we can't have multiple transfers in parallel on the i2c bus.
  49          */
  50         void *buf;
  51 };
  52 
  53 static int dln2_i2c_enable(struct dln2_i2c *dln2, bool enable)
  54 {
  55         u16 cmd;
  56         struct {
  57                 u8 port;
  58         } tx;
  59 
  60         tx.port = dln2->port;
  61 
  62         if (enable)
  63                 cmd = DLN2_I2C_ENABLE;
  64         else
  65                 cmd = DLN2_I2C_DISABLE;
  66 
  67         return dln2_transfer_tx(dln2->pdev, cmd, &tx, sizeof(tx));
  68 }
  69 
  70 static int dln2_i2c_write(struct dln2_i2c *dln2, u8 addr,
  71                           u8 *data, u16 data_len)
  72 {
  73         int ret;
  74         struct {
  75                 u8 port;
  76                 u8 addr;
  77                 u8 mem_addr_len;
  78                 __le32 mem_addr;
  79                 __le16 buf_len;
  80                 u8 buf[DLN2_I2C_MAX_XFER_SIZE];
  81         } __packed *tx = dln2->buf;
  82         unsigned len;
  83 
  84         BUILD_BUG_ON(sizeof(*tx) > DLN2_I2C_BUF_SIZE);
  85 
  86         tx->port = dln2->port;
  87         tx->addr = addr;
  88         tx->mem_addr_len = 0;
  89         tx->mem_addr = 0;
  90         tx->buf_len = cpu_to_le16(data_len);
  91         memcpy(tx->buf, data, data_len);
  92 
  93         len = sizeof(*tx) + data_len - DLN2_I2C_MAX_XFER_SIZE;
  94         ret = dln2_transfer_tx(dln2->pdev, DLN2_I2C_WRITE, tx, len);
  95         if (ret < 0)
  96                 return ret;
  97 
  98         return data_len;
  99 }
 100 
 101 static int dln2_i2c_read(struct dln2_i2c *dln2, u16 addr, u8 *data,
 102                          u16 data_len)
 103 {
 104         int ret;
 105         struct {
 106                 u8 port;
 107                 u8 addr;
 108                 u8 mem_addr_len;
 109                 __le32 mem_addr;
 110                 __le16 buf_len;
 111         } __packed tx;
 112         struct {
 113                 __le16 buf_len;
 114                 u8 buf[DLN2_I2C_MAX_XFER_SIZE];
 115         } __packed *rx = dln2->buf;
 116         unsigned rx_len = sizeof(*rx);
 117 
 118         BUILD_BUG_ON(sizeof(*rx) > DLN2_I2C_BUF_SIZE);
 119 
 120         tx.port = dln2->port;
 121         tx.addr = addr;
 122         tx.mem_addr_len = 0;
 123         tx.mem_addr = 0;
 124         tx.buf_len = cpu_to_le16(data_len);
 125 
 126         ret = dln2_transfer(dln2->pdev, DLN2_I2C_READ, &tx, sizeof(tx),
 127                             rx, &rx_len);
 128         if (ret < 0)
 129                 return ret;
 130         if (rx_len < sizeof(rx->buf_len) + data_len)
 131                 return -EPROTO;
 132         if (le16_to_cpu(rx->buf_len) != data_len)
 133                 return -EPROTO;
 134 
 135         memcpy(data, rx->buf, data_len);
 136 
 137         return data_len;
 138 }
 139 
 140 static int dln2_i2c_xfer(struct i2c_adapter *adapter,
 141                          struct i2c_msg *msgs, int num)
 142 {
 143         struct dln2_i2c *dln2 = i2c_get_adapdata(adapter);
 144         struct i2c_msg *pmsg;
 145         int i;
 146 
 147         for (i = 0; i < num; i++) {
 148                 int ret;
 149 
 150                 pmsg = &msgs[i];
 151 
 152                 if (pmsg->flags & I2C_M_RD) {
 153                         ret = dln2_i2c_read(dln2, pmsg->addr, pmsg->buf,
 154                                             pmsg->len);
 155                         if (ret < 0)
 156                                 return ret;
 157 
 158                         pmsg->len = ret;
 159                 } else {
 160                         ret = dln2_i2c_write(dln2, pmsg->addr, pmsg->buf,
 161                                              pmsg->len);
 162                         if (ret != pmsg->len)
 163                                 return -EPROTO;
 164                 }
 165         }
 166 
 167         return num;
 168 }
 169 
 170 static u32 dln2_i2c_func(struct i2c_adapter *a)
 171 {
 172         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
 173                 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
 174                 I2C_FUNC_SMBUS_I2C_BLOCK;
 175 }
 176 
 177 static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
 178         .master_xfer = dln2_i2c_xfer,
 179         .functionality = dln2_i2c_func,
 180 };
 181 
 182 static const struct i2c_adapter_quirks dln2_i2c_quirks = {
 183         .max_read_len = DLN2_I2C_MAX_XFER_SIZE,
 184         .max_write_len = DLN2_I2C_MAX_XFER_SIZE,
 185 };
 186 
 187 static int dln2_i2c_probe(struct platform_device *pdev)
 188 {
 189         int ret;
 190         struct dln2_i2c *dln2;
 191         struct device *dev = &pdev->dev;
 192         struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 193 
 194         dln2 = devm_kzalloc(dev, sizeof(*dln2), GFP_KERNEL);
 195         if (!dln2)
 196                 return -ENOMEM;
 197 
 198         dln2->buf = devm_kmalloc(dev, DLN2_I2C_BUF_SIZE, GFP_KERNEL);
 199         if (!dln2->buf)
 200                 return -ENOMEM;
 201 
 202         dln2->pdev = pdev;
 203         dln2->port = pdata->port;
 204 
 205         /* setup i2c adapter description */
 206         dln2->adapter.owner = THIS_MODULE;
 207         dln2->adapter.class = I2C_CLASS_HWMON;
 208         dln2->adapter.algo = &dln2_i2c_usb_algorithm;
 209         dln2->adapter.quirks = &dln2_i2c_quirks;
 210         dln2->adapter.dev.parent = dev;
 211         ACPI_COMPANION_SET(&dln2->adapter.dev, ACPI_COMPANION(&pdev->dev));
 212         dln2->adapter.dev.of_node = dev->of_node;
 213         i2c_set_adapdata(&dln2->adapter, dln2);
 214         snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
 215                  "dln2-i2c", dev_name(pdev->dev.parent), dln2->port);
 216 
 217         platform_set_drvdata(pdev, dln2);
 218 
 219         /* initialize the i2c interface */
 220         ret = dln2_i2c_enable(dln2, true);
 221         if (ret < 0) {
 222                 dev_err(dev, "failed to initialize adapter: %d\n", ret);
 223                 return ret;
 224         }
 225 
 226         /* and finally attach to i2c layer */
 227         ret = i2c_add_adapter(&dln2->adapter);
 228         if (ret < 0)
 229                 goto out_disable;
 230 
 231         return 0;
 232 
 233 out_disable:
 234         dln2_i2c_enable(dln2, false);
 235 
 236         return ret;
 237 }
 238 
 239 static int dln2_i2c_remove(struct platform_device *pdev)
 240 {
 241         struct dln2_i2c *dln2 = platform_get_drvdata(pdev);
 242 
 243         i2c_del_adapter(&dln2->adapter);
 244         dln2_i2c_enable(dln2, false);
 245 
 246         return 0;
 247 }
 248 
 249 static struct platform_driver dln2_i2c_driver = {
 250         .driver.name    = "dln2-i2c",
 251         .probe          = dln2_i2c_probe,
 252         .remove         = dln2_i2c_remove,
 253 };
 254 
 255 module_platform_driver(dln2_i2c_driver);
 256 
 257 MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>");
 258 MODULE_DESCRIPTION("Driver for the Diolan DLN2 I2C master interface");
 259 MODULE_LICENSE("GPL v2");
 260 MODULE_ALIAS("platform:dln2-i2c");

/* [<][>][^][v][top][bottom][index][help] */