Merge git://git.infradead.org/users/willy/linux-nvme
[linux/fpc-iii.git] / arch / mips / mti-sead3 / sead3-i2c-drv.c
blob1f787a6a78788f806d3555da3be283b5f13b6931
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.
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>
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
36 static DEFINE_SPINLOCK(pic32_bus_lock);
38 static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
39 static void __iomem *bus_status = (void __iomem *)0xbf000060;
41 #define DELAY() udelay(100)
43 static inline unsigned int ioready(void)
45 return readl(bus_status) & 1;
48 static inline void wait_ioready(void)
50 do { } while (!ioready());
53 static inline void wait_ioclear(void)
55 do { } while (ioready());
58 static inline void check_ioclear(void)
60 if (ioready()) {
61 do {
62 (void) readl(bus_xfer);
63 DELAY();
64 } while (ioready());
68 static u32 pic32_bus_readl(u32 reg)
70 unsigned long flags;
71 u32 status, val;
73 spin_lock_irqsave(&pic32_bus_lock, flags);
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();
84 spin_unlock_irqrestore(&pic32_bus_lock, flags);
86 return val;
89 static void pic32_bus_writel(u32 val, u32 reg)
91 unsigned long flags;
92 u32 status;
94 spin_lock_irqsave(&pic32_bus_lock, flags);
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();
105 spin_unlock_irqrestore(&pic32_bus_lock, flags);
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;
116 static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap)
118 pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
121 static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap)
123 pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
126 static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap)
128 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
129 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
132 static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap)
134 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
135 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
138 static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap)
140 int i;
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);
152 return -ETIMEDOUT;
155 static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap,
156 u32 byte)
158 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
159 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
160 PIC32_I2CSTAT_IWCOL;
163 static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap)
165 pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
166 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN)
168 pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
169 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
172 static int pic32_i2c_address(struct pic32_i2c_platform_data *adap,
173 unsigned int addr, int rd)
175 pic32_i2c_idle(adap);
176 pic32_i2c_start(adap);
177 pic32_i2c_idle(adap);
179 addr <<= 1;
180 if (rd)
181 addr |= 1;
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;
192 static int sead3_i2c_read(struct pic32_i2c_platform_data *adap,
193 unsigned char *buf, unsigned int len)
195 u32 data;
196 int i;
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);
208 pic32_i2c_stop(adap);
209 pic32_i2c_idle(adap);
210 return 0;
213 static int sead3_i2c_write(struct pic32_i2c_platform_data *adap,
214 unsigned char *buf, unsigned int len)
216 int i;
217 u32 data;
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++;
231 pic32_i2c_stop(adap);
232 pic32_i2c_idle(adap);
233 return 0;
236 static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap,
237 struct i2c_msg *msgs, int num)
239 struct pic32_i2c_platform_data *adap = i2c_adap->algo_data;
240 struct i2c_msg *p;
241 int i, err = 0;
243 for (i = 0; i < num; i++) {
244 #define __BUFSIZE 80
245 int ii;
246 static char buf[__BUFSIZE];
247 char *b = buf;
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;
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);
274 /* Return the number of messages processed, or the error code. */
275 if (err == 0)
276 err = num;
278 return err;
281 static u32 sead3_pic32_platform_func(struct i2c_adapter *adap)
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
286 static const struct i2c_algorithm sead3_platform_algo = {
287 .master_xfer = sead3_pic32_platform_xfer,
288 .functionality = sead3_pic32_platform_func,
291 static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
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);
300 static int sead3_i2c_platform_probe(struct platform_device *pdev)
302 struct pic32_i2c_platform_data *priv;
303 struct resource *r;
304 int ret;
306 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
307 if (!r) {
308 ret = -ENODEV;
309 goto out;
312 priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL);
313 if (!priv) {
314 ret = -ENOMEM;
315 goto out;
318 priv->base = r->start;
319 if (!priv->base) {
320 ret = -EBUSY;
321 goto out_mem;
324 priv->xfer_timeout = 200;
325 priv->ack_timeout = 200;
326 priv->ctl_timeout = 200;
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));
334 sead3_i2c_platform_setup(priv);
336 ret = i2c_add_numbered_adapter(&priv->adap);
337 if (ret == 0) {
338 platform_set_drvdata(pdev, priv);
339 return 0;
342 out_mem:
343 kfree(priv);
344 out:
345 return ret;
348 static int sead3_i2c_platform_remove(struct platform_device *pdev)
350 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
352 platform_set_drvdata(pdev, NULL);
353 i2c_del_adapter(&priv->adap);
354 kfree(priv);
355 return 0;
358 #ifdef CONFIG_PM
359 static int sead3_i2c_platform_suspend(struct platform_device *pdev,
360 pm_message_t state)
362 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
363 return 0;
366 static int sead3_i2c_platform_resume(struct platform_device *pdev)
368 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
370 dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n");
371 sead3_i2c_platform_setup(priv);
373 return 0;
375 #else
376 #define sead3_i2c_platform_suspend NULL
377 #define sead3_i2c_platform_resume NULL
378 #endif
380 static struct platform_driver sead3_i2c_platform_driver = {
381 .driver = {
382 .name = "sead3-i2c",
383 .owner = THIS_MODULE,
385 .probe = sead3_i2c_platform_probe,
386 .remove = sead3_i2c_platform_remove,
387 .suspend = sead3_i2c_platform_suspend,
388 .resume = sead3_i2c_platform_resume,
391 static int __init sead3_i2c_platform_init(void)
393 return platform_driver_register(&sead3_i2c_platform_driver);
395 module_init(sead3_i2c_platform_init);
397 static void __exit sead3_i2c_platform_exit(void)
399 platform_driver_unregister(&sead3_i2c_platform_driver);
401 module_exit(sead3_i2c_platform_exit);
403 MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
404 MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver");
405 MODULE_LICENSE("GPL");