brcm2708: add support for 3.10 kernel
[openwrt/staging/dedeckeh.git] / target / linux / brcm2708 / patches-3.10 / 015-bcm2708-i2c-driver.patch
1 diff -urN linux-3.10/drivers/i2c/busses/i2c-bcm2708.c linux-rpi-3.10.y/drivers/i2c/busses/i2c-bcm2708.c
2 --- linux-3.10/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-rpi-3.10.y/drivers/i2c/busses/i2c-bcm2708.c 2013-07-06 15:25:50.000000000 +0100
4 @@ -0,0 +1,408 @@
5 +/*
6 + * Driver for Broadcom BCM2708 BSC Controllers
7 + *
8 + * Copyright (C) 2012 Chris Boot & Frank Buss
9 + *
10 + * This driver is inspired by:
11 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
12 + *
13 + * This program is free software; you can redistribute it and/or modify
14 + * it under the terms of the GNU General Public License as published by
15 + * the Free Software Foundation; either version 2 of the License, or
16 + * (at your option) any later version.
17 + *
18 + * This program is distributed in the hope that it will be useful,
19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 + * GNU General Public License for more details.
22 + *
23 + * You should have received a copy of the GNU General Public License
24 + * along with this program; if not, write to the Free Software
25 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 + */
27 +
28 +#include <linux/kernel.h>
29 +#include <linux/module.h>
30 +#include <linux/spinlock.h>
31 +#include <linux/clk.h>
32 +#include <linux/err.h>
33 +#include <linux/platform_device.h>
34 +#include <linux/io.h>
35 +#include <linux/slab.h>
36 +#include <linux/i2c.h>
37 +#include <linux/interrupt.h>
38 +#include <linux/sched.h>
39 +#include <linux/wait.h>
40 +
41 +/* BSC register offsets */
42 +#define BSC_C 0x00
43 +#define BSC_S 0x04
44 +#define BSC_DLEN 0x08
45 +#define BSC_A 0x0c
46 +#define BSC_FIFO 0x10
47 +#define BSC_DIV 0x14
48 +#define BSC_DEL 0x18
49 +#define BSC_CLKT 0x1c
50 +
51 +/* Bitfields in BSC_C */
52 +#define BSC_C_I2CEN 0x00008000
53 +#define BSC_C_INTR 0x00000400
54 +#define BSC_C_INTT 0x00000200
55 +#define BSC_C_INTD 0x00000100
56 +#define BSC_C_ST 0x00000080
57 +#define BSC_C_CLEAR_1 0x00000020
58 +#define BSC_C_CLEAR_2 0x00000010
59 +#define BSC_C_READ 0x00000001
60 +
61 +/* Bitfields in BSC_S */
62 +#define BSC_S_CLKT 0x00000200
63 +#define BSC_S_ERR 0x00000100
64 +#define BSC_S_RXF 0x00000080
65 +#define BSC_S_TXE 0x00000040
66 +#define BSC_S_RXD 0x00000020
67 +#define BSC_S_TXD 0x00000010
68 +#define BSC_S_RXR 0x00000008
69 +#define BSC_S_TXW 0x00000004
70 +#define BSC_S_DONE 0x00000002
71 +#define BSC_S_TA 0x00000001
72 +
73 +#define I2C_TIMEOUT_MS 150
74 +
75 +#define DRV_NAME "bcm2708_i2c"
76 +
77 +static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE;
78 +module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
79 +MODULE_PARM_DESC(baudrate, "The I2C baudrate");
80 +
81 +
82 +struct bcm2708_i2c {
83 + struct i2c_adapter adapter;
84 +
85 + spinlock_t lock;
86 + void __iomem *base;
87 + int irq;
88 + struct clk *clk;
89 +
90 + struct completion done;
91 +
92 + struct i2c_msg *msg;
93 + int pos;
94 + int nmsgs;
95 + bool error;
96 +};
97 +
98 +/*
99 + * This function sets the ALT mode on the I2C pins so that we can use them with
100 + * the BSC hardware.
101 + *
102 + * FIXME: This is a hack. Use pinmux / pinctrl.
103 + */
104 +static void bcm2708_i2c_init_pinmode(int id)
105 +{
106 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
107 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
108 +
109 + int pin;
110 + u32 *gpio = ioremap(0x20200000, SZ_16K);
111 +
112 + BUG_ON(id != 0 && id != 1);
113 + /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */
114 + for (pin = id*2+0; pin <= id*2+1; pin++) {
115 +printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin);
116 + INP_GPIO(pin); /* set mode to GPIO input first */
117 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
118 + }
119 +
120 + iounmap(gpio);
121 +
122 +#undef INP_GPIO
123 +#undef SET_GPIO_ALT
124 +}
125 +
126 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
127 +{
128 + return readl(bi->base + reg);
129 +}
130 +
131 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
132 +{
133 + writel(val, bi->base + reg);
134 +}
135 +
136 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
137 +{
138 + bcm2708_wr(bi, BSC_C, 0);
139 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
140 +}
141 +
142 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
143 +{
144 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len))
145 + bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);
146 +}
147 +
148 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
149 +{
150 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len))
151 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
152 +}
153 +
154 +static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
155 +{
156 + unsigned long bus_hz;
157 + u32 cdiv;
158 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
159 +
160 + bus_hz = clk_get_rate(bi->clk);
161 + cdiv = bus_hz / baudrate;
162 +
163 + if (bi->msg->flags & I2C_M_RD)
164 + c |= BSC_C_INTR | BSC_C_READ;
165 + else
166 + c |= BSC_C_INTT;
167 +
168 + bcm2708_wr(bi, BSC_DIV, cdiv);
169 + bcm2708_wr(bi, BSC_A, bi->msg->addr);
170 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
171 + bcm2708_wr(bi, BSC_C, c);
172 +}
173 +
174 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
175 +{
176 + struct bcm2708_i2c *bi = dev_id;
177 + bool handled = true;
178 + u32 s;
179 +
180 + spin_lock(&bi->lock);
181 +
182 + /* we may see camera interrupts on the "other" I2C channel
183 + Just return if we've not sent anything */
184 + if (!bi->nmsgs || !bi->msg )
185 + goto early_exit;
186 +
187 + s = bcm2708_rd(bi, BSC_S);
188 +
189 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
190 + bcm2708_bsc_reset(bi);
191 + bi->error = true;
192 +
193 + /* wake up our bh */
194 + complete(&bi->done);
195 + } else if (s & BSC_S_DONE) {
196 + bi->nmsgs--;
197 +
198 + if (bi->msg->flags & I2C_M_RD)
199 + bcm2708_bsc_fifo_drain(bi);
200 +
201 + bcm2708_bsc_reset(bi);
202 +
203 + if (bi->nmsgs) {
204 + /* advance to next message */
205 + bi->msg++;
206 + bi->pos = 0;
207 + bcm2708_bsc_setup(bi);
208 + } else {
209 + /* wake up our bh */
210 + complete(&bi->done);
211 + }
212 + } else if (s & BSC_S_TXW) {
213 + bcm2708_bsc_fifo_fill(bi);
214 + } else if (s & BSC_S_RXR) {
215 + bcm2708_bsc_fifo_drain(bi);
216 + } else {
217 + handled = false;
218 + }
219 +
220 +early_exit:
221 + spin_unlock(&bi->lock);
222 +
223 + return handled ? IRQ_HANDLED : IRQ_NONE;
224 +}
225 +
226 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
227 + struct i2c_msg *msgs, int num)
228 +{
229 + struct bcm2708_i2c *bi = adap->algo_data;
230 + unsigned long flags;
231 + int ret;
232 +
233 + spin_lock_irqsave(&bi->lock, flags);
234 +
235 + INIT_COMPLETION(bi->done);
236 + bi->msg = msgs;
237 + bi->pos = 0;
238 + bi->nmsgs = num;
239 + bi->error = false;
240 +
241 + spin_unlock_irqrestore(&bi->lock, flags);
242 +
243 + bcm2708_bsc_setup(bi);
244 +
245 + ret = wait_for_completion_timeout(&bi->done,
246 + msecs_to_jiffies(I2C_TIMEOUT_MS));
247 + if (ret == 0) {
248 + dev_err(&adap->dev, "transfer timed out\n");
249 + spin_lock_irqsave(&bi->lock, flags);
250 + bcm2708_bsc_reset(bi);
251 + spin_unlock_irqrestore(&bi->lock, flags);
252 + return -ETIMEDOUT;
253 + }
254 +
255 + return bi->error ? -EIO : num;
256 +}
257 +
258 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
259 +{
260 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
261 +}
262 +
263 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
264 + .master_xfer = bcm2708_i2c_master_xfer,
265 + .functionality = bcm2708_i2c_functionality,
266 +};
267 +
268 +static int bcm2708_i2c_probe(struct platform_device *pdev)
269 +{
270 + struct resource *regs;
271 + int irq, err = -ENOMEM;
272 + struct clk *clk;
273 + struct bcm2708_i2c *bi;
274 + struct i2c_adapter *adap;
275 +
276 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
277 + if (!regs) {
278 + dev_err(&pdev->dev, "could not get IO memory\n");
279 + return -ENXIO;
280 + }
281 +
282 + irq = platform_get_irq(pdev, 0);
283 + if (irq < 0) {
284 + dev_err(&pdev->dev, "could not get IRQ\n");
285 + return irq;
286 + }
287 +
288 + clk = clk_get(&pdev->dev, NULL);
289 + if (IS_ERR(clk)) {
290 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
291 + return PTR_ERR(clk);
292 + }
293 +
294 + bcm2708_i2c_init_pinmode(pdev->id);
295 +
296 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
297 + if (!bi)
298 + goto out_clk_put;
299 +
300 + platform_set_drvdata(pdev, bi);
301 +
302 + adap = &bi->adapter;
303 + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;
304 + adap->algo = &bcm2708_i2c_algorithm;
305 + adap->algo_data = bi;
306 + adap->dev.parent = &pdev->dev;
307 + adap->nr = pdev->id;
308 + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
309 +
310 + switch (pdev->id) {
311 + case 0:
312 + adap->class = I2C_CLASS_HWMON;
313 + break;
314 + case 1:
315 + adap->class = I2C_CLASS_DDC;
316 + break;
317 + default:
318 + dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
319 + err = -ENXIO;
320 + goto out_free_bi;
321 + }
322 +
323 + spin_lock_init(&bi->lock);
324 + init_completion(&bi->done);
325 +
326 + bi->base = ioremap(regs->start, resource_size(regs));
327 + if (!bi->base) {
328 + dev_err(&pdev->dev, "could not remap memory\n");
329 + goto out_free_bi;
330 + }
331 +
332 + bi->irq = irq;
333 + bi->clk = clk;
334 +
335 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
336 + dev_name(&pdev->dev), bi);
337 + if (err) {
338 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
339 + goto out_iounmap;
340 + }
341 +
342 + bcm2708_bsc_reset(bi);
343 +
344 + err = i2c_add_numbered_adapter(adap);
345 + if (err < 0) {
346 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
347 + goto out_free_irq;
348 + }
349 +
350 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",
351 + pdev->id, (unsigned long)regs->start, irq, baudrate/1000);
352 +
353 + return 0;
354 +
355 +out_free_irq:
356 + free_irq(bi->irq, bi);
357 +out_iounmap:
358 + iounmap(bi->base);
359 +out_free_bi:
360 + kfree(bi);
361 +out_clk_put:
362 + clk_put(clk);
363 + return err;
364 +}
365 +
366 +static int bcm2708_i2c_remove(struct platform_device *pdev)
367 +{
368 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
369 +
370 + platform_set_drvdata(pdev, NULL);
371 +
372 + i2c_del_adapter(&bi->adapter);
373 + free_irq(bi->irq, bi);
374 + iounmap(bi->base);
375 + clk_disable(bi->clk);
376 + clk_put(bi->clk);
377 + kfree(bi);
378 +
379 + return 0;
380 +}
381 +
382 +static struct platform_driver bcm2708_i2c_driver = {
383 + .driver = {
384 + .name = DRV_NAME,
385 + .owner = THIS_MODULE,
386 + },
387 + .probe = bcm2708_i2c_probe,
388 + .remove = bcm2708_i2c_remove,
389 +};
390 +
391 +// module_platform_driver(bcm2708_i2c_driver);
392 +
393 +
394 +static int __init bcm2708_i2c_init(void)
395 +{
396 + return platform_driver_register(&bcm2708_i2c_driver);
397 +}
398 +
399 +static void __exit bcm2708_i2c_exit(void)
400 +{
401 + platform_driver_unregister(&bcm2708_i2c_driver);
402 +}
403 +
404 +module_init(bcm2708_i2c_init);
405 +module_exit(bcm2708_i2c_exit);
406 +
407 +
408 +
409 +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");
410 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
411 +MODULE_LICENSE("GPL v2");
412 +MODULE_ALIAS("platform:" DRV_NAME);
413 diff -urN linux-3.10/drivers/i2c/busses/Kconfig linux-rpi-3.10.y/drivers/i2c/busses/Kconfig
414 --- linux-3.10/drivers/i2c/busses/Kconfig 2013-06-30 23:13:29.000000000 +0100
415 +++ linux-rpi-3.10.y/drivers/i2c/busses/Kconfig 2013-07-06 15:25:50.000000000 +0100
416 @@ -343,6 +343,25 @@
417 This support is also available as a module. If so, the module
418 will be called i2c-bcm2835.
419
420 +config I2C_BCM2708
421 + tristate "BCM2708 BSC"
422 + depends on MACH_BCM2708
423 + help
424 + Enabling this option will add BSC (Broadcom Serial Controller)
425 + support for the BCM2708. BSC is a Broadcom proprietary bus compatible
426 + with I2C/TWI/SMBus.
427 +
428 +config I2C_BCM2708_BAUDRATE
429 + prompt "BCM2708 I2C baudrate"
430 + depends on I2C_BCM2708
431 + int
432 + default 100000
433 + help
434 + Set the I2C baudrate. This will alter the default value. A
435 + different baudrate can be set by using a module parameter as well. If
436 + no parameter is provided when loading, this is the value that will be
437 + used.
438 +
439 config I2C_BLACKFIN_TWI
440 tristate "Blackfin TWI I2C support"
441 depends on BLACKFIN
442 diff -urN linux-3.10/drivers/i2c/busses/Makefile linux-rpi-3.10.y/drivers/i2c/busses/Makefile
443 --- linux-3.10/drivers/i2c/busses/Makefile 2013-06-30 23:13:29.000000000 +0100
444 +++ linux-rpi-3.10.y/drivers/i2c/busses/Makefile 2013-07-06 15:25:50.000000000 +0100
445 @@ -32,6 +32,7 @@
446 obj-$(CONFIG_I2C_AT91) += i2c-at91.o
447 obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
448 obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o
449 +obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o
450 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
451 obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
452 obj-$(CONFIG_I2C_CPM) += i2c-cpm.o