malta: remove 2.6.39 and 3.0 support
[openwrt.git] / target / linux / xburst / patches-2.6.36 / 050-i2c.patch
1 From e5d89837a365a810b3cc5ce58d273a7c49029f36 Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sun, 5 Sep 2010 03:19:10 +0200
4 Subject: [PATCH] i2c: Add i2c driver for JZ47XX SoCs
5
6 This patch adds a driver for the i2c controller found in Ingenic JZ47XX based
7 SoCs.
8
9 Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
10 ---
11  drivers/i2c/busses/Kconfig      |   10 +
12  drivers/i2c/busses/Makefile     |    1 +
13  drivers/i2c/busses/i2c-jz47xx.c |  424 +++++++++++++++++++++++++++++++++++++++
14  3 files changed, 435 insertions(+), 0 deletions(-)
15  create mode 100644 drivers/i2c/busses/i2c-jz47xx.c
16
17 --- a/drivers/i2c/busses/Kconfig
18 +++ b/drivers/i2c/busses/Kconfig
19 @@ -420,6 +420,16 @@ config I2C_IXP2000
20           This driver is deprecated and will be dropped soon. Use i2c-gpio
21           instead.
22  
23 +config I2C_JZ47XX
24 +       tristate "JZ4740 I2C Interface"
25 +       depends on MACH_JZ4740
26 +       help
27 +         Say Y here if you want support for the I2C controller found on Ingenic
28 +         JZ47XX based SoCs.
29 +
30 +         This driver can also be built as a module. If so, the module will be
31 +         called i2c-jz47xx.
32 +
33  config I2C_MPC
34         tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
35         depends on PPC32
36 --- a/drivers/i2c/busses/Makefile
37 +++ b/drivers/i2c/busses/Makefile
38 @@ -40,6 +40,7 @@ obj-$(CONFIG_I2C_IBM_IIC)     += i2c-ibm_iic
39  obj-$(CONFIG_I2C_IMX)          += i2c-imx.o
40  obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
41  obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
42 +obj-$(CONFIG_I2C_JZ47XX)       += i2c-jz47xx.o
43  obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
44  obj-$(CONFIG_I2C_MV64XXX)      += i2c-mv64xxx.o
45  obj-$(CONFIG_I2C_NOMADIK)      += i2c-nomadik.o
46 --- /dev/null
47 +++ b/drivers/i2c/busses/i2c-jz47xx.c
48 @@ -0,0 +1,424 @@
49 +
50 +#include <linux/init.h>
51 +#include <linux/kernel.h>
52 +#include <linux/module.h>
53 +#include <linux/err.h>
54 +#include <linux/clk.h>
55 +#include <linux/platform_device.h>
56 +#include <linux/i2c.h>
57 +#include <linux/slab.h>
58 +#include <linux/interrupt.h>
59 +
60 +#include <linux/gpio.h>
61 +#include <linux/delay.h>
62 +
63 +#define JZ47XX_REG_I2C_DATA    0x00
64 +#define JZ47XX_REG_I2C_CTRL    0x04
65 +#define JZ47XX_REG_I2C_STATUS  0x08
66 +#define JZ47XX_REG_I2C_CLOCK   0x0C
67 +
68 +#define JZ47XX_I2C_STATUS_FIFO_FULL    BIT(4)
69 +#define JZ47XX_I2C_STATUS_BUSY         BIT(3)
70 +#define JZ47XX_I2C_STATUS_TEND         BIT(2)
71 +#define JZ47XX_I2C_STATUS_DATA_VALID   BIT(1)
72 +#define JZ47XX_I2C_STATUS_NACK         BIT(0)
73 +
74 +#define JZ47XX_I2C_CTRL_IRQ_ENABLE     BIT(4)
75 +#define JZ47XX_I2C_CTRL_START          BIT(3)
76 +#define JZ47XX_I2C_CTRL_STOP           BIT(2)
77 +#define JZ47XX_I2C_CTRL_NACK           BIT(1)
78 +#define JZ47XX_I2C_CTRL_ENABLE         BIT(0)
79 +
80 +struct jz47xx_i2c {
81 +       struct resource *mem;
82 +       void __iomem *base;
83 +       int irq;
84 +       struct clk *clk;
85 +
86 +       struct i2c_adapter adapter;
87 +
88 +       wait_queue_head_t wait_queue;
89 +};
90 +
91 +static inline struct jz47xx_i2c *adapter_to_jz47xx_i2c(struct i2c_adapter *adap)
92 +{
93 +       return container_of(adap, struct jz47xx_i2c, adapter);
94 +}
95 +
96 +static inline void jz47xx_i2c_set_ctrl(struct jz47xx_i2c *jz47xx_i2c,
97 +       uint8_t mask, uint8_t value)
98 +{
99 +       uint8_t ctrl;
100 +       ctrl = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
101 +       ctrl &= ~mask;
102 +       ctrl |= value;
103 +       printk("ctrl: %x\n", ctrl);
104 +       writeb(ctrl, jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
105 +}
106 +
107 +static irqreturn_t jz47xx_i2c_irq_handler(int irq, void *devid)
108 +{
109 +       struct jz47xx_i2c *jz47xx_i2c = devid;
110 +
111 +       printk("IRQ\n");
112 +
113 +       wake_up(&jz47xx_i2c->wait_queue);
114 +
115 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE, 0);
116 +
117 +       return IRQ_HANDLED;
118 +}
119 +
120 +static inline void jz47xx_i2c_set_data_valid(struct jz47xx_i2c *jz47xx_i2c,
121 +       bool valid)
122 +{
123 +       uint8_t val;
124 +       val = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
125 +       if (valid)
126 +               val |= JZ47XX_I2C_STATUS_DATA_VALID;
127 +       else
128 +               val &= ~JZ47XX_I2C_STATUS_DATA_VALID;
129 +       writeb(val, jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
130 +}
131 +
132 +static int jz47xx_i2c_test_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t mask, uint8_t value)
133 +{
134 +       uint8_t status;
135 +
136 +       mask |= JZ47XX_I2C_STATUS_NACK;
137 +       value |= JZ47XX_I2C_STATUS_NACK;
138 +
139 +       status = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
140 +       printk("status: %x %x %x %x\n", status, mask, value, (status & mask) ^
141 +       value);
142 +       if (((status & mask) ^ value) == mask) {
143 +               jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE,
144 +                       JZ47XX_I2C_CTRL_IRQ_ENABLE);
145 +               return 0;
146 +       }
147 +       return 1;
148 +}
149 +
150 +static int jz47xx_i2c_wait_event_or_nack(struct jz47xx_i2c *jz47xx_i2c, uint8_t
151 +mask, uint8_t value)
152 +{
153 +       int ret;
154 +
155 +       ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
156 +               jz47xx_i2c_test_event(jz47xx_i2c, mask, value), 30 * HZ);
157 +
158 +/*     while (!jz47xx_i2c_test_event(jz47xx_i2c, mask, value));
159 +
160 +       ret = 1;*/
161 +
162 +       printk("wait event or nack: %d %x\n", ret, readb(jz47xx_i2c->base +
163 +       JZ47XX_REG_I2C_STATUS));
164 +
165 +       if (ret == 0)
166 +               ret = -ETIMEDOUT;
167 +       else if(ret > 0) {
168 +               if (readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS) & JZ47XX_I2C_STATUS_NACK)
169 +                       ret = -EIO;
170 +               else
171 +                       ret = 0;
172 +       }
173 +
174 +       return ret;
175 +}
176 +
177 +static int jz47xx_i2c_wait_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t event)
178 +{
179 +       int ret;
180 +
181 +       ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
182 +               jz47xx_i2c_test_event(jz47xx_i2c, event, event), 30 * HZ);
183 +
184 +       if (ret == 0)
185 +               ret = -ETIMEDOUT;
186 +       else if(ret > 0)
187 +               ret = 0;
188 +
189 +       return ret;
190 +}
191 +
192 +
193 +static int jz47xx_i2c_write_msg(struct jz47xx_i2c *jz47xx_i2c,
194 +       struct i2c_msg *msg)
195 +{
196 +       int ret;
197 +       int i;
198 +
199 +       printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
200 +       for (i = 0; i < msg->len; ++i) {
201 +               writeb(msg->buf[i], jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
202 +               jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
203 +               ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
204 +                       JZ47XX_I2C_STATUS_DATA_VALID, 0);
205 +               if (ret)
206 +                       break;
207 +       }
208 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
209 +               JZ47XX_I2C_CTRL_STOP);
210 +
211 +       if (!ret)
212 +               ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c, JZ47XX_I2C_STATUS_TEND,
213 +                       JZ47XX_I2C_STATUS_TEND);
214 +
215 +       return ret;
216 +}
217 +
218 +static int jz47xx_i2c_read_msg(struct jz47xx_i2c *jz47xx_i2c,
219 +       struct i2c_msg *msg)
220 +{
221 +       int i;
222 +       int ret;
223 +       printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
224 +
225 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
226 +               msg->len == 1 ? JZ47XX_I2C_CTRL_NACK : 0);
227 +
228 +       for (i = 0; i < msg->len; ++i) {
229 +               ret = jz47xx_i2c_wait_event(jz47xx_i2c, JZ47XX_I2C_STATUS_DATA_VALID);
230 +               if (ret) {
231 +                       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
232 +                               JZ47XX_I2C_CTRL_NACK);
233 +                       break;
234 +               }
235 +
236 +               if (i == msg->len - 2) {
237 +                       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
238 +                               JZ47XX_I2C_CTRL_NACK);
239 +               }
240 +
241 +               msg->buf[i] = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
242 +               printk("read: %x\n", msg->buf[i]);
243 +               jz47xx_i2c_set_data_valid(jz47xx_i2c, false);
244 +       }
245 +
246 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
247 +               JZ47XX_I2C_CTRL_STOP);
248 +
249 +       return ret;
250 +}
251 +
252 +static int jz47xx_i2c_xfer_msg(struct jz47xx_i2c *jz47xx_i2c,
253 +       struct i2c_msg *msg)
254 +{
255 +       uint8_t addr;
256 +       int ret;
257 +
258 +       addr = msg->addr << 1;
259 +       if (msg->flags & I2C_M_RD)
260 +               addr |= 1;
261 +
262 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_START,
263 +               JZ47XX_I2C_CTRL_START);
264 +       writeb(addr, jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
265 +       jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
266 +
267 +       if (msg->flags & I2C_M_RD) {
268 +               printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
269 +               ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
270 +               JZ47XX_I2C_STATUS_TEND, JZ47XX_I2C_STATUS_TEND);
271 +               if (!ret)
272 +                       ret = jz47xx_i2c_read_msg(jz47xx_i2c, msg);
273 +       } else {
274 +               printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
275 +               ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
276 +                   JZ47XX_I2C_STATUS_DATA_VALID, 0);
277 +               if (!ret)
278 +                       ret = jz47xx_i2c_write_msg(jz47xx_i2c, msg);
279 +       }
280 +
281 +       return ret;
282 +}
283 +
284 +static int jz47xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int
285 +num)
286 +{
287 +       struct jz47xx_i2c *jz47xx_i2c = adapter_to_jz47xx_i2c(adap);
288 +       int ret = 0;
289 +       int i;
290 +       int mask = JZ47XX_I2C_CTRL_ENABLE;
291 +
292 +       printk("xfer: %d %x\n", num, readb(jz47xx_i2c->base +
293 +       JZ47XX_REG_I2C_STATUS));
294 +
295 +       clk_enable(jz47xx_i2c->clk);
296 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, mask);
297 +
298 +       for (i = 0; i < num; ++i) {
299 +               ret = jz47xx_i2c_xfer_msg(jz47xx_i2c, &msgs[i]);
300 +               if (ret)
301 +                       break;
302 +       }
303 +
304 +       jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, 0);
305 +       clk_disable(jz47xx_i2c->clk);
306 +
307 +       printk("xfer ret: %d\n", ret);
308 +
309 +       return ret;
310 +}
311 +
312 +static u32 jz47xx_i2c_functionality(struct i2c_adapter *adap)
313 +{
314 +       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
315 +}
316 +
317 +static const struct i2c_algorithm jz47xx_i2c_algorithm = {
318 +       .master_xfer = jz47xx_i2c_xfer,
319 +       .functionality = jz47xx_i2c_functionality,
320 +};
321 +
322 +const static struct jz_gpio_bulk_request jz47xx_i2c_pins[] = {
323 +       JZ_GPIO_BULK_PIN(I2C_SDA),
324 +       JZ_GPIO_BULK_PIN(I2C_SCK),
325 +};
326 +
327 +static int __devinit jz47xx_i2c_probe(struct platform_device *pdev)
328 +{
329 +       struct jz47xx_i2c *jz47xx_i2c;
330 +       struct resource *mem;
331 +       void __iomem *base;
332 +       struct clk *clk;
333 +       int irq;
334 +       int ret;
335 +
336 +       irq = platform_get_irq(pdev, 0);
337 +       if (!irq) {
338 +               dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
339 +               return irq;
340 +       }
341 +
342 +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
343 +       if (!mem) {
344 +               dev_err(&pdev->dev, "Failed to get iomem region\n");
345 +               return -ENXIO;
346 +       }
347 +
348 +       mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
349 +       if (!mem) {
350 +               dev_err(&pdev->dev, "Failed to request iomem region\n");
351 +               return -EBUSY;
352 +       }
353 +
354 +       base = ioremap(mem->start, resource_size(mem));
355 +       if (!base) {
356 +               dev_err(&pdev->dev, "Failed to ioremap iomem\n");
357 +               ret = -EBUSY;
358 +               goto err_release_mem_region;
359 +       }
360 +
361 +       clk = clk_get(&pdev->dev, "i2c");
362 +       if (IS_ERR(clk)) {
363 +               ret = PTR_ERR(clk);
364 +               goto err_iounmap;
365 +       }
366 +
367 +       jz47xx_i2c = kzalloc(sizeof(*jz47xx_i2c), GFP_KERNEL);
368 +       if (!jz47xx_i2c) {
369 +               ret = -ENOMEM;
370 +               goto err_clk_put;
371 +       }
372 +
373 +       jz47xx_i2c->adapter.owner = THIS_MODULE;
374 +       jz47xx_i2c->adapter.algo = &jz47xx_i2c_algorithm;
375 +       jz47xx_i2c->adapter.dev.parent = &pdev->dev;
376 +       jz47xx_i2c->adapter.nr = pdev->id < 0 ?: 0;
377 +       strcpy(jz47xx_i2c->adapter.name, pdev->name);
378 +
379 +       jz47xx_i2c->mem = mem;
380 +       jz47xx_i2c->base = base;
381 +       jz47xx_i2c->clk = clk;
382 +       jz47xx_i2c->irq = irq;
383 +
384 +       init_waitqueue_head(&jz47xx_i2c->wait_queue);
385 +
386 +       ret = request_irq(irq, jz47xx_i2c_irq_handler, 0, pdev->name, jz47xx_i2c);
387 +       if (ret) {
388 +               dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
389 +               goto err_free;
390 +       }
391 +
392 +    ret = jz_gpio_bulk_request(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
393 +       if (ret) {
394 +               dev_err(&pdev->dev, "Failed to request i2c pins: %d\n", ret);
395 +               goto err_free_irq;
396 +       }
397 +
398 +       writew(0x10, jz47xx_i2c->base + JZ47XX_REG_I2C_CLOCK);
399 +
400 +       ret = i2c_add_numbered_adapter(&jz47xx_i2c->adapter);
401 +       if (ret) {
402 +               dev_err(&pdev->dev, "Failed to add i2c adapter: %d\n", ret);
403 +               goto err_free_gpios;
404 +       }
405 +
406 +       platform_set_drvdata(pdev, jz47xx_i2c);
407 +
408 +       printk("JZ4740 I2C\n");
409 +
410 +       return 0;
411 +
412 +err_free_gpios:
413 +       jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
414 +err_free_irq:
415 +       free_irq(irq, jz47xx_i2c);
416 +err_free:
417 +       kfree(jz47xx_i2c);
418 +err_clk_put:
419 +       clk_put(clk);
420 +err_iounmap:
421 +       iounmap(base);
422 +err_release_mem_region:
423 +       release_mem_region(mem->start, resource_size(mem));
424 +       return ret;
425 +}
426 +
427 +static int __devexit jz47xx_i2c_remove(struct platform_device *pdev)
428 +{
429 +       struct jz47xx_i2c *jz47xx_i2c = platform_get_drvdata(pdev);
430 +
431 +       platform_set_drvdata(pdev, NULL);
432 +       i2c_del_adapter(&jz47xx_i2c->adapter);
433 +
434 +       jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
435 +
436 +       free_irq(jz47xx_i2c->irq, jz47xx_i2c);
437 +       clk_put(jz47xx_i2c->clk);
438 +
439 +       iounmap(jz47xx_i2c->base);
440 +       release_mem_region(jz47xx_i2c->mem->start, resource_size(jz47xx_i2c->mem));
441 +
442 +       kfree(jz47xx_i2c);
443 +
444 +       return 0;
445 +}
446 +
447 +static struct platform_driver jz47xx_i2c_driver = {
448 +       .probe = jz47xx_i2c_probe,
449 +       .remove = jz47xx_i2c_remove,
450 +       .driver = {
451 +               .name = "jz47xx-i2c",
452 +               .owner = THIS_MODULE,
453 +       },
454 +};
455 +
456 +static int __init jz47xx_i2c_init(void)
457 +{
458 +       return platform_driver_register(&jz47xx_i2c_driver);
459 +}
460 +module_init(jz47xx_i2c_init);
461 +
462 +static void jz47xx_i2c_exit(void)
463 +{
464 +       platform_driver_unregister(&jz47xx_i2c_driver);
465 +}
466 +module_exit(jz47xx_i2c_exit);
467 +
468 +MODULE_LICENSE("GPL");
469 +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
470 +MODULE_DESCRIPTION("I2C adapter driver for JZ47XX SoCs");
471 +MODULE_ALIAS("platform:jz47xx-i2c");
472 +