Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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                 .pm     = PUV3_I2C_PM,
274         }
275 };
276
277 module_platform_driver(puv3_i2c_driver);
278
279 MODULE_DESCRIPTION("PKUnity v3 I2C driver");
280 MODULE_LICENSE("GPL v2");
281 MODULE_ALIAS("platform:puv3_i2c");