MIPS: Whitespace cleanup.
[linux-drm-fsl-dcu.git] / arch / mips / mti-sead3 / sead3-pic32-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/delay.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/spinlock.h>
12 #include <linux/platform_device.h>
13 #include <linux/init.h>
14 #include <linux/errno.h>
15 #include <linux/i2c.h>
16 #include <linux/slab.h>
17
18 #define PIC32_I2CxCON           0x0000
19 #define PIC32_I2CxCONCLR        0x0004
20 #define PIC32_I2CxCONSET        0x0008
21 #define PIC32_I2CxCONINV        0x000C
22 #define  I2CCON_ON              (1<<15)
23 #define  I2CCON_FRZ             (1<<14)
24 #define  I2CCON_SIDL            (1<<13)
25 #define  I2CCON_SCLREL          (1<<12)
26 #define  I2CCON_STRICT          (1<<11)
27 #define  I2CCON_A10M            (1<<10)
28 #define  I2CCON_DISSLW          (1<<9)
29 #define  I2CCON_SMEN            (1<<8)
30 #define  I2CCON_GCEN            (1<<7)
31 #define  I2CCON_STREN           (1<<6)
32 #define  I2CCON_ACKDT           (1<<5)
33 #define  I2CCON_ACKEN           (1<<4)
34 #define  I2CCON_RCEN            (1<<3)
35 #define  I2CCON_PEN             (1<<2)
36 #define  I2CCON_RSEN            (1<<1)
37 #define  I2CCON_SEN             (1<<0)
38
39 #define PIC32_I2CxSTAT          0x0010
40 #define PIC32_I2CxSTATCLR       0x0014
41 #define PIC32_I2CxSTATSET       0x0018
42 #define PIC32_I2CxSTATINV       0x001C
43 #define  I2CSTAT_ACKSTAT        (1<<15)
44 #define  I2CSTAT_TRSTAT         (1<<14)
45 #define  I2CSTAT_BCL            (1<<10)
46 #define  I2CSTAT_GCSTAT         (1<<9)
47 #define  I2CSTAT_ADD10          (1<<8)
48 #define  I2CSTAT_IWCOL          (1<<7)
49 #define  I2CSTAT_I2COV          (1<<6)
50 #define  I2CSTAT_DA             (1<<5)
51 #define  I2CSTAT_P              (1<<4)
52 #define  I2CSTAT_S              (1<<3)
53 #define  I2CSTAT_RW             (1<<2)
54 #define  I2CSTAT_RBF            (1<<1)
55 #define  I2CSTAT_TBF            (1<<0)
56
57 #define PIC32_I2CxADD           0x0020
58 #define PIC32_I2CxADDCLR        0x0024
59 #define PIC32_I2CxADDSET        0x0028
60 #define PIC32_I2CxADDINV        0x002C
61 #define PIC32_I2CxMSK           0x0030
62 #define PIC32_I2CxMSKCLR        0x0034
63 #define PIC32_I2CxMSKSET        0x0038
64 #define PIC32_I2CxMSKINV        0x003C
65 #define PIC32_I2CxBRG           0x0040
66 #define PIC32_I2CxBRGCLR        0x0044
67 #define PIC32_I2CxBRGSET        0x0048
68 #define PIC32_I2CxBRGINV        0x004C
69 #define PIC32_I2CxTRN           0x0050
70 #define PIC32_I2CxTRNCLR        0x0054
71 #define PIC32_I2CxTRNSET        0x0058
72 #define PIC32_I2CxTRNINV        0x005C
73 #define PIC32_I2CxRCV           0x0060
74
75 struct i2c_platform_data {
76         u32     base;
77         struct i2c_adapter adap;
78         u32     xfer_timeout;
79         u32     ack_timeout;
80         u32     ctl_timeout;
81 };
82
83 extern u32 pic32_bus_readl(u32 reg);
84 extern void pic32_bus_writel(u32 val, u32 reg);
85
86 static inline void
87 StartI2C(struct i2c_platform_data *adap)
88 {
89         pr_debug("StartI2C\n");
90         pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
91 }
92
93 static inline void
94 StopI2C(struct i2c_platform_data *adap)
95 {
96         pr_debug("StopI2C\n");
97         pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
98 }
99
100 static inline void
101 AckI2C(struct i2c_platform_data *adap)
102 {
103         pr_debug("AckI2C\n");
104         pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
105         pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
106 }
107
108 static inline void
109 NotAckI2C(struct i2c_platform_data *adap)
110 {
111         pr_debug("NakI2C\n");
112         pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
113         pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
114 }
115
116 static inline int
117 IdleI2C(struct i2c_platform_data *adap)
118 {
119         int i;
120
121         pr_debug("IdleI2C\n");
122         for (i = 0; i < adap->ctl_timeout; i++) {
123                 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
124                      (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN |
125                       I2CCON_SEN)) == 0) &&
126                     ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
127                      (I2CSTAT_TRSTAT)) == 0))
128                         return 0;
129                 udelay(1);
130         }
131         return -ETIMEDOUT;
132 }
133
134 static inline u32
135 MasterWriteI2C(struct i2c_platform_data *adap, u32 byte)
136 {
137         pr_debug("MasterWriteI2C\n");
138
139         pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
140
141         return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL;
142 }
143
144 static inline u32
145 MasterReadI2C(struct i2c_platform_data *adap)
146 {
147         pr_debug("MasterReadI2C\n");
148
149         pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
150
151         while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN)
152                 ;
153
154         pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
155
156         return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
157 }
158
159 static int
160 do_address(struct i2c_platform_data *adap, unsigned int addr, int rd)
161 {
162         pr_debug("doaddress\n");
163
164         IdleI2C(adap);
165         StartI2C(adap);
166         IdleI2C(adap);
167
168         addr <<= 1;
169         if (rd)
170                 addr |= 1;
171
172         if (MasterWriteI2C(adap, addr))
173                 return -EIO;
174         IdleI2C(adap);
175         if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT)
176                 return -EIO;
177         return 0;
178 }
179
180 static int
181 i2c_read(struct i2c_platform_data *adap, unsigned char *buf,
182                     unsigned int len)
183 {
184         int     i;
185         u32     data;
186
187         pr_debug("i2c_read\n");
188
189         i = 0;
190         while (i < len) {
191                 data = MasterReadI2C(adap);
192                 buf[i++] = data;
193                 if (i < len)
194                         AckI2C(adap);
195                 else
196                         NotAckI2C(adap);
197         }
198
199         StopI2C(adap);
200         IdleI2C(adap);
201         return 0;
202 }
203
204 static int
205 i2c_write(struct i2c_platform_data *adap, unsigned char *buf,
206                      unsigned int len)
207 {
208         int     i;
209         u32     data;
210
211         pr_debug("i2c_write\n");
212
213         i = 0;
214         while (i < len) {
215                 data = buf[i];
216                 if (MasterWriteI2C(adap, data))
217                         return -EIO;
218                 IdleI2C(adap);
219                 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
220                     I2CSTAT_ACKSTAT)
221                         return -EIO;
222                 i++;
223         }
224
225         StopI2C(adap);
226         IdleI2C(adap);
227         return 0;
228 }
229
230 static int
231 platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
232 {
233         struct i2c_platform_data *adap = i2c_adap->algo_data;
234         struct i2c_msg *p;
235         int i, err = 0;
236
237         pr_debug("platform_xfer\n");
238         for (i = 0; i < num; i++) {
239 #define __BUFSIZE 80
240                 int ii;
241                 static char buf[__BUFSIZE];
242                 char *b = buf;
243
244                 p = &msgs[i];
245                 b += sprintf(buf, " [%d bytes]", p->len);
246                 if ((p->flags & I2C_M_RD) == 0) {
247                         for (ii = 0; ii < p->len; ii++) {
248                                 if (b < &buf[__BUFSIZE-4]) {
249                                         b += sprintf(b, " %02x", p->buf[ii]);
250                                 } else {
251                                         strcat(b, "...");
252                                         break;
253                                 }
254                         }
255                 }
256                 pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr,
257                          (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf);
258         }
259
260
261         for (i = 0; !err && i < num; i++) {
262                 p = &msgs[i];
263                 err = do_address(adap, p->addr, p->flags & I2C_M_RD);
264                 if (err || !p->len)
265                         continue;
266                 if (p->flags & I2C_M_RD)
267                         err = i2c_read(adap, p->buf, p->len);
268                 else
269                         err = i2c_write(adap, p->buf, p->len);
270         }
271
272         /* Return the number of messages processed, or the error code. */
273         if (err == 0)
274                 err = num;
275
276         return err;
277 }
278
279 static u32
280 platform_func(struct i2c_adapter *adap)
281 {
282         pr_debug("platform_algo\n");
283         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284 }
285
286 static const struct i2c_algorithm platform_algo = {
287         .master_xfer    = platform_xfer,
288         .functionality  = platform_func,
289 };
290
291 static void i2c_platform_setup(struct i2c_platform_data *priv)
292 {
293         pr_debug("i2c_platform_setup\n");
294
295         pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
296         pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
297         pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET);
298         pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL),
299                 (priv->base + PIC32_I2CxSTATCLR));
300 }
301
302 static void i2c_platform_disable(struct i2c_platform_data *priv)
303 {
304         pr_debug("i2c_platform_disable\n");
305 }
306
307 static int i2c_platform_probe(struct platform_device *pdev)
308 {
309         struct i2c_platform_data *priv;
310         struct resource *r;
311         int ret;
312
313         pr_debug("i2c_platform_probe\n");
314         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
315         if (!r) {
316                 ret = -ENODEV;
317                 goto out;
318         }
319
320         priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL);
321         if (!priv) {
322                 ret = -ENOMEM;
323                 goto out;
324         }
325
326         /* FIXME: need to allocate resource in PIC32 space */
327 #if 0
328         priv->base = bus_request_region(r->start, resource_size(r),
329                                           pdev->name);
330 #else
331         priv->base = r->start;
332 #endif
333         if (!priv->base) {
334                 ret = -EBUSY;
335                 goto out_mem;
336         }
337
338         priv->xfer_timeout = 200;
339         priv->ack_timeout = 200;
340         priv->ctl_timeout = 200;
341
342         priv->adap.nr = pdev->id;
343         priv->adap.algo = &platform_algo;
344         priv->adap.algo_data = priv;
345         priv->adap.dev.parent = &pdev->dev;
346         strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name));
347
348         i2c_platform_setup(priv);
349
350         ret = i2c_add_numbered_adapter(&priv->adap);
351         if (ret == 0) {
352                 platform_set_drvdata(pdev, priv);
353                 return 0;
354         }
355
356         i2c_platform_disable(priv);
357
358 out_mem:
359         kfree(priv);
360 out:
361         return ret;
362 }
363
364 static int i2c_platform_remove(struct platform_device *pdev)
365 {
366         struct i2c_platform_data *priv = platform_get_drvdata(pdev);
367
368         pr_debug("i2c_platform_remove\n");
369         platform_set_drvdata(pdev, NULL);
370         i2c_del_adapter(&priv->adap);
371         i2c_platform_disable(priv);
372         kfree(priv);
373         return 0;
374 }
375
376 #ifdef CONFIG_PM
377 static int
378 i2c_platform_suspend(struct platform_device *pdev, pm_message_t state)
379 {
380         struct i2c_platform_data *priv = platform_get_drvdata(pdev);
381
382         dev_dbg(&pdev->dev, "i2c_platform_disable\n");
383         i2c_platform_disable(priv);
384
385         return 0;
386 }
387
388 static int
389 i2c_platform_resume(struct platform_device *pdev)
390 {
391         struct i2c_platform_data *priv = platform_get_drvdata(pdev);
392
393         dev_dbg(&pdev->dev, "i2c_platform_setup\n");
394         i2c_platform_setup(priv);
395
396         return 0;
397 }
398 #else
399 #define i2c_platform_suspend    NULL
400 #define i2c_platform_resume     NULL
401 #endif
402
403 static struct platform_driver i2c_platform_driver = {
404         .driver = {
405                 .name   = "i2c_pic32",
406                 .owner  = THIS_MODULE,
407         },
408         .probe          = i2c_platform_probe,
409         .remove         = i2c_platform_remove,
410         .suspend        = i2c_platform_suspend,
411         .resume         = i2c_platform_resume,
412 };
413
414 static int __init
415 i2c_platform_init(void)
416 {
417         pr_debug("i2c_platform_init\n");
418         return platform_driver_register(&i2c_platform_driver);
419 }
420
421 static void __exit
422 i2c_platform_exit(void)
423 {
424         pr_debug("i2c_platform_exit\n");
425         platform_driver_unregister(&i2c_platform_driver);
426 }
427
428 MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
429 MODULE_DESCRIPTION("PIC32 I2C driver");
430 MODULE_LICENSE("GPL");
431
432 module_init(i2c_platform_init);
433 module_exit(i2c_platform_exit);