* [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2
@ 2008-09-25 7:53 Tony Lindgren
2008-09-25 7:53 ` [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
2008-09-29 22:23 ` [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Ben Dooks
0 siblings, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Tony Lindgren
Hi all,
Here's a repost of the whole series, the first series had a compile
error starting with one of the patches. Sorry for the extra noise.
This series contains pending i2c-omap patches from linux-omap tree
for review.
Looks like we've managed to pile up stuff in the omap tree for this
driver again... Anyways, future patches will be coming straight via
the i2c list.
The first two patches could be pushed as fixes to current -rc series,
but I'm fine with them going in later too.
I've left out some clean-up from the last patch so it won't conflict with
omap ioremp changes that are currently in Russell King's devel
branch.
Regards,
Tony
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
2008-09-25 7:53 [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
2008-09-29 22:21 ` [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Ben Dooks
2008-09-29 22:23 ` [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Jarkko Nikula, Juha Yrjola, Tony Lindgren
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 | 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 e7eb7bf..cfb76f5 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -328,8 +328,8 @@ 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);
+ r = wait_for_completion_timeout(&dev->cmd_complete,
+ OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
2008-09-25 7:53 ` [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
2008-09-29 22:21 ` [i2c] [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Ben Dooks
2008-09-29 22:21 ` [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Paul Walmsley, Tony Lindgren
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 | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index cfb76f5..a06ad42 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -181,22 +181,28 @@ 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)
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
else
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
+ /*
+ * The wmb() is to ensure that the I2C interrupt mask write
+ * reaches the I2C controller before the dev->idle store
+ * occurs.
+ */
+ wmb();
+ dev->idle = 1;
clk_disable(dev->fclk);
if (dev->iclk != NULL)
clk_disable(dev->iclk);
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c
2008-09-25 7:53 ` [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
2008-09-29 22:25 ` [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Ben Dooks
2008-09-29 22:21 ` [i2c] [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Syed Mohammed Khasim, Tony Lindgren
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.
Signed-off-by: Syed Mohammed Khasim <x0khasim@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 111 +++++++++++++++++++++++++++++-----------
1 files changed, 80 insertions(+), 31 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index a06ad42..0d30790 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;
@@ -152,17 +152,28 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
return -ENODEV;
}
}
-
- dev->fclk = clk_get(dev->dev, "i2c_fck");
- if (IS_ERR(dev->fclk)) {
- if (dev->iclk != NULL) {
- clk_put(dev->iclk);
- dev->iclk = NULL;
+ /* For I2C operations on 2430 we need 96Mhz clock */
+ if (cpu_is_omap2430()) {
+ dev->fclk = clk_get(dev->dev, "i2chs_fck");
+ if (IS_ERR(dev->fclk)) {
+ if (dev->iclk != NULL) {
+ clk_put(dev->iclk);
+ dev->iclk = NULL;
+ }
+ dev->fclk = NULL;
+ return -ENODEV;
+ }
+ } else {
+ dev->fclk = clk_get(dev->dev, "i2c_fck");
+ if (IS_ERR(dev->fclk)) {
+ if (dev->iclk != NULL) {
+ clk_put(dev->iclk);
+ dev->iclk = NULL;
+ }
+ dev->fclk = NULL;
+ return -ENODEV;
}
- dev->fclk = NULL;
- return -ENODEV;
}
-
return 0;
}
@@ -210,9 +221,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);
@@ -255,18 +268,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);
@@ -326,6 +368,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))
@@ -562,6 +609,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);
@@ -582,17 +630,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 = (void __iomem *) IO_ADDRESS(mem->start);
@@ -618,7 +667,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);
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
2008-09-25 7:53 ` [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
` (2 more replies)
2008-09-29 22:25 ` [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Ben Dooks
1 sibling, 3 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Nishanth Menon, Jason P Marini, Tony Lindgren
From: Nishanth Menon <menon.nishanth@gmail.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 <menon.nishanth@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 189 ++++++++++++++++++++++++++++++++---------
1 files changed, 149 insertions(+), 40 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0d30790..ded4636 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 */
};
@@ -310,6 +321,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);
@@ -317,7 +336,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;
}
@@ -364,6 +384,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;
@@ -371,16 +396,38 @@ 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);
+ }
r = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
@@ -525,7 +572,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;
@@ -540,39 +587,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) {
@@ -580,18 +682,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;
@@ -655,6 +748,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);
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 5/8] i2c-omap: Add support on 34xx
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 6/8] i2c-omap: Mark init-only functions as __init Tony Lindgren
2008-09-29 22:28 ` [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx Ben Dooks
2008-09-25 11:39 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap, v3 Tony Lindgren
2008-09-29 22:27 ` [i2c] [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Ben Dooks
2 siblings, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Chandra shekhar, Tony Lindgren
From: Chandra shekhar <x0044955@ti.com>
Signed-off-by: chandra shekhar <x0044955@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ded4636..b41431a 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;
@@ -279,7 +279,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;
@@ -616,7 +616,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--;
@@ -654,7 +655,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--;
@@ -748,7 +750,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 */
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 6/8] i2c-omap: Mark init-only functions as __init
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
2008-09-29 22:30 ` [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init Ben Dooks
2008-09-29 22:28 ` [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Paul Walmsley, Tony Lindgren
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 b41431a..e71f1f2 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");
@@ -697,7 +697,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;
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-25 7:53 ` [PATCH 6/8] i2c-omap: Mark init-only functions as __init Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 7:53 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap Tony Lindgren
2008-09-29 22:29 ` [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Ben Dooks
2008-09-29 22:30 ` [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Paul Walmsley, Tony Lindgren
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 | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index e71f1f2..5c54864 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -511,6 +511,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)
{
@@ -565,6 +568,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)
@@ -843,14 +849,14 @@ static struct platform_driver omap_i2c_driver = {
};
/* I2C may be needed to bring up other drivers */
-static int __init
+static int __devinit
omap_i2c_init_driver(void)
{
return platform_driver_register(&omap_i2c_driver);
}
subsys_initcall(omap_i2c_init_driver);
-static void __exit omap_i2c_exit_driver(void)
+static void __devexit omap_i2c_exit_driver(void)
{
platform_driver_unregister(&omap_i2c_driver);
}
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 8/8] i2c-omap: Clean-up i2c-omap
2008-09-25 7:53 ` [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
@ 2008-09-25 7:53 ` Tony Lindgren
2008-09-25 11:40 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap, v3 Tony Lindgren
2008-09-29 22:31 ` [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap Ben Dooks
2008-09-29 22:29 ` [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Ben Dooks
1 sibling, 2 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 7:53 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Tony Lindgren
Minor checkpatch and formatting clean-up. Also update copyrights.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 28 ++++++++++++++++------------
1 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5c54864..a41b655 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,15 @@
* 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@nokia.com>
+ * Syed Khasim <x0khasim@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 +35,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))
@@ -215,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)
- 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);
/*
@@ -334,9 +335,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;
}
@@ -402,8 +403,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);
/*
@@ -476,7 +479,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++) {
--
1.5.6.rc3.21.g8c6b5
--
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] 33+ messages in thread
* Re: [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap, v3
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
@ 2008-09-25 11:39 ` Tony Lindgren
2008-09-29 22:27 ` [i2c] [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Ben Dooks
2 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 11:39 UTC (permalink / raw)
To: i2c; +Cc: linux-omap, Nishanth Menon, Jason P Marini
[-- Attachment #1: Type: text/plain, Size: 704 bytes --]
* Tony Lindgren <tony@atomide.com> [080925 10:54]:
> From: Nishanth Menon <menon.nishanth@gmail.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 <menon.nishanth@gmail.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
Here's this one update with current email address for Nishant
Menon as requested by Nishant.
Tony
[-- Attachment #2: 0004-i2c-omap-FIFO-handling-support-and-broken-hw-workar.patch --]
[-- Type: text/x-diff, Size: 10444 bytes --]
>From 5ee572214da6efd0dfbd3765616caa0f03aca25d Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 25 Sep 2008 10:46:43 +0300
Subject: [PATCH] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
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 | 189 ++++++++++++++++++++++++++++++++---------
1 files changed, 149 insertions(+), 40 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0d30790..ded4636 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 */
};
@@ -310,6 +321,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);
@@ -317,7 +336,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;
}
@@ -364,6 +384,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;
@@ -371,16 +396,38 @@ 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);
+ }
r = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
@@ -525,7 +572,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;
@@ -540,39 +587,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) {
@@ -580,18 +682,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;
@@ -655,6 +748,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);
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 8/8] i2c-omap: Clean-up i2c-omap, v3
2008-09-25 7:53 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap Tony Lindgren
@ 2008-09-25 11:40 ` Tony Lindgren
2008-09-29 22:31 ` [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap Ben Dooks
1 sibling, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-09-25 11:40 UTC (permalink / raw)
To: i2c; +Cc: linux-omap
[-- Attachment #1: Type: text/plain, Size: 201 bytes --]
* Tony Lindgren <tony@atomide.com> [080925 10:55]:
> Minor checkpatch and formatting clean-up. Also update copyrights.
Here's this one updated with correct email addresses for Juha
and Nishant.
Tony
[-- Attachment #2: 0008-i2c-omap-Clean-up-i2c-omap.patch --]
[-- Type: text/x-diff, Size: 3144 bytes --]
>From 738680e6b79e87132b6cdb15a0b9727b381b87ac Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Thu, 25 Sep 2008 14:35:16 +0300
Subject: [PATCH] i2c-omap: Clean-up i2c-omap
Minor checkpatch and formatting clean-up. Also update copyrights.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/i2c/busses/i2c-omap.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5c54864..7308648 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))
@@ -215,7 +217,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);
/*
@@ -334,9 +336,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;
}
@@ -402,8 +404,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);
/*
@@ -476,7 +480,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++) {
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
2008-09-25 7:53 ` [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
2008-09-25 7:53 ` [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
@ 2008-09-29 22:21 ` Ben Dooks
2008-09-30 11:51 ` Jarkko Nikula
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:21 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, Juha Yrjola, linux-omap, Jarkko Nikula
On Thu, Sep 25, 2008 at 10:53:47AM +0300, Tony Lindgren wrote:
> 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.
I assume that this is preferable to aborting an transfer when the
signal is caught (if possible) ?
> 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 | 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 e7eb7bf..cfb76f5 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -328,8 +328,8 @@ 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);
> + r = wait_for_completion_timeout(&dev->cmd_complete,
> + OMAP_I2C_TIMEOUT);
> dev->buf_len = 0;
> if (r < 0)
> return r;
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
2008-09-25 7:53 ` [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
2008-09-25 7:53 ` [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
@ 2008-09-29 22:21 ` Ben Dooks
1 sibling, 0 replies; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:21 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, Paul Walmsley, linux-omap
On Thu, Sep 25, 2008 at 10:53:48AM +0300, Tony Lindgren wrote:
> 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!
that looks ok.
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 10 ++++++++--
> 1 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index cfb76f5..a06ad42 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -181,22 +181,28 @@ 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)
> iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
> else
> omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
> + /*
> + * The wmb() is to ensure that the I2C interrupt mask write
> + * reaches the I2C controller before the dev->idle store
> + * occurs.
> + */
> + wmb();
> + dev->idle = 1;
> clk_disable(dev->fclk);
> if (dev->iclk != NULL)
> clk_disable(dev->iclk);
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2
2008-09-25 7:53 [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Tony Lindgren
2008-09-25 7:53 ` [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
@ 2008-09-29 22:23 ` Ben Dooks
2008-09-30 5:35 ` Tony Lindgren
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:23 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, linux-omap
On Thu, Sep 25, 2008 at 10:53:46AM +0300, Tony Lindgren wrote:
> Hi all,
>
> Here's a repost of the whole series, the first series had a compile
> error starting with one of the patches. Sorry for the extra noise.
>
> This series contains pending i2c-omap patches from linux-omap tree
> for review.
>
> Looks like we've managed to pile up stuff in the omap tree for this
> driver again... Anyways, future patches will be coming straight via
> the i2c list.
>
> The first two patches could be pushed as fixes to current -rc series,
> but I'm fine with them going in later too.
It is too late in the -rc series, and it will be easier to push the
lot in one go.
> I've left out some clean-up from the last patch so it won't conflict with
> omap ioremp changes that are currently in Russell King's devel
> branch.
If you can provide an url to a git tree to pull, that'd be great,
otherwise I'll apply from the series unless anyone else decides
there are problems with it.
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c
2008-09-25 7:53 ` [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
@ 2008-09-29 22:25 ` Ben Dooks
2008-10-17 15:37 ` Tony Lindgren
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:25 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, linux-omap, Syed Mohammed Khasim
On Thu, Sep 25, 2008 at 10:53:49AM +0300, Tony Lindgren wrote:
> 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.
>
> Signed-off-by: Syed Mohammed Khasim <x0khasim@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 111 +++++++++++++++++++++++++++++-----------
> 1 files changed, 80 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index a06ad42..0d30790 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;
> @@ -152,17 +152,28 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
> return -ENODEV;
> }
> }
> -
> - dev->fclk = clk_get(dev->dev, "i2c_fck");
> - if (IS_ERR(dev->fclk)) {
> - if (dev->iclk != NULL) {
> - clk_put(dev->iclk);
> - dev->iclk = NULL;
> + /* For I2C operations on 2430 we need 96Mhz clock */
> + if (cpu_is_omap2430()) {
> + dev->fclk = clk_get(dev->dev, "i2chs_fck");
> + if (IS_ERR(dev->fclk)) {
> + if (dev->iclk != NULL) {
> + clk_put(dev->iclk);
> + dev->iclk = NULL;
> + }
I'm sorry, but I think this is mis-use of the clock system. The
actual name of the clock should be provided for the driver, not
the driver having to search for different clocks.
> + dev->fclk = NULL;
> + return -ENODEV;
> + }
> + } else {
> + dev->fclk = clk_get(dev->dev, "i2c_fck");
> + if (IS_ERR(dev->fclk)) {
> + if (dev->iclk != NULL) {
> + clk_put(dev->iclk);
> + dev->iclk = NULL;
> + }
> + dev->fclk = NULL;
> + return -ENODEV;
> }
> - dev->fclk = NULL;
> - return -ENODEV;
> }
> -
> return 0;
> }
>
> @@ -210,9 +221,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);
> @@ -255,18 +268,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);
> @@ -326,6 +368,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))
> @@ -562,6 +609,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);
> @@ -582,17 +630,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 = (void __iomem *) IO_ADDRESS(mem->start);
> @@ -618,7 +667,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);
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
2008-09-25 11:39 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap, v3 Tony Lindgren
@ 2008-09-29 22:27 ` Ben Dooks
2 siblings, 0 replies; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:27 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, linux-omap, Jason P Marini
On Thu, Sep 25, 2008 at 10:53:50AM +0300, Tony Lindgren wrote:
> From: Nishanth Menon <menon.nishanth@gmail.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.
This looks ok
> Signed-off-by: Jason P Marini <jason.marini@gmail.com>
> Signed-off-by: Nishanth Menon <menon.nishanth@gmail.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 189 ++++++++++++++++++++++++++++++++---------
> 1 files changed, 149 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 0d30790..ded4636 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 */
> };
> @@ -310,6 +321,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);
>
> @@ -317,7 +336,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;
> }
>
> @@ -364,6 +384,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;
>
> @@ -371,16 +396,38 @@ 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);
> + }
> r = wait_for_completion_timeout(&dev->cmd_complete,
> OMAP_I2C_TIMEOUT);
> dev->buf_len = 0;
> @@ -525,7 +572,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;
> @@ -540,39 +587,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) {
> @@ -580,18 +682,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;
> @@ -655,6 +748,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;
how about some constants for these instead of us having to guess what
is going on here?
> + 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);
>
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
2008-09-25 7:53 ` [PATCH 6/8] i2c-omap: Mark init-only functions as __init Tony Lindgren
@ 2008-09-29 22:28 ` Ben Dooks
2008-10-17 15:38 ` Tony Lindgren
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:28 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, linux-omap, Chandra shekhar
On Thu, Sep 25, 2008 at 10:53:51AM +0300, Tony Lindgren wrote:
> From: Chandra shekhar <x0044955@ti.com>
Not very informative description in here. At lease you could have
copied the subject?
> Signed-off-by: chandra shekhar <x0044955@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 12 +++++++-----
> 1 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index ded4636..b41431a 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;
> @@ -279,7 +279,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;
> @@ -616,7 +616,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--;
> @@ -654,7 +655,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--;
> @@ -748,7 +750,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 */
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-25 7:53 ` [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
2008-09-25 7:53 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap Tony Lindgren
@ 2008-09-29 22:29 ` Ben Dooks
2008-09-29 23:06 ` David Brownell
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:29 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, Paul Walmsley, linux-omap
On Thu, Sep 25, 2008 at 10:53:53AM +0300, Tony Lindgren wrote:
> From: Paul Walmsley <paul@pwsan.com>
>
> Skip compiling OMAP15xx I2C ISR for non-OMAP15xx builds. Saves 400 bytes
> of text for most OMAP builds.
you've sneaked in __devinit/__devexit changes into this patch,
I'm going to put my foot down on that.
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 10 ++++++++--
> 1 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index e71f1f2..5c54864 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -511,6 +511,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)
> {
> @@ -565,6 +568,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)
> @@ -843,14 +849,14 @@ static struct platform_driver omap_i2c_driver = {
> };
>
> /* I2C may be needed to bring up other drivers */
> -static int __init
> +static int __devinit
> omap_i2c_init_driver(void)
> {
> return platform_driver_register(&omap_i2c_driver);
> }
> subsys_initcall(omap_i2c_init_driver);
>
> -static void __exit omap_i2c_exit_driver(void)
> +static void __devexit omap_i2c_exit_driver(void)
a differerent change to the one advertised.
> {
> platform_driver_unregister(&omap_i2c_driver);
> }
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init
2008-09-25 7:53 ` [PATCH 6/8] i2c-omap: Mark init-only functions as __init Tony Lindgren
2008-09-25 7:53 ` [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
@ 2008-09-29 22:30 ` Ben Dooks
2008-10-17 15:39 ` Tony Lindgren
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:30 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, Paul Walmsley, linux-omap
On Thu, Sep 25, 2008 at 10:53:52AM +0300, Tony Lindgren wrote:
> From: Paul Walmsley <paul@pwsan.com>
>
> Mark functions called only at init time as __init.
surely these should be __devinit in case of hotplugged-ness?
> 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 b41431a..e71f1f2 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");
> @@ -697,7 +697,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;
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap
2008-09-25 7:53 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap Tony Lindgren
2008-09-25 11:40 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap, v3 Tony Lindgren
@ 2008-09-29 22:31 ` Ben Dooks
2008-10-17 15:41 ` Tony Lindgren
1 sibling, 1 reply; 33+ messages in thread
From: Ben Dooks @ 2008-09-29 22:31 UTC (permalink / raw)
To: Tony Lindgren; +Cc: i2c, linux-omap
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 3798 bytes --]
On Thu, Sep 25, 2008 at 10:53:54AM +0300, Tony Lindgren wrote:
> Minor checkpatch and formatting clean-up. Also update copyrights.
looks ok, assuming it doesn't get broken by any changes
from the review comments i've made earlier in the series.
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> drivers/i2c/busses/i2c-omap.c | 28 ++++++++++++++++------------
> 1 files changed, 16 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 5c54864..a41b655 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -2,13 +2,15 @@
> * 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@nokia.com>
> + * Syed Khasim <x0khasim@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 +35,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))
> @@ -215,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)
> - 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);
> /*
> @@ -334,9 +335,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;
> }
> @@ -402,8 +403,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);
>
> /*
> @@ -476,7 +479,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++) {
> --
> 1.5.6.rc3.21.g8c6b5
>
>
> _______________________________________________
> i2c mailing list
> i2c@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
--
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] 33+ messages in thread
* Re: [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-29 22:29 ` [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Ben Dooks
@ 2008-09-29 23:06 ` David Brownell
2008-09-30 5:35 ` Paul Walmsley
0 siblings, 1 reply; 33+ messages in thread
From: David Brownell @ 2008-09-29 23:06 UTC (permalink / raw)
To: Ben Dooks; +Cc: Tony Lindgren, i2c, Paul Walmsley, linux-omap
On Monday 29 September 2008, Ben Dooks wrote:
> > -static void __exit omap_i2c_exit_driver(void)
> > +static void __devexit omap_i2c_exit_driver(void)
>
> a differerent change to the one advertised.
>
> > {
> > platform_driver_unregister(&omap_i2c_driver);
> > }
And incorrect too.
--
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] 33+ messages in thread
* Re: [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2
2008-09-29 22:23 ` [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Ben Dooks
@ 2008-09-30 5:35 ` Tony Lindgren
2008-10-17 16:04 ` git-pull request for i2c-omap changes (Re: [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2) Tony Lindgren
0 siblings, 1 reply; 33+ messages in thread
From: Tony Lindgren @ 2008-09-30 5:35 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, linux-omap
* Ben Dooks <ben-linux@fluff.org> [080930 01:23]:
> On Thu, Sep 25, 2008 at 10:53:46AM +0300, Tony Lindgren wrote:
> > Hi all,
> >
> > Here's a repost of the whole series, the first series had a compile
> > error starting with one of the patches. Sorry for the extra noise.
> >
> > This series contains pending i2c-omap patches from linux-omap tree
> > for review.
> >
> > Looks like we've managed to pile up stuff in the omap tree for this
> > driver again... Anyways, future patches will be coming straight via
> > the i2c list.
> >
> > The first two patches could be pushed as fixes to current -rc series,
> > but I'm fine with them going in later too.
>
> It is too late in the -rc series, and it will be easier to push the
> lot in one go.
OK
> > I've left out some clean-up from the last patch so it won't conflict with
> > omap ioremp changes that are currently in Russell King's devel
> > branch.
>
> If you can provide an url to a git tree to pull, that'd be great,
> otherwise I'll apply from the series unless anyone else decides
> there are problems with it.
Thanks for looking, I'll fix the issues you commented on and will
repost. It may take a few days before I can get back on this again
though.
Tony
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-29 23:06 ` David Brownell
@ 2008-09-30 5:35 ` Paul Walmsley
2008-09-30 5:36 ` Paul Walmsley
0 siblings, 1 reply; 33+ messages in thread
From: Paul Walmsley @ 2008-09-30 5:35 UTC (permalink / raw)
To: David Brownell; +Cc: Ben Dooks, Tony Lindgren, i2c, linux-omap
[-- Attachment #1: Type: TEXT/PLAIN, Size: 441 bytes --]
Hello Ben, David,
On Mon, 29 Sep 2008, David Brownell wrote:
> On Monday 29 September 2008, Ben Dooks wrote:
> > > -static void __exit omap_i2c_exit_driver(void)
> > > +static void __devexit omap_i2c_exit_driver(void)
> >
> > a differerent change to the one advertised.
> >
> > > {
> > > platform_driver_unregister(&omap_i2c_driver);
> > > }
>
> And incorrect too.
Indeed, will split and resubmit.
- Paul
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-30 5:35 ` Paul Walmsley
@ 2008-09-30 5:36 ` Paul Walmsley
2008-10-17 15:40 ` Tony Lindgren
0 siblings, 1 reply; 33+ messages in thread
From: Paul Walmsley @ 2008-09-30 5:36 UTC (permalink / raw)
To: David Brownell; +Cc: Ben Dooks, Tony Lindgren, i2c, linux-omap
[-- Attachment #1: Type: TEXT/PLAIN, Size: 551 bytes --]
On Mon, 29 Sep 2008, Paul Walmsley wrote:
> Hello Ben, David,
>
> On Mon, 29 Sep 2008, David Brownell wrote:
>
> > On Monday 29 September 2008, Ben Dooks wrote:
> > > > -static void __exit omap_i2c_exit_driver(void)
> > > > +static void __devexit omap_i2c_exit_driver(void)
> > >
> > > a differerent change to the one advertised.
> > >
> > > > {
> > > > platform_driver_unregister(&omap_i2c_driver);
> > > > }
> >
> > And incorrect too.
>
> Indeed, will split and resubmit.
(and change to __init/__exit)
- Paul
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
2008-09-29 22:21 ` [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Ben Dooks
@ 2008-09-30 11:51 ` Jarkko Nikula
2008-10-17 15:35 ` Tony Lindgren
0 siblings, 1 reply; 33+ messages in thread
From: Jarkko Nikula @ 2008-09-30 11:51 UTC (permalink / raw)
To: ext Ben Dooks; +Cc: Tony Lindgren, i2c, Juha Yrjola, linux-omap
On Mon, 29 Sep 2008 23:21:00 +0100
"ext Ben Dooks" <ben-linux@fluff.org> wrote:
> On Thu, Sep 25, 2008 at 10:53:47AM +0300, Tony Lindgren wrote:
> > 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.
>
> I assume that this is preferable to aborting an transfer when the
> signal is caught (if possible) ?
>
Most probably yes as long as the stop condition is generated
successfully. IRCC bug behind this fix, OMAP I2C went into bus
arbitration without code able to recover easily or something like that.
Would it be ok to let this fix as now, probably adding FIXME line near
wait_for_completion_timeout so that we don't break anything now but
note that this is not optimal fix?
Jarkko
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
2008-09-30 11:51 ` Jarkko Nikula
@ 2008-10-17 15:35 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:35 UTC (permalink / raw)
To: Jarkko Nikula; +Cc: ext Ben Dooks, i2c, Juha Yrjola, linux-omap
[-- Attachment #1: Type: text/plain, Size: 1308 bytes --]
* Jarkko Nikula <jarkko.nikula@nokia.com> [080930 04:52]:
> On Mon, 29 Sep 2008 23:21:00 +0100
> "ext Ben Dooks" <ben-linux@fluff.org> wrote:
>
> > On Thu, Sep 25, 2008 at 10:53:47AM +0300, Tony Lindgren wrote:
> > > 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.
> >
> > I assume that this is preferable to aborting an transfer when the
> > signal is caught (if possible) ?
> >
> Most probably yes as long as the stop condition is generated
> successfully. IRCC bug behind this fix, OMAP I2C went into bus
> arbitration without code able to recover easily or something like that.
>
> Would it be ok to let this fix as now, probably adding FIXME line near
> wait_for_completion_timeout so that we don't break anything now but
> note that this is not optimal fix?
Here's this one updated with a comment.
Tony
[-- Attachment #2: 0001-i2c-omap-Do-not-use-interruptible-wait-call-in-omap.patch --]
[-- Type: text/x-diff, Size: 1670 bytes --]
>From d93aaaf440acb6705c2eac4fc7ee8c9a4f32580f Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Fri, 17 Oct 2008 07:16:49 -0700
Subject: [PATCH] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg
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;
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c
2008-09-29 22:25 ` [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Ben Dooks
@ 2008-10-17 15:37 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:37 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, linux-omap, Syed Mohammed Khasim, Russell King
[-- Attachment #1: Type: text/plain, Size: 8412 bytes --]
* Ben Dooks <ben-linux@fluff.org> [080929 15:26]:
> On Thu, Sep 25, 2008 at 10:53:49AM +0300, Tony Lindgren wrote:
> > 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.
> >
> > Signed-off-by: Syed Mohammed Khasim <x0khasim@ti.com>
> > Signed-off-by: Tony Lindgren <tony@atomide.com>
> > ---
> > drivers/i2c/busses/i2c-omap.c | 111 +++++++++++++++++++++++++++++-----------
> > 1 files changed, 80 insertions(+), 31 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> > index a06ad42..0d30790 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;
> > @@ -152,17 +152,28 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
> > return -ENODEV;
> > }
> > }
> > -
> > - dev->fclk = clk_get(dev->dev, "i2c_fck");
> > - if (IS_ERR(dev->fclk)) {
> > - if (dev->iclk != NULL) {
> > - clk_put(dev->iclk);
> > - dev->iclk = NULL;
> > + /* For I2C operations on 2430 we need 96Mhz clock */
> > + if (cpu_is_omap2430()) {
> > + dev->fclk = clk_get(dev->dev, "i2chs_fck");
> > + if (IS_ERR(dev->fclk)) {
> > + if (dev->iclk != NULL) {
> > + clk_put(dev->iclk);
> > + dev->iclk = NULL;
> > + }
>
> I'm sorry, but I think this is mis-use of the clock system. The
> actual name of the clock should be provided for the driver, not
> the driver having to search for different clocks.
Here's this one fixed in arch/arm/mach-omap2/clock24xx.h. I've also
added Russell to the Cc.
Tony
>
> > + dev->fclk = NULL;
> > + return -ENODEV;
> > + }
> > + } else {
> > + dev->fclk = clk_get(dev->dev, "i2c_fck");
> > + if (IS_ERR(dev->fclk)) {
> > + if (dev->iclk != NULL) {
> > + clk_put(dev->iclk);
> > + dev->iclk = NULL;
> > + }
> > + dev->fclk = NULL;
> > + return -ENODEV;
> > }
> > - dev->fclk = NULL;
> > - return -ENODEV;
> > }
> > -
> > return 0;
> > }
> >
> > @@ -210,9 +221,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);
> > @@ -255,18 +268,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);
> > @@ -326,6 +368,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))
> > @@ -562,6 +609,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);
> > @@ -582,17 +630,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 = (void __iomem *) IO_ADDRESS(mem->start);
> > @@ -618,7 +667,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);
> > --
> > 1.5.6.rc3.21.g8c6b5
> >
> >
> > _______________________________________________
> > i2c mailing list
> > i2c@lm-sensors.org
> > http://lists.lm-sensors.org/mailman/listinfo/i2c
>
> --
> Ben (ben@fluff.org, http://www.fluff.org/)
>
> 'a smiley only costs 4 bytes'
[-- Attachment #2: 0003-i2c-omap-Add-high-speed-support-to-omap-i2c.patch --]
[-- Type: text/x-diff, Size: 6977 bytes --]
>From 4417355fe48c037c768ed2a3ba7fb56351625fce Mon Sep 17 00:00:00 2001
From: Syed Mohammed Khasim <x0khasim@ti.com>
Date: Fri, 17 Oct 2008 07:31:06 -0700
Subject: [PATCH] i2c-omap: Add high-speed support to omap-i2c
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 489abd5..ff1b76c 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;
@@ -210,9 +210,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);
@@ -255,18 +257,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);
@@ -326,6 +357,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))
@@ -566,6 +602,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);
@@ -586,17 +623,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);
@@ -627,7 +665,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);
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx
2008-09-29 22:28 ` [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx Ben Dooks
@ 2008-10-17 15:38 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:38 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, linux-omap, Chandra shekhar
[-- Attachment #1: Type: text/plain, Size: 2750 bytes --]
* Ben Dooks <ben-linux@fluff.org> [080929 15:28]:
> On Thu, Sep 25, 2008 at 10:53:51AM +0300, Tony Lindgren wrote:
> > From: Chandra shekhar <x0044955@ti.com>
>
> Not very informative description in here. At lease you could have
> copied the subject?
Here's this one updated.
Tony
>
> > Signed-off-by: chandra shekhar <x0044955@ti.com>
> > Signed-off-by: Tony Lindgren <tony@atomide.com>
> > ---
> > drivers/i2c/busses/i2c-omap.c | 12 +++++++-----
> > 1 files changed, 7 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> > index ded4636..b41431a 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;
> > @@ -279,7 +279,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;
> > @@ -616,7 +616,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--;
> > @@ -654,7 +655,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--;
> > @@ -748,7 +750,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 */
> > --
> > 1.5.6.rc3.21.g8c6b5
> >
> >
> > _______________________________________________
> > i2c mailing list
> > i2c@lm-sensors.org
> > http://lists.lm-sensors.org/mailman/listinfo/i2c
>
> --
> Ben (ben@fluff.org, http://www.fluff.org/)
>
> 'a smiley only costs 4 bytes'
[-- Attachment #2: 0005-i2c-omap-Add-support-for-omap34xx.patch --]
[-- Type: text/x-diff, Size: 2204 bytes --]
>From e5bba093a9541e2943f8e582bd459343d9574b38 Mon Sep 17 00:00:00 2001
From: Chandra shekhar <x0044955@ti.com>
Date: Fri, 17 Oct 2008 07:44:01 -0700
Subject: [PATCH] i2c-omap: Add support for omap34xx
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 | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index a87e21c..5dd8a24 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;
@@ -268,7 +268,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;
@@ -611,7 +611,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--;
@@ -649,7 +650,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--;
@@ -748,7 +750,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 */
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init
2008-09-29 22:30 ` [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init Ben Dooks
@ 2008-10-17 15:39 ` Tony Lindgren
2008-10-17 17:07 ` Tony Lindgren
0 siblings, 1 reply; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:39 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, Paul Walmsley, linux-omap
[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]
* Ben Dooks <ben-linux@fluff.org> [080929 15:30]:
> On Thu, Sep 25, 2008 at 10:53:52AM +0300, Tony Lindgren wrote:
> > From: Paul Walmsley <paul@pwsan.com>
> >
> > Mark functions called only at init time as __init.
>
> surely these should be __devinit in case of hotplugged-ness?
Here's this one fixed.
Tony
>
> > 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 b41431a..e71f1f2 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");
> > @@ -697,7 +697,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;
> > --
> > 1.5.6.rc3.21.g8c6b5
> >
> >
> > _______________________________________________
> > i2c mailing list
> > i2c@lm-sensors.org
> > http://lists.lm-sensors.org/mailman/listinfo/i2c
>
> --
> Ben (ben@fluff.org, http://www.fluff.org/)
>
> 'a smiley only costs 4 bytes'
[-- Attachment #2: 0006-i2c-omap-Mark-init-only-functions-as-__init.patch --]
[-- Type: text/x-diff, Size: 1247 bytes --]
>From 168065ac952d019a1a578c2cdc46df4ef01044c2 Mon Sep 17 00:00:00 2001
From: Paul Walmsley <paul@pwsan.com>
Date: Fri, 17 Oct 2008 07:44:58 -0700
Subject: [PATCH] i2c-omap: Mark init-only functions as __init
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 5dd8a24..018d284 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 __devinit 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");
@@ -692,7 +692,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int
+static int __devinit
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
2008-09-30 5:36 ` Paul Walmsley
@ 2008-10-17 15:40 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:40 UTC (permalink / raw)
To: Paul Walmsley; +Cc: David Brownell, Ben Dooks, i2c, linux-omap
[-- Attachment #1: Type: text/plain, Size: 677 bytes --]
* Paul Walmsley <paul@booyaka.com> [080929 22:36]:
> On Mon, 29 Sep 2008, Paul Walmsley wrote:
>
> > Hello Ben, David,
> >
> > On Mon, 29 Sep 2008, David Brownell wrote:
> >
> > > On Monday 29 September 2008, Ben Dooks wrote:
> > > > > -static void __exit omap_i2c_exit_driver(void)
> > > > > +static void __devexit omap_i2c_exit_driver(void)
> > > >
> > > > a differerent change to the one advertised.
> > > >
> > > > > {
> > > > > platform_driver_unregister(&omap_i2c_driver);
> > > > > }
> > >
> > > And incorrect too.
> >
> > Indeed, will split and resubmit.
>
> (and change to __init/__exit)
Here's this one with the __init/__exit changes removed.
Tony
[-- Attachment #2: 0007-i2c-omap-Don-t-compile-in-OMAP15xx-I2C-ISR-for-non.patch --]
[-- Type: text/x-diff, Size: 1221 bytes --]
>From 6e8249e9d1aa28bda2c0123542582104635a0a83 Mon Sep 17 00:00:00 2001
From: Paul Walmsley <paul@pwsan.com>
Date: Fri, 17 Oct 2008 07:46:56 -0700
Subject: [PATCH] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
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 018d284..5560064 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -506,6 +506,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)
{
@@ -560,6 +563,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)
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap
2008-09-29 22:31 ` [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap Ben Dooks
@ 2008-10-17 15:41 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 15:41 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, linux-omap
[-- Attachment #1: Type: text/plain, Size: 416 bytes --]
* Ben Dooks <ben-linux@fluff.org> [080929 15:31]:
> On Thu, Sep 25, 2008 at 10:53:54AM +0300, Tony Lindgren wrote:
> > Minor checkpatch and formatting clean-up. Also update copyrights.
>
> looks ok, assuming it doesn't get broken by any changes
> from the review comments i've made earlier in the series.
Here's this one updated with one sparse fix to change the
#define omap_i2c_rev1_isr NULL instead of 0.
Tony
[-- Attachment #2: 0008-i2c-omap-Clean-up-i2c-omap.patch --]
[-- Type: text/x-diff, Size: 3345 bytes --]
>From 8537c8bb8753f3e3c5dd23ec15ba59c3562812a1 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Fri, 17 Oct 2008 07:49:27 -0700
Subject: [PATCH] i2c-omap: Clean-up i2c-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 5560064..17166a2 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);
/*
@@ -323,9 +325,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;
}
@@ -391,8 +393,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);
/*
@@ -471,7 +475,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++) {
@@ -564,7 +569,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
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
* git-pull request for i2c-omap changes (Re: [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2)
2008-09-30 5:35 ` Tony Lindgren
@ 2008-10-17 16:04 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 16:04 UTC (permalink / raw)
To: Ben Dooks; +Cc: i2c, linux-omap
[-- Attachment #1: Type: text/plain, Size: 1849 bytes --]
* Tony Lindgren <tony@atomide.com> [080929 22:33]:
> * Ben Dooks <ben-linux@fluff.org> [080930 01:23]:
> > On Thu, Sep 25, 2008 at 10:53:46AM +0300, Tony Lindgren wrote:
> > > Hi all,
> > >
> > > Here's a repost of the whole series, the first series had a compile
> > > error starting with one of the patches. Sorry for the extra noise.
> > >
> > > This series contains pending i2c-omap patches from linux-omap tree
> > > for review.
> > >
> > > Looks like we've managed to pile up stuff in the omap tree for this
> > > driver again... Anyways, future patches will be coming straight via
> > > the i2c list.
> > >
> > > The first two patches could be pushed as fixes to current -rc series,
> > > but I'm fine with them going in later too.
> >
> > It is too late in the -rc series, and it will be easier to push the
> > lot in one go.
>
> OK
>
> > > I've left out some clean-up from the last patch so it won't conflict with
> > > omap ioremp changes that are currently in Russell King's devel
> > > branch.
> >
> > If you can provide an url to a git tree to pull, that'd be great,
> > otherwise I'll apply from the series unless anyone else decides
> > there are problems with it.
>
> Thanks for looking, I'll fix the issues you commented on and will
> repost. It may take a few days before I can get back on this again
> though.
Sorry for the delay in fixing these issues. Hopefully there's still
some time to get these in..
The minimal omap34xx support hit mainline yesterday, so if these
still can get integrated, people will be able to work on a bunch of
related drivers against the mainline.
This would enable at least drivers/mfd/twl4030*, and all the twl4030
related drivers. And also USB OTG for MUSB can be worked on. The twl4030
core code should be queued for integration, and MUSB stuff is already
integrated.
Regards,
Tony
[-- Attachment #2: pull --]
[-- Type: text/plain, Size: 1162 bytes --]
The following changes since commit 2e532d68a2b3e2aa6b19731501222069735c741c:
Linus Torvalds (1):
{pci,pnp} quirks.c: don't use deprecated print_fn_descriptor_symbol()
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git i2c-for-ben
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
Nishanth Menon (1):
i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
Paul Walmsley (4):
i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr()
i2c-omap: Mark init-only functions as __init
i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds
i2c-omap: fix I2C timeouts due to recursive omap_i2c_{un,}idle()
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 | 335 ++++++++++++++++++++++++++++++---------
2 files changed, 258 insertions(+), 81 deletions(-)
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init
2008-10-17 15:39 ` Tony Lindgren
@ 2008-10-17 17:07 ` Tony Lindgren
0 siblings, 0 replies; 33+ messages in thread
From: Tony Lindgren @ 2008-10-17 17:07 UTC (permalink / raw)
To: Ben Dooks; +Cc: Paul Walmsley, linux-omap, i2c
[-- Attachment #1: Type: text/plain, Size: 2003 bytes --]
* Tony Lindgren <tony@atomide.com> [081017 08:40]:
> * Ben Dooks <ben-linux@fluff.org> [080929 15:30]:
> > On Thu, Sep 25, 2008 at 10:53:52AM +0300, Tony Lindgren wrote:
> > > From: Paul Walmsley <paul@pwsan.com>
> > >
> > > Mark functions called only at init time as __init.
> >
> > surely these should be __devinit in case of hotplugged-ness?
>
> Here's this one fixed.
Sorry, these should be __init, not __devinit as they are called from
platform_driver_register(), not i2c_add_driver(). Updated patch
again to revert to the original version.
>
> Tony
>
>
> >
> > > 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 b41431a..e71f1f2 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");
> > > @@ -697,7 +697,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;
> > > --
> > > 1.5.6.rc3.21.g8c6b5
> > >
> > >
> > > _______________________________________________
> > > i2c mailing list
> > > i2c@lm-sensors.org
> > > http://lists.lm-sensors.org/mailman/listinfo/i2c
> >
> > --
> > Ben (ben@fluff.org, http://www.fluff.org/)
> >
> > 'a smiley only costs 4 bytes'
[-- Attachment #2: 0006-i2c-omap-Mark-init-only-functions-as-__init.patch --]
[-- Type: text/x-diff, Size: 1241 bytes --]
>From 827b812e278a3a4fceba0a6957bbaddf2a53d19c Mon Sep 17 00:00:00 2001
From: Paul Walmsley <paul@pwsan.com>
Date: Fri, 17 Oct 2008 07:44:58 -0700
Subject: [PATCH] i2c-omap: Mark init-only functions as __init
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 5dd8a24..45c9511 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");
@@ -692,7 +692,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;
--
1.5.6.rc3.21.g8c6b5
^ permalink raw reply related [flat|nested] 33+ messages in thread
end of thread, other threads:[~2008-10-17 17:07 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-25 7:53 [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Tony Lindgren
2008-09-25 7:53 ` [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Tony Lindgren
2008-09-25 7:53 ` [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Tony Lindgren
2008-09-25 7:53 ` [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Tony Lindgren
2008-09-25 7:53 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Tony Lindgren
2008-09-25 7:53 ` [PATCH 5/8] i2c-omap: Add support on 34xx Tony Lindgren
2008-09-25 7:53 ` [PATCH 6/8] i2c-omap: Mark init-only functions as __init Tony Lindgren
2008-09-25 7:53 ` [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Tony Lindgren
2008-09-25 7:53 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap Tony Lindgren
2008-09-25 11:40 ` [PATCH 8/8] i2c-omap: Clean-up i2c-omap, v3 Tony Lindgren
2008-09-29 22:31 ` [i2c] [PATCH 8/8] i2c-omap: Clean-up i2c-omap Ben Dooks
2008-10-17 15:41 ` Tony Lindgren
2008-09-29 22:29 ` [i2c] [PATCH 7/8] i2c-omap: Don't compile in OMAP15xx I2C ISR for non-OMAP15xx builds Ben Dooks
2008-09-29 23:06 ` David Brownell
2008-09-30 5:35 ` Paul Walmsley
2008-09-30 5:36 ` Paul Walmsley
2008-10-17 15:40 ` Tony Lindgren
2008-09-29 22:30 ` [i2c] [PATCH 6/8] i2c-omap: Mark init-only functions as __init Ben Dooks
2008-10-17 15:39 ` Tony Lindgren
2008-10-17 17:07 ` Tony Lindgren
2008-09-29 22:28 ` [i2c] [PATCH 5/8] i2c-omap: Add support on 34xx Ben Dooks
2008-10-17 15:38 ` Tony Lindgren
2008-09-25 11:39 ` [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap, v3 Tony Lindgren
2008-09-29 22:27 ` [i2c] [PATCH 4/8] i2c-omap: FIFO handling support and broken hw workaround for i2c-omap Ben Dooks
2008-09-29 22:25 ` [i2c] [PATCH 3/8] i2c-omap: Add high-speed support to omap-i2c Ben Dooks
2008-10-17 15:37 ` Tony Lindgren
2008-09-29 22:21 ` [i2c] [PATCH 2/8] i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() Ben Dooks
2008-09-29 22:21 ` [i2c] [PATCH 1/8] i2c-omap: Do not use interruptible wait call in omap_i2c_xfer_msg Ben Dooks
2008-09-30 11:51 ` Jarkko Nikula
2008-10-17 15:35 ` Tony Lindgren
2008-09-29 22:23 ` [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2 Ben Dooks
2008-09-30 5:35 ` Tony Lindgren
2008-10-17 16:04 ` git-pull request for i2c-omap changes (Re: [i2c] [PATCH 0/8] Updates for i2c-omap from linux-omap tree for review, v2) Tony Lindgren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).