Skip to contentSkip to conversation

i2c: SuperH Mobile I2C Bus Controller V3

PATCH In review Paul Mundt 2 participants 3 messages Mar 25, 2008 – Mar 27, 2008

Subsystems (3)
lore
Share & tools
lore

Paul Mundt

author
#0 lore raw

PATCH 1/1 i2c: SuperH Mobile I2C Bus Controller V3

This is V3 of the SuperH Mobile I2C Controller Driver. A simple Master only driver for the I2C block included in processors such as sh7343, sh7722 and sh7723. Tested on a sh7722 MigoR using a rs5c372b rtc.

Changes since V2:
- dev_xxx() use
- Kill off superfluous ioarea resource
- Add SMBus emulation
Changes since V1:
- Use clk_get()/clk_put()/clk_get_rate() to get peripheral clock rate.
- Use pdev->dev.bus_id instead of dev->name

Verified with the rtc-rs5c372 SMBus conversion patches currently in -mm.

---

 drivers/i2c/busses/Kconfig         |    9 
 drivers/i2c/busses/Makefile        |    1 
 drivers/i2c/busses/i2c-sh_mobile.c |  504 +++++++++++++++++++++++++++++++++++++
 3 files changed, 513 insertions(+)
drivers/i2c/busses/Kconfig +9 -0
index 3376d53..80b426c 100644
@@ -684,4 +684,13 @@ config I2C_PMCMSP
 	  This driver can also be built as module. If so, the module
 	  will be called i2c-pmcmsp.
 
+config I2C_SH_MOBILE
+	tristate "SuperH Mobile I2C Controller"
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the Renesas SH-Mobile processor.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-sh_mobile.
+
 endmenu
drivers/i2c/busses/Makefile +1 -0
index d179bce..5fe799d 100644
@@ -53,6 +53,7 @@ obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o
 obj-$(CONFIG_I2C_VOODOO3)	+= i2c-voodoo3.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
+obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
drivers/i2c/busses/i2c-sh_mobile.c new file +497 -0

497 lines not on this page · raw message

#1 lore raw
Quoted 5 lines · On Tue, 25 Mar 2008 19:55:59 +0900 Paul Mundt <[email protected]> wrote:

This is V3 of the SuperH Mobile I2C Controller Driver. A simple Master only driver for the I2C block included in processors such as sh7343, sh7722 and sh7723. Tested on a sh7722 MigoR using a rs5c372b rtc.

+#include <asm/io.h>

please use checkpatch.

Quoted 29 lines
drivers/i2c/busses/i2c-sh_mobile.c new file +29 -0
+static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
+			    int op, unsigned char data)
+{
+	unsigned char ret = 0;
+
+	dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data);
+
+	spin_lock_irq(&pd->lock);
+
+	switch (op) {
+	case OP_START:
+		iowrite8(0x94, ICCR(pd));
+		break;
+	case OP_TX_ONLY:
+		iowrite8(data, ICDR(pd));
+		break;
+	case OP_TX_STOP:
+		iowrite8(data, ICDR(pd));
+		iowrite8(0x90, ICCR(pd));
+		iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
+		break;
+	case OP_TX_TO_RX:
+		iowrite8(data, ICDR(pd));
+		iowrite8(0x81, ICCR(pd));
+		break;
+	case OP_RX_ONLY:
+		ret = ioread8(ICDR(pd));
+		break;
+	case OP_RX_STOP:

drivers/i2c/busses/i2c-sh_mobile.c line 159

Quoted 10 lines
drivers/i2c/busses/i2c-sh_mobile.c new file +10 -0
+		ret = ioread8(ICDR(pd));
+		iowrite8(0xc0, ICCR(pd));
+		break;
+	}
+
+	spin_unlock_irq(&pd->lock);
+
+	dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
+	return ret;
+}

I'd be a bit concerned about reenabling interrupts...

Quoted 13 lines
drivers/i2c/busses/i2c-sh_mobile.c new file +13 -0
+static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
+{
+	struct platform_device *dev = dev_id;
+	struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
+	struct i2c_msg *msg = pd->msg;
+	unsigned char data, sr;
+	int wakeup = 0;
+
+	sr = ioread8(ICSR(pd));
+	pd->sr |= sr;
+
+	dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
+	       (msg->flags & I2C_M_RD) ? "read" : "write",

drivers/i2c/busses/i2c-sh_mobile.c line 183

Quoted 10 lines
drivers/i2c/busses/i2c-sh_mobile.c new file +10 -0
+	       pd->pos, msg->len);
+
+	if (sr & (ICSR_AL | ICSR_TACK)) {
+		iowrite8(0, ICIC(pd)); /* disable interrupts */
+		wakeup = 1;
+		goto do_wakeup;
+	}
+
+	if (pd->pos == msg->len) {
+		i2c_op(pd, OP_RX_ONLY, 0);

from the interrupt handler...

drivers/i2c/busses/i2c-sh_mobile.c line 360

Quoted 12 lines
drivers/i2c/busses/i2c-sh_mobile.c new file +12 -0
+static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
+{
+	struct resource *res;
+	int ret = -ENXIO;
+	int q, m;
+	int k = 0;
+	int n = 0;
+
+	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
+		for (n = res->start; hook && n <= res->end; n++) {
+			if (request_irq(n, sh_mobile_i2c_isr, 0,
+					dev->dev.bus_id, dev))

even though it isn't using IRQF_DISABLED here,

: int request_irq(unsigned int irq, irq_handler_t handler,
: unsigned long irqflags, const char *devname, void *dev_id)
: {
: struct irqaction *action;
: int retval;
:
: #ifdef CONFIG_LOCKDEP
: /*
: * Lockdep wants atomic interrupt handlers:
: */
: irqflags |= IRQF_DISABLED;
: #endif

it will do so if lockdep is supported.

#2 lore raw
In reply to Paul Mundt
Quoted 1 line · On Tue, 25 Mar 2008 19:55:59 +0900 Paul Mundt <[email protected]> wrote:

This is V3 of the SuperH Mobile I2C Controller Driver.

i386 allmodconfig:

ERROR: "clk_get_rate" [drivers/i2c/busses/i2c-sh_mobile.ko] undefined!
ERROR: "clk_get" [drivers/i2c/busses/i2c-sh_mobile.ko] undefined!
ERROR: "clk_put" [drivers/i2c/busses/i2c-sh_mobile.ko] undefined!