Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[deliverable/linux.git] / arch / mips / mti-sead3 / sead3-i2c-drv.c
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
12 #include <linux/i2c.h>
13 #include <linux/platform_device.h>
14
15 #define PIC32_I2CxCON 0x0000
16 #define PIC32_I2CCON_ON (1<<15)
17 #define PIC32_I2CCON_ACKDT (1<<5)
18 #define PIC32_I2CCON_ACKEN (1<<4)
19 #define PIC32_I2CCON_RCEN (1<<3)
20 #define PIC32_I2CCON_PEN (1<<2)
21 #define PIC32_I2CCON_RSEN (1<<1)
22 #define PIC32_I2CCON_SEN (1<<0)
23 #define PIC32_I2CxCONCLR 0x0004
24 #define PIC32_I2CxCONSET 0x0008
25 #define PIC32_I2CxSTAT 0x0010
26 #define PIC32_I2CxSTATCLR 0x0014
27 #define PIC32_I2CSTAT_ACKSTAT (1<<15)
28 #define PIC32_I2CSTAT_TRSTAT (1<<14)
29 #define PIC32_I2CSTAT_BCL (1<<10)
30 #define PIC32_I2CSTAT_IWCOL (1<<7)
31 #define PIC32_I2CSTAT_I2COV (1<<6)
32 #define PIC32_I2CxBRG 0x0040
33 #define PIC32_I2CxTRN 0x0050
34 #define PIC32_I2CxRCV 0x0060
35
36 static DEFINE_SPINLOCK(pic32_bus_lock);
37
38 static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
39 static void __iomem *bus_status = (void __iomem *)0xbf000060;
40
41 #define DELAY() udelay(100)
42
43 static inline unsigned int ioready(void)
44 {
45 return readl(bus_status) & 1;
46 }
47
48 static inline void wait_ioready(void)
49 {
50 do { } while (!ioready());
51 }
52
53 static inline void wait_ioclear(void)
54 {
55 do { } while (ioready());
56 }
57
58 static inline void check_ioclear(void)
59 {
60 if (ioready()) {
61 do {
62 (void) readl(bus_xfer);
63 DELAY();
64 } while (ioready());
65 }
66 }
67
68 static u32 pic32_bus_readl(u32 reg)
69 {
70 unsigned long flags;
71 u32 status, val;
72
73 spin_lock_irqsave(&pic32_bus_lock, flags);
74
75 check_ioclear();
76 writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer);
77 DELAY();
78 wait_ioready();
79 status = readl(bus_xfer);
80 DELAY();
81 val = readl(bus_xfer);
82 wait_ioclear();
83
84 spin_unlock_irqrestore(&pic32_bus_lock, flags);
85
86 return val;
87 }
88
89 static void pic32_bus_writel(u32 val, u32 reg)
90 {
91 unsigned long flags;
92 u32 status;
93
94 spin_lock_irqsave(&pic32_bus_lock, flags);
95
96 check_ioclear();
97 writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer);
98 DELAY();
99 writel(val, bus_xfer);
100 DELAY();
101 wait_ioready();
102 status = readl(bus_xfer);
103 wait_ioclear();
104
105 spin_unlock_irqrestore(&pic32_bus_lock, flags);
106 }
107
108 struct pic32_i2c_platform_data {
109 u32 base;
110 struct i2c_adapter adap;
111 u32 xfer_timeout;
112 u32 ack_timeout;
113 u32 ctl_timeout;
114 };
115
116 static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap)
117 {
118 pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
119 }
120
121 static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap)
122 {
123 pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
124 }
125
126 static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap)
127 {
128 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
129 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
130 }
131
132 static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap)
133 {
134 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
135 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
136 }
137
138 static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap)
139 {
140 int i;
141
142 for (i = 0; i < adap->ctl_timeout; i++) {
143 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
144 (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN |
145 PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN |
146 PIC32_I2CCON_SEN)) == 0) &&
147 ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
148 (PIC32_I2CSTAT_TRSTAT)) == 0))
149 return 0;
150 udelay(1);
151 }
152 return -ETIMEDOUT;
153 }
154
155 static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap,
156 u32 byte)
157 {
158 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
159 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
160 PIC32_I2CSTAT_IWCOL;
161 }
162
163 static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap)
164 {
165 pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
166 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN)
167 ;
168 pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
169 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
170 }
171
172 static int pic32_i2c_address(struct pic32_i2c_platform_data *adap,
173 unsigned int addr, int rd)
174 {
175 pic32_i2c_idle(adap);
176 pic32_i2c_start(adap);
177 pic32_i2c_idle(adap);
178
179 addr <<= 1;
180 if (rd)
181 addr |= 1;
182
183 if (pic32_i2c_master_write(adap, addr))
184 return -EIO;
185 pic32_i2c_idle(adap);
186 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
187 PIC32_I2CSTAT_ACKSTAT)
188 return -EIO;
189 return 0;
190 }
191
192 static int sead3_i2c_read(struct pic32_i2c_platform_data *adap,
193 unsigned char *buf, unsigned int len)
194 {
195 u32 data;
196 int i;
197
198 i = 0;
199 while (i < len) {
200 data = pic32_i2c_master_read(adap);
201 buf[i++] = data;
202 if (i < len)
203 pic32_i2c_ack(adap);
204 else
205 pic32_i2c_nack(adap);
206 }
207
208 pic32_i2c_stop(adap);
209 pic32_i2c_idle(adap);
210 return 0;
211 }
212
213 static int sead3_i2c_write(struct pic32_i2c_platform_data *adap,
214 unsigned char *buf, unsigned int len)
215 {
216 int i;
217 u32 data;
218
219 i = 0;
220 while (i < len) {
221 data = buf[i];
222 if (pic32_i2c_master_write(adap, data))
223 return -EIO;
224 pic32_i2c_idle(adap);
225 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
226 PIC32_I2CSTAT_ACKSTAT)
227 return -EIO;
228 i++;
229 }
230
231 pic32_i2c_stop(adap);
232 pic32_i2c_idle(adap);
233 return 0;
234 }
235
236 static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap,
237 struct i2c_msg *msgs, int num)
238 {
239 struct pic32_i2c_platform_data *adap = i2c_adap->algo_data;
240 struct i2c_msg *p;
241 int i, err = 0;
242
243 for (i = 0; i < num; i++) {
244 #define __BUFSIZE 80
245 int ii;
246 static char buf[__BUFSIZE];
247 char *b = buf;
248
249 p = &msgs[i];
250 b += sprintf(buf, " [%d bytes]", p->len);
251 if ((p->flags & I2C_M_RD) == 0) {
252 for (ii = 0; ii < p->len; ii++) {
253 if (b < &buf[__BUFSIZE-4]) {
254 b += sprintf(b, " %02x", p->buf[ii]);
255 } else {
256 strcat(b, "...");
257 break;
258 }
259 }
260 }
261 }
262
263 for (i = 0; !err && i < num; i++) {
264 p = &msgs[i];
265 err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD);
266 if (err || !p->len)
267 continue;
268 if (p->flags & I2C_M_RD)
269 err = sead3_i2c_read(adap, p->buf, p->len);
270 else
271 err = sead3_i2c_write(adap, p->buf, p->len);
272 }
273
274 /* Return the number of messages processed, or the error code. */
275 if (err == 0)
276 err = num;
277
278 return err;
279 }
280
281 static u32 sead3_pic32_platform_func(struct i2c_adapter *adap)
282 {
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284 }
285
286 static const struct i2c_algorithm sead3_platform_algo = {
287 .master_xfer = sead3_pic32_platform_xfer,
288 .functionality = sead3_pic32_platform_func,
289 };
290
291 static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
292 {
293 pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
294 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
295 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET);
296 pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL,
297 priv->base + PIC32_I2CxSTATCLR);
298 }
299
300 static int __devinit sead3_i2c_platform_probe(struct platform_device *pdev)
301 {
302 struct pic32_i2c_platform_data *priv;
303 struct resource *r;
304 int ret;
305
306 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
307 if (!r) {
308 ret = -ENODEV;
309 goto out;
310 }
311
312 priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL);
313 if (!priv) {
314 ret = -ENOMEM;
315 goto out;
316 }
317
318 priv->base = r->start;
319 if (!priv->base) {
320 ret = -EBUSY;
321 goto out_mem;
322 }
323
324 priv->xfer_timeout = 200;
325 priv->ack_timeout = 200;
326 priv->ctl_timeout = 200;
327
328 priv->adap.nr = pdev->id;
329 priv->adap.algo = &sead3_platform_algo;
330 priv->adap.algo_data = priv;
331 priv->adap.dev.parent = &pdev->dev;
332 strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name));
333
334 sead3_i2c_platform_setup(priv);
335
336 ret = i2c_add_numbered_adapter(&priv->adap);
337 if (ret == 0) {
338 platform_set_drvdata(pdev, priv);
339 return 0;
340 }
341
342 out_mem:
343 kfree(priv);
344 out:
345 return ret;
346 }
347
348 static int __devexit sead3_i2c_platform_remove(struct platform_device *pdev)
349 {
350 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
351
352 platform_set_drvdata(pdev, NULL);
353 i2c_del_adapter(&priv->adap);
354 kfree(priv);
355 return 0;
356 }
357
358 #ifdef CONFIG_PM
359 static int sead3_i2c_platform_suspend(struct platform_device *pdev,
360 pm_message_t state)
361 {
362 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
363 return 0;
364 }
365
366 static int sead3_i2c_platform_resume(struct platform_device *pdev)
367 {
368 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
369
370 dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n");
371 sead3_i2c_platform_setup(priv);
372
373 return 0;
374 }
375 #else
376 #define sead3_i2c_platform_suspend NULL
377 #define sead3_i2c_platform_resume NULL
378 #endif
379
380 static struct platform_driver sead3_i2c_platform_driver = {
381 .driver = {
382 .name = "sead3-i2c",
383 .owner = THIS_MODULE,
384 },
385 .probe = sead3_i2c_platform_probe,
386 .remove = __devexit_p(sead3_i2c_platform_remove),
387 .suspend = sead3_i2c_platform_suspend,
388 .resume = sead3_i2c_platform_resume,
389 };
390
391 static int __init sead3_i2c_platform_init(void)
392 {
393 return platform_driver_register(&sead3_i2c_platform_driver);
394 }
395 module_init(sead3_i2c_platform_init);
396
397 static void __exit sead3_i2c_platform_exit(void)
398 {
399 platform_driver_unregister(&sead3_i2c_platform_driver);
400 }
401 module_exit(sead3_i2c_platform_exit);
402
403 MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
404 MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver");
405 MODULE_LICENSE("GPL");
This page took 0.042192 seconds and 6 git commands to generate.