Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

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

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us