* [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4
@ 2008-11-29 1:28 Tony Lindgren
2008-11-29 1:28 ` [PATCH 01/12] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
` (12 more replies)
0 siblings, 13 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap
Hi all,
Here are the i2c-omap patches again for next merge window.
Regards,
Tony
---
Chandra shekhar (1):
i2c-omap: Add support for omap34xx
Jarkko Nikula (1):
i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
Kalle Jokiniemi (1):
i2c-omap: Enable I2C wakeups for 34xx
Nishanth Menon (1):
i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
Paul Walmsley (6):
i2c-omap: reprogram OCP_SYSCONFIG register after reset
i2c-omap: convert 'rev1' flag to generic 'rev' u8
i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un,}idle()
i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
i2c-omap: Mark init-only functions as __init
i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
Syed Mohammed Khasim (1):
i2c-omap: Add high-speed support to omap-i2c
Tony Lindgren (1):
i2c-omap: Clean-up i2c-omap
arch/arm/mach-omap2/clock24xx.h | 4
drivers/i2c/busses/i2c-omap.c | 420 ++++++++++++++++++++++++++++++---------
2 files changed, 330 insertions(+), 94 deletions(-)
--
Signature
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/12] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 02/12] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
` (11 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Juha Yrjola, linux-omap, Jarkko Nikula
From: Jarkko Nikula <jarkko.nikula@nokia.com>
If there is a signal pending and wait_for_completion_interruptible_timeout
terminates with -ERESTARTSYS, we return and disable the i2c clocks in
omap_i2c_xfer.
If we terminate before sending last i2c message with a stop condition, the
bus remains busy and we are not able to send new messages into bus with
successive omap_i2c_xfer calls. Therefore a pending signal is not caught
here and we return only because of timeout or i2c error.
Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 608038d..17476ec 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -328,8 +328,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
- r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- OMAP_I2C_TIMEOUT);
+ /*
+ * REVISIT: We should abort the transfer on signals, but the bus goes
+ * into arbitration and we're currently unable to recover from it.
+ */
+ r = wait_for_completion_timeout(&dev->cmd_complete,
+ OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/12] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
2008-11-29 1:28 ` [PATCH 01/12] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 03/12] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
` (10 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Paul Walmsley, linux-omap
From: Paul Walmsley <paul@pwsan.com>
omap_i2c_idle() sets an internal flag, "dev->idle", instructing its
ISR to decline interrupts. It sets this flag before it actually masks
the interrupts on the I2C controller. This is problematic, since an
I2C interrupt could arrive after dev->idle is set, but before the
interrupt source is masked. When this happens, Linux disables the I2C
controller's IRQ, causing all future transactions on the bus to fail.
Symptoms, happening on about 7% of boots:
irq 56: nobody cared (try booting with the "irqpoll" option)
<warning traceback here>
Disabling IRQ #56
i2c_omap i2c_omap.1: controller timed out
In omap_i2c_idle(), this patch sets dev->idle only after the interrupt
mask write to the I2C controller has left the ARM write buffer.
That's probably the major offender. For additional prophylaxis, in
omap_i2c_unidle(), the patch clears the dev->idle flag before
interrupts are enabled, rather than afterwards.
The patch has survived twenty-two reboots on the 3430SDP here without
wedging I2C1. Not absolutely dispositive, but promising!
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 17476ec..5ca0e00 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -181,22 +181,26 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
+ dev->idle = 0;
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- dev->idle = 0;
}
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
- dev->idle = 1;
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev1)
+ if (dev->rev1) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
- else
+ } else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
+
+ /* Flush posted write before the dev->idle store occurs */
+ omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ }
+ dev->idle = 1;
clk_disable(dev->fclk);
if (dev->iclk != NULL)
clk_disable(dev->iclk);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/12] i2c-omap: Add high-speed support to omap-i2c
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
2008-11-29 1:28 ` [PATCH 01/12] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
2008-11-29 1:28 ` [PATCH 02/12] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 04/12] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
` (9 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap, Russell King, Syed Mohammed Khasim
From: Syed Mohammed Khasim <x0khasim@ti.com>
Omap2430 has additional support for high-speed I2C.
This patch moves I2C speed parameter (from module) to platform data.
Also added basic High Speed support based on I2C bus speed.
This patch is tested for high speed I2C (with TWL4030 Keypad) and works as
expected.
Also change the 2430 i2chs_fck names to use the standard naming.
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Syed Mohammed Khasim <x0khasim@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/clock24xx.h | 4 +-
drivers/i2c/busses/i2c-omap.c | 82 +++++++++++++++++++++++++++++----------
2 files changed, 62 insertions(+), 24 deletions(-)
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 242a19d..e5fc5bf 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = {
};
static struct clk i2chs2_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 2,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
@@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = {
};
static struct clk i2chs1_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 1,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5ca0e00..b0aa0f8 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -83,6 +83,7 @@
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
+#define OMAP_I2C_CON_OPMODE (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -91,6 +92,10 @@
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
+/* I2C SCL time value when Master */
+#define OMAP_I2C_SCLL_HSSCLL 8
+#define OMAP_I2C_SCLH_HSSCLH 8
+
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@@ -109,12 +114,6 @@
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
-/* REVISIT: Use platform_data instead of module parameters */
-/* Fast Mode = 400 kHz, Standard = 100 kHz */
-static int clock = 100; /* Default: 100 kHz */
-module_param(clock, int, 0);
-MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
-
struct omap_i2c_dev {
struct device *dev;
void __iomem *base; /* virtual */
@@ -123,6 +122,7 @@ struct omap_i2c_dev {
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
struct resource *ioarea;
+ u32 speed; /* Speed of bus in Khz */
u16 cmd_err;
u8 *buf;
size_t buf_len;
@@ -208,9 +208,11 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
- u16 psc = 0;
+ u16 psc = 0, scll = 0, sclh = 0;
+ u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout;
+ unsigned long internal_clk = 0;
if (!dev->rev1) {
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
@@ -253,18 +255,47 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
+ if (cpu_is_omap2430()) {
+
+ /* HSI2C controller internal clk rate should be 19.2 Mhz */
+ internal_clk = 19200;
+ fclk_rate = clk_get_rate(dev->fclk) / 1000;
+
+ /* Compute prescaler divisor */
+ psc = fclk_rate / internal_clk;
+ psc = psc - 1;
+
+ /* If configured for High Speed */
+ if (dev->speed > 400) {
+ /* For first phase of HS mode */
+ fsscll = internal_clk / (400 * 2) - 6;
+ fssclh = internal_clk / (400 * 2) - 6;
+
+ /* For second phase of HS mode */
+ hsscll = fclk_rate / (dev->speed * 2) - 6;
+ hssclh = fclk_rate / (dev->speed * 2) - 6;
+ } else {
+ /* To handle F/S modes */
+ fsscll = internal_clk / (dev->speed * 2) - 6;
+ fssclh = internal_clk / (dev->speed * 2) - 6;
+ }
+ scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
+ sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
+ } else {
+ /* Program desired operating rate */
+ fclk_rate /= (psc + 1) * 1000;
+ if (psc > 2)
+ psc = 2;
+ scll = fclk_rate / (dev->speed * 2) - 7 + psc;
+ sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
+ }
+
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
- /* Program desired operating rate */
- fclk_rate /= (psc + 1) * 1000;
- if (psc > 2)
- psc = 2;
-
- omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
- fclk_rate / (clock * 2) - 7 + psc);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
- fclk_rate / (clock * 2) - 7 + psc);
+ /* SCL low and high time values */
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
@@ -324,6 +355,11 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+
+ /* High speed configuration */
+ if (dev->speed > 400)
+ w |= OMAP_I2C_CON_OPMODE;
+
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
@@ -564,6 +600,7 @@ omap_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
int r;
+ u32 *speed = NULL;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -584,17 +621,18 @@ omap_i2c_probe(struct platform_device *pdev)
return -EBUSY;
}
- if (clock > 200)
- clock = 400; /* Fast mode */
- else
- clock = 100; /* Standard mode */
-
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) {
r = -ENOMEM;
goto err_release_region;
}
+ if (pdev->dev.platform_data != NULL)
+ speed = (u32 *) pdev->dev.platform_data;
+ else
+ *speed = 100; /* Defualt speed */
+
+ dev->speed = *speed;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -625,7 +663,7 @@ omap_i2c_probe(struct platform_device *pdev)
}
r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, r >> 4, r & 0xf, clock);
+ pdev->id, r >> 4, r & 0xf, dev->speed);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/12] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (2 preceding siblings ...)
2008-11-29 1:28 ` [PATCH 03/12] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 05/12] i2c-omap: Add support for omap34xx Tony Lindgren
` (8 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Nishanth Menon, linux-omap, Jason P Marini
From: Nishanth Menon <nm@ti.com>
Based on an earlier patch from Nishant Menon:
- Transfers can use FIFO on FIFO capable devices
- Prevents errors for HSI2C if FIFO is not used
- Implemented errenous handling of STT-STP handling on SDP2430
Also merged in is a fix from Jaron Marini to fix occasional i2c
hang if OMAP_I2C_CON_STT remains asserted.
Signed-off-by: Jason P Marini <jason.marini@gmail.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 190 ++++++++++++++++++++++++++++++++---------
1 files changed, 150 insertions(+), 40 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b0aa0f8..9ae4b74 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -55,8 +55,11 @@
#define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
+#define OMAP_I2C_BUFSTAT_REG 0x40
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
+#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@@ -64,7 +67,8 @@
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
-#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */
+#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
+#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@@ -78,12 +82,14 @@
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
+#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
+#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
-#define OMAP_I2C_CON_OPMODE (1 << 12) /* High Speed support */
+#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -127,7 +133,12 @@ struct omap_i2c_dev {
u8 *buf;
size_t buf_len;
struct i2c_adapter adapter;
+ u8 fifo_size; /* use as flag and value
+ * fifo_size==0 implies no fifo
+ * if set, should be trsh+1
+ */
unsigned rev1:1;
+ unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1;
u16 iestate; /* Saved interrupt register */
};
@@ -297,6 +308,14 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
+ if (dev->fifo_size)
+ /* Note: setup required fifo size - 1 */
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+ (dev->fifo_size - 1) << 8 | /* RTRSH */
+ OMAP_I2C_BUF_RXFIF_CLR |
+ (dev->fifo_size - 1) | /* XTRSH */
+ OMAP_I2C_BUF_TXFIF_CLR);
+
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
@@ -304,7 +323,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL));
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -351,6 +371,11 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+ /* Clear the FIFO Buffers */
+ w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+ w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
+
init_completion(&dev->cmd_complete);
dev->cmd_err = 0;
@@ -358,17 +383,40 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
/* High speed configuration */
if (dev->speed > 400)
- w |= OMAP_I2C_CON_OPMODE;
+ w |= OMAP_I2C_CON_OPMODE_HS;
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
- if (stop)
+ if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
/*
+ * Don't write stt and stp together on some hardware.
+ */
+ if (dev->b_hw && stop) {
+ unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
+ u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+ while (con & OMAP_I2C_CON_STT) {
+ con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+
+ /* Let the user know if i2c is in a bad state */
+ if (time_after(jiffies, delay)) {
+ dev_err(dev->dev, "controller timed out "
+ "waiting for start condition to finish\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ w |= OMAP_I2C_CON_STP;
+ w &= ~OMAP_I2C_CON_STT;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+ }
+
+ /*
* REVISIT: We should abort the transfer on signals, but the bus goes
* into arbitration and we're currently unable to recover from it.
*/
@@ -516,7 +564,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
struct omap_i2c_dev *dev = dev_id;
u16 bits;
u16 stat, w;
- int count = 0;
+ int err, count = 0;
if (dev->idle)
return IRQ_NONE;
@@ -531,39 +579,94 @@ omap_i2c_isr(int this_irq, void *dev_id)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
- if (stat & OMAP_I2C_STAT_ARDY) {
- omap_i2c_complete_cmd(dev, 0);
- continue;
+ err = 0;
+ if (stat & OMAP_I2C_STAT_NACK) {
+ err |= OMAP_I2C_STAT_NACK;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+ OMAP_I2C_CON_STP);
}
- if (stat & OMAP_I2C_STAT_RRDY) {
- w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
- if (dev->buf_len) {
- *dev->buf++ = w;
- dev->buf_len--;
+ if (stat & OMAP_I2C_STAT_AL) {
+ dev_err(dev->dev, "Arbitration lost\n");
+ err |= OMAP_I2C_STAT_AL;
+ }
+ if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
+ OMAP_I2C_STAT_AL))
+ omap_i2c_complete_cmd(dev, err);
+ if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
- *dev->buf++ = w >> 8;
+ *dev->buf++ = w;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430()) {
+ if (dev->buf_len) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ dev_err(dev->dev,
+ "RRDY IRQ while no data"
+ " requested\n");
+ if (stat & OMAP_I2C_STAT_RDR)
+ dev_err(dev->dev,
+ "RDR IRQ while no data"
+ " requested\n");
+ break;
}
- } else
- dev_err(dev->dev, "RRDY IRQ while no data "
- "requested\n");
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
continue;
}
- if (stat & OMAP_I2C_STAT_XRDY) {
- w = 0;
- if (dev->buf_len) {
- w = *dev->buf++;
- dev->buf_len--;
+ if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = 0;
if (dev->buf_len) {
- w |= *dev->buf++ << 8;
+ w = *dev->buf++;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430()) {
+ if (dev->buf_len) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ dev_err(dev->dev,
+ "XRDY IRQ while no "
+ "data to send\n");
+ if (stat & OMAP_I2C_STAT_XDR)
+ dev_err(dev->dev,
+ "XDR IRQ while no "
+ "data to send\n");
+ break;
}
- } else
- dev_err(dev->dev, "XRDY IRQ while no "
- "data to send\n");
- omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
continue;
}
if (stat & OMAP_I2C_STAT_ROVR) {
@@ -571,18 +674,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
dev->cmd_err |= OMAP_I2C_STAT_ROVR;
}
if (stat & OMAP_I2C_STAT_XUDF) {
- dev_err(dev->dev, "Transmit overflow\n");
+ dev_err(dev->dev, "Transmit underflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF;
}
- if (stat & OMAP_I2C_STAT_NACK) {
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
- }
- if (stat & OMAP_I2C_STAT_AL) {
- dev_err(dev->dev, "Arbitration lost\n");
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
- }
}
return count ? IRQ_HANDLED : IRQ_NONE;
@@ -651,6 +745,22 @@ omap_i2c_probe(struct platform_device *pdev)
if (cpu_is_omap15xx())
dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+ if (cpu_is_omap2430()) {
+ u16 s;
+
+ /* Set up the fifo size - Get total size */
+ s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
+ dev->fifo_size = 0x8 << s;
+
+ /*
+ * Set up notification threshold as half the total available
+ * size. This is to ensure that we can handle the status on int
+ * call back latencies.
+ */
+ dev->fifo_size = (dev->fifo_size / 2);
+ dev->b_hw = 1; /* Enable hardware fixes */
+ }
+
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/12] i2c-omap: Add support for omap34xx
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (3 preceding siblings ...)
2008-11-29 1:28 ` [PATCH 04/12] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 06/12] i2c-omap: Mark init-only functions as __init Tony Lindgren
` (7 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap, chandra shekhar
From: Chandra shekhar <x0044955@ti.com>
Add support for omap34xx
Signed-off-by: chandra shekhar <x0044955@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 20 +++++++++++---------
1 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 9ae4b74..3f7726a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -156,7 +156,7 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) {
dev->iclk = NULL;
@@ -266,7 +266,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
- if (cpu_is_omap2430()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
/* HSI2C controller internal clk rate should be 19.2 Mhz */
internal_clk = 19200;
@@ -608,7 +608,8 @@ omap_i2c_isr(int this_irq, void *dev_id)
*dev->buf++ = w;
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
- if (!cpu_is_omap2430()) {
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
@@ -646,7 +647,8 @@ omap_i2c_isr(int this_irq, void *dev_id)
w = *dev->buf++;
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
- if (!cpu_is_omap2430()) {
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
@@ -694,7 +696,7 @@ omap_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
int r;
- u32 *speed = NULL;
+ u32 speed = 0;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -722,11 +724,11 @@ omap_i2c_probe(struct platform_device *pdev)
}
if (pdev->dev.platform_data != NULL)
- speed = (u32 *) pdev->dev.platform_data;
+ speed = *(u32 *)pdev->dev.platform_data;
else
- *speed = 100; /* Defualt speed */
+ speed = 100; /* Defualt speed */
- dev->speed = *speed;
+ dev->speed = speed;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -745,7 +747,7 @@ omap_i2c_probe(struct platform_device *pdev)
if (cpu_is_omap15xx())
dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
- if (cpu_is_omap2430()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
u16 s;
/* Set up the fifo size - Get total size */
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/12] i2c-omap: Mark init-only functions as __init
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (4 preceding siblings ...)
2008-11-29 1:28 ` [PATCH 05/12] i2c-omap: Add support for omap34xx Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:28 ` [PATCH 07/12] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
` (6 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Paul Walmsley, linux-omap
From: Paul Walmsley <paul@pwsan.com>
Mark functions called only at init time as __init.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 3f7726a..61d2e5a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -154,7 +154,7 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg);
}
-static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
@@ -689,7 +689,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int
+static int __init
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/12] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (5 preceding siblings ...)
2008-11-29 1:28 ` [PATCH 06/12] i2c-omap: Mark init-only functions as __init Tony Lindgren
@ 2008-11-29 1:28 ` Tony Lindgren
2008-11-29 1:29 ` [PATCH 08/12] i2c-omap: Clean-up i2c-omap Tony Lindgren
` (5 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:28 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Paul Walmsley, linux-omap
From: Paul Walmsley <paul@pwsan.com>
Skip compiling OMAP15xx I2C ISR for non-OMAP15xx builds. Saves 400 bytes
of text for most OMAP builds.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 61d2e5a..195c3d1 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -503,6 +503,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+/* rev1 devices are apparently only on some 15xx */
+#ifdef CONFIG_ARCH_OMAP15XX
+
static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id)
{
@@ -557,6 +560,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
+#else
+#define omap_i2c_rev1_isr 0
+#endif
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id)
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/12] i2c-omap: Clean-up i2c-omap
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (6 preceding siblings ...)
2008-11-29 1:28 ` [PATCH 07/12] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
@ 2008-11-29 1:29 ` Tony Lindgren
2008-11-29 1:29 ` [PATCH 09/12] i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un, }idle() Tony Lindgren
` (4 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:29 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap
Minor sparse, checkpatch and formatting clean-up. Also update copyrights.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 31 ++++++++++++++++++-------------
1 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 195c3d1..4aeebad 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Updated to work with multiple I2C interfaces on 24xx by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ * Tony Lindgren <tony@atomide.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * Juha Yrjölä <juha.yrjola@solidboot.com>
+ * Syed Khasim <x0khasim@ti.com>
+ * Nishant Menon <nm@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,8 +36,7 @@
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -204,7 +206,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev1) {
- iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
@@ -321,9 +323,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
- (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
- OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+ OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -389,8 +391,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
+
if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
/*
@@ -468,7 +472,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev);
- if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ r = omap_i2c_wait_for_bb(dev);
+ if (r < 0)
goto out;
for (i = 0; i < num; i++) {
@@ -561,7 +566,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
#else
-#define omap_i2c_rev1_isr 0
+#define omap_i2c_rev1_isr NULL
#endif
static irqreturn_t
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/12] i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un, }idle()
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (7 preceding siblings ...)
2008-11-29 1:29 ` [PATCH 08/12] i2c-omap: Clean-up i2c-omap Tony Lindgren
@ 2008-11-29 1:29 ` Tony Lindgren
2008-11-29 1:29 ` [PATCH 10/12] i2c-omap: convert 'rev1' flag to generic 'rev' u8 Tony Lindgren
` (3 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:29 UTC (permalink / raw)
To: i2c-linux, ben-linux
Cc: David Brownell, Paul Walmsley, linux-omap, Richard Woodruff
From: Paul Walmsley <paul@pwsan.com>
omap_i2c_unidle() and omap_i2c_idle() are called recursively during
omap_i2c_probe(). This is evidently unexpected and will wipe
out the I2C interrupt enable register the second time that
omap_i2c_idle() is called consecutively. Any I2C transactions
following a probe of a bus with at least one device on it will then
time out.
Fix by moving omap_i2c_idle() further up in omap_i2c_probe(). Ensure
the I2C controller is marked as idle before the probe starts. Also
attempt to catch future reappearances of this bug early in development
by warning in omap_i2c_{un,}idle() when they are called recursively.
Problem reported by David Brownell <david-b@pacbell.net>.
Tested on 3430SDP and 2430SDP.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: David Brownell <david-b@pacbell.net>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Acked-by; Steve Sakoman <steve@sakoman.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 4aeebad..40a1e4b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -191,6 +191,8 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
+ WARN_ON(!dev->idle);
+
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
@@ -203,6 +205,8 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
+ WARN_ON(dev->idle);
+
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev1) {
@@ -740,6 +744,7 @@ omap_i2c_probe(struct platform_device *pdev)
speed = 100; /* Defualt speed */
dev->speed = speed;
+ dev->idle = 1;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -788,6 +793,8 @@ omap_i2c_probe(struct platform_device *pdev)
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
pdev->id, r >> 4, r & 0xf, dev->speed);
+ omap_i2c_idle(dev);
+
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
@@ -804,8 +811,6 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
- omap_i2c_idle(dev);
-
return 0;
err_free_irq:
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/12] i2c-omap: convert 'rev1' flag to generic 'rev' u8
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (8 preceding siblings ...)
2008-11-29 1:29 ` [PATCH 09/12] i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un, }idle() Tony Lindgren
@ 2008-11-29 1:29 ` Tony Lindgren
2008-11-29 1:29 ` [PATCH 11/12] i2c-omap: reprogram OCP_SYSCONFIG register after reset Tony Lindgren
` (2 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:29 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Paul Walmsley, linux-omap
From: Paul Walmsley <paul@pwsan.com>
i2c-omap discriminates only between "revision 1" or "greater than
revision 1." A following patch introduces code that must also
discriminate between rev2.x, rev3.6, and rev3.12 controllers. Support
this by storing the full revision data from the I2C_REV register, rather
than just a single bit.
The revision definitions may need to be extended for other ES levels
that aren't currently available here. rev3.6 is what's present on the
2430SDP here (unknown ES revision); rev3.12 is used on the 3430ES2
here.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 25 ++++++++++++++++---------
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 40a1e4b..3ac510d 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -38,6 +38,13 @@
#include <linux/clk.h>
#include <linux/io.h>
+/* I2C controller revisions */
+#define OMAP_I2C_REV_2 0x20
+
+/* I2C controller revisions present on specific hardware */
+#define OMAP_I2C_REV_ON_2430 0x36
+#define OMAP_I2C_REV_ON_3430 0x3C
+
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -139,7 +146,7 @@ struct omap_i2c_dev {
* fifo_size==0 implies no fifo
* if set, should be trsh+1
*/
- unsigned rev1:1;
+ u8 rev;
unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1;
u16 iestate; /* Saved interrupt register */
@@ -209,7 +216,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev1) {
+ if (dev->rev < OMAP_I2C_REV_2) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
@@ -231,7 +238,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
unsigned long timeout;
unsigned long internal_clk = 0;
- if (!dev->rev1) {
+ if (dev->rev >= OMAP_I2C_REV_2) {
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
@@ -710,6 +717,7 @@ omap_i2c_probe(struct platform_device *pdev)
struct omap_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
+ void *isr;
int r;
u32 speed = 0;
@@ -760,8 +768,7 @@ omap_i2c_probe(struct platform_device *pdev)
omap_i2c_unidle(dev);
- if (cpu_is_omap15xx())
- dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+ dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
u16 s;
@@ -782,16 +789,16 @@ omap_i2c_probe(struct platform_device *pdev)
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
- r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
- 0, pdev->name, dev);
+ isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+ r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
}
- r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, r >> 4, r & 0xf, dev->speed);
+ pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
omap_i2c_idle(dev);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 11/12] i2c-omap: reprogram OCP_SYSCONFIG register after reset
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (9 preceding siblings ...)
2008-11-29 1:29 ` [PATCH 10/12] i2c-omap: convert 'rev1' flag to generic 'rev' u8 Tony Lindgren
@ 2008-11-29 1:29 ` Tony Lindgren
2008-11-29 1:29 ` [PATCH 12/12] i2c-omap: Enable I2C wakeups for 34xx Tony Lindgren
2008-11-29 1:31 ` [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:29 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: Paul Walmsley, linux-omap, Richard Woodruff
From: Paul Walmsley <paul@pwsan.com>
The I2C controller clears its OCP_SYSCONFIG register after an OCP soft reset.
Reprogram OCP_SYSCONFIG for maximum power savings on rev3.6 controllers
and beyond. On 2430, this involves setting the module AUTOIDLE bit.
On 3430, this includes module AUTOIDLE, wakeup enable, slave smart-idle,
and considers only the module functional clock state for idle-ack.
Boot-tested on 2430SDP and 3430SDP.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 40 ++++++++++++++++++++++++++++++++++------
1 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 3ac510d..b202354 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -123,11 +123,19 @@
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif
-/* I2C System Status register (OMAP_I2C_SYSS): */
-#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
+/* OCP_SYSSTATUS bit definitions */
+#define SYSS_RESETDONE_MASK (1 << 0)
+
+/* OCP_SYSCONFIG bit definitions */
+#define SYSC_CLOCKACTIVITY_MASK (0x3 << 8)
+#define SYSC_SIDLEMODE_MASK (0x3 << 3)
+#define SYSC_ENAWAKEUP_MASK (1 << 2)
+#define SYSC_SOFTRESET_MASK (1 << 1)
+#define SYSC_AUTOIDLE_MASK (1 << 0)
+
+#define SYSC_IDLEMODE_SMART 0x2
+#define SYSC_CLOCKACTIVITY_FCLK 0x2
-/* I2C System Configuration Register (OMAP_I2C_SYSC): */
-#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
struct omap_i2c_dev {
struct device *dev;
@@ -239,13 +247,13 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
unsigned long internal_clk = 0;
if (dev->rev >= OMAP_I2C_REV_2) {
- omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
- OMAP_I2C_SYSS_RDONE)) {
+ SYSS_RESETDONE_MASK)) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting "
"for controller reset\n");
@@ -253,6 +261,26 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
}
msleep(1);
}
+
+ /* SYSC register is cleared by the reset; rewrite it */
+ if (dev->rev == OMAP_I2C_REV_ON_2430) {
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+ SYSC_AUTOIDLE_MASK);
+
+ } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
+ u32 v;
+
+ v = SYSC_AUTOIDLE_MASK;
+ v |= SYSC_ENAWAKEUP_MASK;
+ v |= (SYSC_IDLEMODE_SMART <<
+ __ffs(SYSC_SIDLEMODE_MASK));
+ v |= (SYSC_CLOCKACTIVITY_FCLK <<
+ __ffs(SYSC_CLOCKACTIVITY_MASK));
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+
+ }
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 12/12] i2c-omap: Enable I2C wakeups for 34xx
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (10 preceding siblings ...)
2008-11-29 1:29 ` [PATCH 11/12] i2c-omap: reprogram OCP_SYSCONFIG register after reset Tony Lindgren
@ 2008-11-29 1:29 ` Tony Lindgren
2008-11-29 1:31 ` [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:29 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap, Kalle Jokiniemi
From: Kalle Jokiniemi <ext-kalle.jokiniemi@nokia.com>
I2C_WE registers were not configured, which caused huge delays in
I2C operations while cpu idle was enabled and omap entered WFI.
This patch enables all I2C wakeup sources.
Signed-off-by: Kalle Jokiniemi <ext-kalle.jokiniemi@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b202354..96f3bed 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -52,6 +52,8 @@
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
+/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
+#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
@@ -89,6 +91,24 @@
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
+/* I2C WE wakeup enable register */
+#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */
+#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */
+#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/
+#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */
+#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */
+#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */
+#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */
+#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */
+#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */
+#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */
+
+#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \
+ OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \
+ OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \
+ OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \
+ OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE)
+
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
@@ -279,6 +299,13 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
__ffs(SYSC_CLOCKACTIVITY_MASK));
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+ /*
+ * Enabling all wakup sources to stop I2C freezing on
+ * WFI instruction.
+ * REVISIT: Some wkup sources might not be needed.
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+ OMAP_I2C_WE_ALL);
}
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
` (11 preceding siblings ...)
2008-11-29 1:29 ` [PATCH 12/12] i2c-omap: Enable I2C wakeups for 34xx Tony Lindgren
@ 2008-11-29 1:31 ` Tony Lindgren
12 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:31 UTC (permalink / raw)
To: i2c-linux, ben-linux; +Cc: linux-omap
* Tony Lindgren <tony@atomide.com> [081128 17:28]:
> Hi all,
>
> Here are the i2c-omap patches again for next merge window.
Oops, please ignore this series, the i2c list address is wrong. Will
resend.
> Regards,
>
> Tony
>
> ---
>
> Chandra shekhar (1):
> i2c-omap: Add support for omap34xx
>
> Jarkko Nikula (1):
> i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
>
> Kalle Jokiniemi (1):
> i2c-omap: Enable I2C wakeups for 34xx
>
> Nishanth Menon (1):
> i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
>
> Paul Walmsley (6):
> i2c-omap: reprogram OCP_SYSCONFIG register after reset
> i2c-omap: convert 'rev1' flag to generic 'rev' u8
> i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un,}idle()
> i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
> i2c-omap: Mark init-only functions as __init
> i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
>
> Syed Mohammed Khasim (1):
> i2c-omap: Add high-speed support to omap-i2c
>
> Tony Lindgren (1):
> i2c-omap: Clean-up i2c-omap
>
>
> arch/arm/mach-omap2/clock24xx.h | 4
> drivers/i2c/busses/i2c-omap.c | 420 ++++++++++++++++++++++++++++++---------
> 2 files changed, 330 insertions(+), 94 deletions(-)
>
> --
> Signature
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/12] i2c-omap: Clean-up i2c-omap
2008-11-29 1:33 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v5 Tony Lindgren
@ 2008-11-29 1:34 ` Tony Lindgren
0 siblings, 0 replies; 15+ messages in thread
From: Tony Lindgren @ 2008-11-29 1:34 UTC (permalink / raw)
To: linux-i2c, ben-linux; +Cc: linux-omap
Minor sparse, checkpatch and formatting clean-up. Also update copyrights.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 31 ++++++++++++++++++-------------
1 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 195c3d1..4aeebad 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Updated to work with multiple I2C interfaces on 24xx by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ * Tony Lindgren <tony@atomide.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * Juha Yrjölä <juha.yrjola@solidboot.com>
+ * Syed Khasim <x0khasim@ti.com>
+ * Nishant Menon <nm@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,8 +36,7 @@
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -204,7 +206,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev1) {
- iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
@@ -321,9 +323,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
- (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
- OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+ OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -389,8 +391,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
+
if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
/*
@@ -468,7 +472,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev);
- if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ r = omap_i2c_wait_for_bb(dev);
+ if (r < 0)
goto out;
for (i = 0; i < num; i++) {
@@ -561,7 +566,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
#else
-#define omap_i2c_rev1_isr 0
+#define omap_i2c_rev1_isr NULL
#endif
static irqreturn_t
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-11-29 1:34 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-29 1:28 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
2008-11-29 1:28 ` [PATCH 01/12] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
2008-11-29 1:28 ` [PATCH 02/12] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
2008-11-29 1:28 ` [PATCH 03/12] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
2008-11-29 1:28 ` [PATCH 04/12] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
2008-11-29 1:28 ` [PATCH 05/12] i2c-omap: Add support for omap34xx Tony Lindgren
2008-11-29 1:28 ` [PATCH 06/12] i2c-omap: Mark init-only functions as __init Tony Lindgren
2008-11-29 1:28 ` [PATCH 07/12] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
2008-11-29 1:29 ` [PATCH 08/12] i2c-omap: Clean-up i2c-omap Tony Lindgren
2008-11-29 1:29 ` [PATCH 09/12] i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un, }idle() Tony Lindgren
2008-11-29 1:29 ` [PATCH 10/12] i2c-omap: convert 'rev1' flag to generic 'rev' u8 Tony Lindgren
2008-11-29 1:29 ` [PATCH 11/12] i2c-omap: reprogram OCP_SYSCONFIG register after reset Tony Lindgren
2008-11-29 1:29 ` [PATCH 12/12] i2c-omap: Enable I2C wakeups for 34xx Tony Lindgren
2008-11-29 1:31 ` [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v4 Tony Lindgren
-- strict thread matches above, loose matches on Subject: below --
2008-11-29 1:33 [PATCH 00/12] Updates for i2c-omap for 2.6.29 merge window, v5 Tony Lindgren
2008-11-29 1:34 ` [PATCH 08/12] i2c-omap: Clean-up i2c-omap Tony Lindgren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox