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

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

DEFINITIONS

This source file includes following definitions.
  1. poll_status
  2. xfer_read
  3. xfer_write
  4. puv3_i2c_xfer
  5. puv3_i2c_func
  6. puv3_i2c_probe
  7. puv3_i2c_remove
  8. puv3_i2c_suspend

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * I2C driver for PKUnity-v3 SoC
   4  * Code specific to PKUnity SoC and UniCore ISA
   5  *
   6  *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
   7  *      Copyright (C) 2001-2010 Guan Xuetao
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/kernel.h>
  12 #include <linux/err.h>
  13 #include <linux/slab.h>
  14 #include <linux/types.h>
  15 #include <linux/delay.h>
  16 #include <linux/i2c.h>
  17 #include <linux/clk.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/io.h>
  20 #include <mach/hardware.h>
  21 
  22 /*
  23  * Poll the i2c status register until the specified bit is set.
  24  * Returns 0 if timed out (100 msec).
  25  */
  26 static short poll_status(unsigned long bit)
  27 {
  28         int loop_cntr = 1000;
  29 
  30         if (bit & I2C_STATUS_TFNF) {
  31                 do {
  32                         udelay(10);
  33                 } while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0));
  34         } else {
  35                 /* RXRDY handler */
  36                 do {
  37                         if (readl(I2C_TAR) == I2C_TAR_EEPROM)
  38                                 msleep(20);
  39                         else
  40                                 udelay(10);
  41                 } while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0));
  42         }
  43 
  44         return (loop_cntr > 0);
  45 }
  46 
  47 static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
  48 {
  49         int i2c_reg = *buf;
  50 
  51         /* Read data */
  52         while (length--) {
  53                 if (!poll_status(I2C_STATUS_TFNF)) {
  54                         dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n");
  55                         return -ETIMEDOUT;
  56                 }
  57 
  58                 /* send addr */
  59                 writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
  60 
  61                 /* get ready to next write */
  62                 i2c_reg++;
  63 
  64                 /* send read CMD */
  65                 writel(I2C_DATACMD_READ, I2C_DATACMD);
  66 
  67                 /* wait until the Rx FIFO have available */
  68                 if (!poll_status(I2C_STATUS_RFNE)) {
  69                         dev_dbg(&adap->dev, "RXRDY timeout\n");
  70                         return -ETIMEDOUT;
  71                 }
  72 
  73                 /* read the data to buf */
  74                 *buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK);
  75                 buf++;
  76         }
  77 
  78         return 0;
  79 }
  80 
  81 static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
  82 {
  83         int i2c_reg = *buf;
  84 
  85         /* Do nothing but storing the reg_num to a static variable */
  86         if (i2c_reg == -1) {
  87                 printk(KERN_WARNING "Error i2c reg\n");
  88                 return -ETIMEDOUT;
  89         }
  90 
  91         if (length == 1)
  92                 return 0;
  93 
  94         buf++;
  95         length--;
  96         while (length--) {
  97                 /* send addr */
  98                 writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
  99 
 100                 /* send write CMD */
 101                 writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD);
 102 
 103                 /* wait until the Rx FIFO have available */
 104                 msleep(20);
 105 
 106                 /* read the data to buf */
 107                 i2c_reg++;
 108                 buf++;
 109         }
 110 
 111         return 0;
 112 }
 113 
 114 /*
 115  * Generic i2c master transfer entrypoint.
 116  *
 117  */
 118 static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg,
 119                 int num)
 120 {
 121         int i, ret;
 122         unsigned char swap;
 123 
 124         /* Disable i2c */
 125         writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
 126 
 127         /* Set the work mode and speed*/
 128         writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON);
 129 
 130         writel(pmsg->addr, I2C_TAR);
 131 
 132         /* Enable i2c */
 133         writel(I2C_ENABLE_ENABLE, I2C_ENABLE);
 134 
 135         dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num);
 136 
 137         for (i = 0; i < num; i++) {
 138                 dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
 139                         pmsg->flags & I2C_M_RD ? "read" : "writ",
 140                         pmsg->len, pmsg->len > 1 ? "s" : "",
 141                         pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
 142 
 143                 if (pmsg->len && pmsg->buf) {   /* sanity check */
 144                         if (pmsg->flags & I2C_M_RD)
 145                                 ret = xfer_read(adap, pmsg->buf, pmsg->len);
 146                         else
 147                                 ret = xfer_write(adap, pmsg->buf, pmsg->len);
 148 
 149                         if (ret)
 150                                 return ret;
 151 
 152                 }
 153                 dev_dbg(&adap->dev, "transfer complete\n");
 154                 pmsg++;         /* next message */
 155         }
 156 
 157         /* XXX: fixup be16_to_cpu in bq27x00_battery.c */
 158         if (pmsg->addr == I2C_TAR_PWIC) {
 159                 swap = pmsg->buf[0];
 160                 pmsg->buf[0] = pmsg->buf[1];
 161                 pmsg->buf[1] = swap;
 162         }
 163 
 164         return i;
 165 }
 166 
 167 /*
 168  * Return list of supported functionality.
 169  */
 170 static u32 puv3_i2c_func(struct i2c_adapter *adapter)
 171 {
 172         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 173 }
 174 
 175 static const struct i2c_algorithm puv3_i2c_algorithm = {
 176         .master_xfer    = puv3_i2c_xfer,
 177         .functionality  = puv3_i2c_func,
 178 };
 179 
 180 /*
 181  * Main initialization routine.
 182  */
 183 static int puv3_i2c_probe(struct platform_device *pdev)
 184 {
 185         struct i2c_adapter *adapter;
 186         struct resource *mem;
 187         int rc;
 188 
 189         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 190         if (!mem)
 191                 return -ENODEV;
 192 
 193         if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c"))
 194                 return -EBUSY;
 195 
 196         adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
 197         if (adapter == NULL) {
 198                 dev_err(&pdev->dev, "can't allocate interface!\n");
 199                 rc = -ENOMEM;
 200                 goto fail_nomem;
 201         }
 202         snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x",
 203                         mem->start);
 204         adapter->algo = &puv3_i2c_algorithm;
 205         adapter->class = I2C_CLASS_HWMON;
 206         adapter->dev.parent = &pdev->dev;
 207 
 208         platform_set_drvdata(pdev, adapter);
 209 
 210         adapter->nr = pdev->id;
 211         rc = i2c_add_numbered_adapter(adapter);
 212         if (rc)
 213                 goto fail_add_adapter;
 214 
 215         dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
 216         return 0;
 217 
 218 fail_add_adapter:
 219         kfree(adapter);
 220 fail_nomem:
 221         release_mem_region(mem->start, resource_size(mem));
 222 
 223         return rc;
 224 }
 225 
 226 static int puv3_i2c_remove(struct platform_device *pdev)
 227 {
 228         struct i2c_adapter *adapter = platform_get_drvdata(pdev);
 229         struct resource *mem;
 230 
 231         i2c_del_adapter(adapter);
 232 
 233         put_device(&pdev->dev);
 234 
 235         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 236         release_mem_region(mem->start, resource_size(mem));
 237 
 238         return 0;
 239 }
 240 
 241 #ifdef CONFIG_PM_SLEEP
 242 static int puv3_i2c_suspend(struct device *dev)
 243 {
 244         int poll_count;
 245         /* Disable the IIC */
 246         writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
 247         for (poll_count = 0; poll_count < 50; poll_count++) {
 248                 if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE)
 249                         udelay(25);
 250         }
 251 
 252         return 0;
 253 }
 254 
 255 static SIMPLE_DEV_PM_OPS(puv3_i2c_pm, puv3_i2c_suspend, NULL);
 256 #define PUV3_I2C_PM     (&puv3_i2c_pm)
 257 
 258 #else
 259 #define PUV3_I2C_PM     NULL
 260 #endif
 261 
 262 static struct platform_driver puv3_i2c_driver = {
 263         .probe          = puv3_i2c_probe,
 264         .remove         = puv3_i2c_remove,
 265         .driver         = {
 266                 .name   = "PKUnity-v3-I2C",
 267                 .pm     = PUV3_I2C_PM,
 268         }
 269 };
 270 
 271 module_platform_driver(puv3_i2c_driver);
 272 
 273 MODULE_DESCRIPTION("PKUnity v3 I2C driver");
 274 MODULE_LICENSE("GPL v2");
 275 MODULE_ALIAS("platform:puv3_i2c");

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