1 From 1f72dfe2738305c57605a8192176117e1641779c Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Wed, 17 Jun 2015 15:44:08 +0100
4 Subject: [PATCH] Add Chris Boot's i2c driver
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 i2c-bcm2708: fixed baudrate
11 Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock).
12 In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits.
13 This resulted in incorrect setting of CDIV and higher baudrate than intended.
14 Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz
15 After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz
16 The correct baudrate is shown in the log after the cdiv > 0xffff correction.
18 Perform I2C combined transactions when possible
20 Perform I2C combined transactions whenever possible, within the
21 restrictions of the Broadcomm Serial Controller.
23 Disable DONE interrupt during TA poll
25 Prevent interrupt from being triggered if poll is missed and transfer
28 i2c: Make combined transactions optional and disabled by default
30 i2c: bcm2708: add device tree support
32 Add DT support to driver and add to .dtsi file.
33 Setup pins in .dts file.
34 i2c is disabled by default.
36 Signed-off-by: Noralf Tronnes <notro@tronnes.org>
38 bcm2708: don't register i2c controllers when using DT
40 The devices for the i2c controllers are in the Device Tree.
41 Only register devices when not using DT.
43 Signed-off-by: Noralf Tronnes <notro@tronnes.org>
45 I2C: Only register the I2C device for the current board revision
47 i2c_bcm2708: Fix clock reference counting
49 Fix grabbing lock from atomic context in i2c driver
52 - check for timeouts in the bcm2708_bsc_setup function as indicated by this comment:
53 /* poll for transfer start bit (should only take 1-20 polls) */
54 This implies that the setup function can now fail so account for this everywhere it's called
55 - Removed the clk_get_rate call from inside the setup function as it locks a mutex and that's not ok since we call it from under a spin lock.
57 i2c-bcm2708: When using DT, leave the GPIO setup to pinctrl
59 i2c-bcm2708: Increase timeouts to allow larger transfers
61 Use the timeout value provided by the I2C_TIMEOUT ioctl when waiting
62 for completion. The default timeout is 1 second.
64 See: https://github.com/raspberrypi/linux/issues/260
66 i2c-bcm2708/BCM270X_DT: Add support for I2C2
68 The third I2C bus (I2C2) is normally reserved for HDMI use. Careless
69 use of this bus can break an attached display - use with caution.
71 It is recommended to disable accesses by VideoCore by setting
72 hdmi_ignore_edid=1 or hdmi_edid_file=1 in config.txt.
74 The interface is disabled by default - enable using the
75 i2c2_iknowwhatimdoing DT parameter.
77 bcm2708-spi: Don't use static pin configuration with DT
79 Also remove superfluous error checking - the SPI framework ensures the
80 validity of the chip_select value.
82 i2c-bcm2708: Remove non-DT support
84 Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
86 Set the BSC_CLKT clock streching timeout to 35ms as per SMBus specs.
88 Fixes i2c_bcm2708: Write to FIFO correctly - v2 (#1574)
90 * i2c: fix i2c_bcm2708: Clear FIFO before sending data
92 Make sure FIFO gets cleared before trying to send
93 data in case of a repeated start (COMBINED=Y).
95 * i2c: fix i2c_bcm2708: Only write to FIFO when not full
97 Check if FIFO can accept data before writing.
98 To avoid a peripheral read on the last iteration of a loop,
99 both bcm2708_bsc_fifo_fill and ~drain are changed as well.
101 drivers/i2c/busses/Kconfig | 19 ++
102 drivers/i2c/busses/Makefile | 2 +
103 drivers/i2c/busses/i2c-bcm2708.c | 512 +++++++++++++++++++++++++++++++
104 3 files changed, 533 insertions(+)
105 create mode 100644 drivers/i2c/busses/i2c-bcm2708.c
107 --- a/drivers/i2c/busses/Kconfig
108 +++ b/drivers/i2c/busses/Kconfig
109 @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support"
110 comment "PC SMBus host controller drivers"
114 + tristate "BCM2708 BSC"
115 + depends on ARCH_BCM2835
117 + Enabling this option will add BSC (Broadcom Serial Controller)
118 + support for the BCM2708. BSC is a Broadcom proprietary bus compatible
119 + with I2C/TWI/SMBus.
121 +config I2C_BCM2708_BAUDRATE
122 + prompt "BCM2708 I2C baudrate"
123 + depends on I2C_BCM2708
127 + Set the I2C baudrate. This will alter the default value. A
128 + different baudrate can be set by using a module parameter as well. If
129 + no parameter is provided when loading, this is the value that will be
135 --- a/drivers/i2c/busses/Makefile
136 +++ b/drivers/i2c/busses/Makefile
138 # Makefile for the i2c bus drivers.
141 +obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o
144 obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o
147 +++ b/drivers/i2c/busses/i2c-bcm2708.c
150 + * Driver for Broadcom BCM2708 BSC Controllers
152 + * Copyright (C) 2012 Chris Boot & Frank Buss
154 + * This driver is inspired by:
155 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
157 + * This program is free software; you can redistribute it and/or modify
158 + * it under the terms of the GNU General Public License as published by
159 + * the Free Software Foundation; either version 2 of the License, or
160 + * (at your option) any later version.
162 + * This program is distributed in the hope that it will be useful,
163 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
164 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165 + * GNU General Public License for more details.
167 + * You should have received a copy of the GNU General Public License
168 + * along with this program; if not, write to the Free Software
169 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
172 +#include <linux/kernel.h>
173 +#include <linux/module.h>
174 +#include <linux/spinlock.h>
175 +#include <linux/clk.h>
176 +#include <linux/err.h>
177 +#include <linux/of.h>
178 +#include <linux/platform_device.h>
179 +#include <linux/io.h>
180 +#include <linux/slab.h>
181 +#include <linux/i2c.h>
182 +#include <linux/interrupt.h>
183 +#include <linux/sched.h>
184 +#include <linux/wait.h>
186 +/* BSC register offsets */
189 +#define BSC_DLEN 0x08
191 +#define BSC_FIFO 0x10
192 +#define BSC_DIV 0x14
193 +#define BSC_DEL 0x18
194 +#define BSC_CLKT 0x1c
196 +/* Bitfields in BSC_C */
197 +#define BSC_C_I2CEN 0x00008000
198 +#define BSC_C_INTR 0x00000400
199 +#define BSC_C_INTT 0x00000200
200 +#define BSC_C_INTD 0x00000100
201 +#define BSC_C_ST 0x00000080
202 +#define BSC_C_CLEAR_1 0x00000020
203 +#define BSC_C_CLEAR_2 0x00000010
204 +#define BSC_C_READ 0x00000001
206 +/* Bitfields in BSC_S */
207 +#define BSC_S_CLKT 0x00000200
208 +#define BSC_S_ERR 0x00000100
209 +#define BSC_S_RXF 0x00000080
210 +#define BSC_S_TXE 0x00000040
211 +#define BSC_S_RXD 0x00000020
212 +#define BSC_S_TXD 0x00000010
213 +#define BSC_S_RXR 0x00000008
214 +#define BSC_S_TXW 0x00000004
215 +#define BSC_S_DONE 0x00000002
216 +#define BSC_S_TA 0x00000001
218 +#define I2C_WAIT_LOOP_COUNT 200
220 +#define DRV_NAME "bcm2708_i2c"
222 +static unsigned int baudrate;
223 +module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
224 +MODULE_PARM_DESC(baudrate, "The I2C baudrate");
226 +static bool combined = false;
227 +module_param(combined, bool, 0644);
228 +MODULE_PARM_DESC(combined, "Use combined transactions");
230 +struct bcm2708_i2c {
231 + struct i2c_adapter adapter;
234 + void __iomem *base;
240 + struct completion done;
242 + struct i2c_msg *msg;
248 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
250 + return readl(bi->base + reg);
253 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
255 + writel(val, bi->base + reg);
258 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
260 + bcm2708_wr(bi, BSC_C, 0);
261 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
264 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
266 + while ((bi->pos < bi->msg->len) && (bcm2708_rd(bi, BSC_S) & BSC_S_RXD))
267 + bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);
270 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
272 + while ((bi->pos < bi->msg->len) && (bcm2708_rd(bi, BSC_S) & BSC_S_TXD))
273 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
276 +static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi)
278 + u32 cdiv, s, clk_tout;
279 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
280 + int wait_loops = I2C_WAIT_LOOP_COUNT;
282 + /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked.
283 + * Use the value that we cached in the probe.
286 + clk_tout = bi->clk_tout;
288 + if (bi->msg->flags & I2C_M_RD)
289 + c |= BSC_C_INTR | BSC_C_READ;
293 + bcm2708_wr(bi, BSC_CLKT, clk_tout);
294 + bcm2708_wr(bi, BSC_DIV, cdiv);
295 + bcm2708_wr(bi, BSC_A, bi->msg->addr);
296 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
299 + /* Do the next two messages meet combined transaction criteria?
300 + - Current message is a write, next message is a read
301 + - Both messages to same slave address
302 + - Write message can fit inside FIFO (16 bytes or less) */
303 + if ( (bi->nmsgs > 1) &&
304 + !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
305 + (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
308 + bcm2708_wr(bi, BSC_C, BSC_C_CLEAR_1);
310 + /* Fill FIFO with entire write message (16 byte FIFO) */
311 + while (bi->pos < bi->msg->len) {
312 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
314 + /* Start write transfer (no interrupts, don't clear FIFO) */
315 + bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
317 + /* poll for transfer start bit (should only take 1-20 polls) */
319 + s = bcm2708_rd(bi, BSC_S);
320 + } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0);
322 + /* did we time out or some error occured? */
323 + if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) {
327 + /* Send next read message before the write transfer finishes. */
331 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
332 + c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
335 + bcm2708_wr(bi, BSC_C, c);
340 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
342 + struct bcm2708_i2c *bi = dev_id;
343 + bool handled = true;
347 + spin_lock(&bi->lock);
349 + /* we may see camera interrupts on the "other" I2C channel
350 + Just return if we've not sent anything */
351 + if (!bi->nmsgs || !bi->msg) {
355 + s = bcm2708_rd(bi, BSC_S);
357 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
358 + bcm2708_bsc_reset(bi);
361 + bi->msg = 0; /* to inform the that all work is done */
363 + /* wake up our bh */
364 + complete(&bi->done);
365 + } else if (s & BSC_S_DONE) {
368 + if (bi->msg->flags & I2C_M_RD) {
369 + bcm2708_bsc_fifo_drain(bi);
372 + bcm2708_bsc_reset(bi);
375 + /* advance to next message */
378 + ret = bcm2708_bsc_setup(bi);
380 + bcm2708_bsc_reset(bi);
382 + bi->msg = 0; /* to inform the that all work is done */
384 + /* wake up our bh */
385 + complete(&bi->done);
389 + bi->msg = 0; /* to inform the that all work is done */
391 + /* wake up our bh */
392 + complete(&bi->done);
394 + } else if (s & BSC_S_TXW) {
395 + bcm2708_bsc_fifo_fill(bi);
396 + } else if (s & BSC_S_RXR) {
397 + bcm2708_bsc_fifo_drain(bi);
403 + spin_unlock(&bi->lock);
405 + return handled ? IRQ_HANDLED : IRQ_NONE;
408 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
409 + struct i2c_msg *msgs, int num)
411 + struct bcm2708_i2c *bi = adap->algo_data;
412 + unsigned long flags;
415 + spin_lock_irqsave(&bi->lock, flags);
417 + reinit_completion(&bi->done);
423 + ret = bcm2708_bsc_setup(bi);
425 + spin_unlock_irqrestore(&bi->lock, flags);
427 + /* check the result of the setup */
430 + dev_err(&adap->dev, "transfer setup timed out\n");
431 + goto error_timeout;
434 + ret = wait_for_completion_timeout(&bi->done, adap->timeout);
436 + dev_err(&adap->dev, "transfer timed out\n");
437 + goto error_timeout;
440 + ret = bi->error ? -EIO : num;
444 + spin_lock_irqsave(&bi->lock, flags);
445 + bcm2708_bsc_reset(bi);
446 + bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */
448 + spin_unlock_irqrestore(&bi->lock, flags);
452 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
454 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
457 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
458 + .master_xfer = bcm2708_i2c_master_xfer,
459 + .functionality = bcm2708_i2c_functionality,
462 +static int bcm2708_i2c_probe(struct platform_device *pdev)
464 + struct resource *regs;
465 + int irq, err = -ENOMEM;
467 + struct bcm2708_i2c *bi;
468 + struct i2c_adapter *adap;
469 + unsigned long bus_hz;
470 + u32 cdiv, clk_tout;
473 + baud = CONFIG_I2C_BCM2708_BAUDRATE;
475 + if (pdev->dev.of_node) {
477 + pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c");
478 + if (pdev->id < 0) {
479 + dev_err(&pdev->dev, "alias is missing\n");
482 + if (!of_property_read_u32(pdev->dev.of_node,
483 + "clock-frequency", &bus_clk_rate))
484 + baud = bus_clk_rate;
486 + dev_warn(&pdev->dev,
487 + "Could not read clock-frequency property\n");
493 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
495 + dev_err(&pdev->dev, "could not get IO memory\n");
499 + irq = platform_get_irq(pdev, 0);
501 + dev_err(&pdev->dev, "could not get IRQ\n");
505 + clk = clk_get(&pdev->dev, NULL);
507 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
508 + return PTR_ERR(clk);
511 + err = clk_prepare_enable(clk);
513 + dev_err(&pdev->dev, "could not enable clk: %d\n", err);
517 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
519 + goto out_clk_disable;
521 + platform_set_drvdata(pdev, bi);
523 + adap = &bi->adapter;
524 + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;
525 + adap->algo = &bcm2708_i2c_algorithm;
526 + adap->algo_data = bi;
527 + adap->dev.parent = &pdev->dev;
528 + adap->nr = pdev->id;
529 + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
530 + adap->dev.of_node = pdev->dev.of_node;
532 + switch (pdev->id) {
534 + adap->class = I2C_CLASS_HWMON;
537 + adap->class = I2C_CLASS_DDC;
540 + adap->class = I2C_CLASS_DDC;
543 + dev_err(&pdev->dev, "can only bind to BSC 0, 1 or 2\n");
548 + spin_lock_init(&bi->lock);
549 + init_completion(&bi->done);
551 + bi->base = ioremap(regs->start, resource_size(regs));
553 + dev_err(&pdev->dev, "could not remap memory\n");
560 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
561 + dev_name(&pdev->dev), bi);
563 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
567 + bcm2708_bsc_reset(bi);
569 + err = i2c_add_numbered_adapter(adap);
571 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
575 + bus_hz = clk_get_rate(bi->clk);
576 + cdiv = bus_hz / baud;
577 + if (cdiv > 0xffff) {
579 + baud = bus_hz / cdiv;
582 + clk_tout = 35/1000*baud; //35ms timeout as per SMBus specs.
583 + if (clk_tout > 0xffff)
587 + bi->clk_tout = clk_tout;
589 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n",
590 + pdev->id, (unsigned long)regs->start, irq, baud);
595 + free_irq(bi->irq, bi);
601 + clk_disable_unprepare(clk);
607 +static int bcm2708_i2c_remove(struct platform_device *pdev)
609 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
611 + platform_set_drvdata(pdev, NULL);
613 + i2c_del_adapter(&bi->adapter);
614 + free_irq(bi->irq, bi);
616 + clk_disable_unprepare(bi->clk);
623 +static const struct of_device_id bcm2708_i2c_of_match[] = {
624 + { .compatible = "brcm,bcm2708-i2c" },
627 +MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match);
629 +static struct platform_driver bcm2708_i2c_driver = {
632 + .owner = THIS_MODULE,
633 + .of_match_table = bcm2708_i2c_of_match,
635 + .probe = bcm2708_i2c_probe,
636 + .remove = bcm2708_i2c_remove,
639 +// module_platform_driver(bcm2708_i2c_driver);
642 +static int __init bcm2708_i2c_init(void)
644 + return platform_driver_register(&bcm2708_i2c_driver);
647 +static void __exit bcm2708_i2c_exit(void)
649 + platform_driver_unregister(&bcm2708_i2c_driver);
652 +module_init(bcm2708_i2c_init);
653 +module_exit(bcm2708_i2c_exit);
657 +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");
658 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
659 +MODULE_LICENSE("GPL v2");
660 +MODULE_ALIAS("platform:" DRV_NAME);