1f787a6a78788f806d3555da3be283b5f13b6931
[linux-drm-fsl-dcu.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 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 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         = 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");