Commit 720bd003 authored by Kevin Hilman's avatar Kevin Hilman

ARM: DaVinci: i2c fixes from TI

This patch fixes the I2C errors which were coming during the TI codec
demos. These errors were due bus lockup and inappropriate enabling of
interrupts.

The patch incorporates the following:

1. Enables GPIO power domain.
2. Duty cycle of 50% (Initially it was set to 27%, which is for full
   speed mode).  
3. udelay of 100 instead of the old while (cnt--) fix.
4. Enables the inetrrupts before writing to ICMDR register.
5. Sends a NACK and sends a clock on SCL line in case of cmd_complete
   failure and Bus busy error. 
Signed-off-by: default avatarKevin Hilman <khilman@mvista.com>
parent f7d41d35
...@@ -232,6 +232,7 @@ static void board_init(void) ...@@ -232,6 +232,7 @@ static void board_init(void)
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
/* Turn on WatchDog timer LPSC. Needed for RESET to work */ /* Turn on WatchDog timer LPSC. Needed for RESET to work */
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <asm/arch/irqs.h> #include <asm/arch/irqs.h>
#include <asm/mach-types.h>
#include "i2c-davinci.h" #include "i2c-davinci.h"
MODULE_AUTHOR("Texas Instruments India"); MODULE_AUTHOR("Texas Instruments India");
...@@ -74,13 +75,21 @@ static const char driver_name[] = "i2c_davinci"; ...@@ -74,13 +75,21 @@ static const char driver_name[] = "i2c_davinci";
DAVINCI_I2C_ICIMR_AL_MASK) DAVINCI_I2C_ICIMR_AL_MASK)
/* Following are the default values for the module parameters */ /* Following are the default values for the module parameters */
static int bus_freq = 20; /* Fast Mode = 400 KHz, Standard Mode = 100 KHz */
static int bus_freq = 400; /* Default: Fast Mode = 400 KHz, Standard Mode = 100 KHz */
static int own_addr = 0xa; /* Randomly assigned own address */ static int own_addr = 0xa; /* Randomly assigned own address */
/* Instance of the private I2C device structure */ /* Instance of the private I2C device structure */
static struct i2c_davinci_device i2c_davinci_dev; static struct i2c_davinci_device i2c_davinci_dev;
#define PINMUX1 __REG(0x01c40004)
#define GPIO __REG(0x01C67000)
#define GPIO23_DIR __REG(0x01C67038)
#define GPIO23_SET __REG(0x01C67040)
#define GPIO23_CLR __REG(0x01C67044)
/* /*
* This functions configures I2C and brings I2C out of reset. * This functions configures I2C and brings I2C out of reset.
* This function is called during I2C init function. This function * This function is called during I2C init function. This function
...@@ -118,7 +127,7 @@ static int i2c_davinci_reset(struct i2c_davinci_device *dev) ...@@ -118,7 +127,7 @@ static int i2c_davinci_reset(struct i2c_davinci_device *dev)
clk = ((input_clock/(psc + 1)) / (bus_freq * 1000)) - 10; clk = ((input_clock/(psc + 1)) / (bus_freq * 1000)) - 10;
dev->regs->icpsc = psc; dev->regs->icpsc = psc;
dev->regs->icclkh = (27 * clk) / 100; /* duty cycle should be 27% */ dev->regs->icclkh = (50 * clk) / 100; /* duty cycle should be 27% */
dev->regs->icclkl = (clk - dev->regs->icclkh); dev->regs->icclkl = (clk - dev->regs->icclkh);
dev_dbg(dev->dev, "CLK = %d\n", clk); dev_dbg(dev->dev, "CLK = %d\n", clk);
...@@ -141,15 +150,46 @@ static int i2c_davinci_reset(struct i2c_davinci_device *dev) ...@@ -141,15 +150,46 @@ static int i2c_davinci_reset(struct i2c_davinci_device *dev)
/* /*
* Waiting on Bus Busy * Waiting on Bus Busy
*/ */
static int i2c_davinci_wait_for_bb(char allow_sleep) static int i2c_davinci_wait_for_bb(struct i2c_davinci_device *dev,
char allow_sleep)
{ {
unsigned long timeout; unsigned long timeout;
int i;
static char to_cnt = 0;
timeout = jiffies + DAVINCI_I2C_TIMEOUT; timeout = jiffies + DAVINCI_I2C_TIMEOUT;
while ((i2c_davinci_dev.regs->icstr) & DAVINCI_I2C_ICSTR_BB_MASK) { while ((i2c_davinci_dev.regs->icstr) & DAVINCI_I2C_ICSTR_BB_MASK) {
if (to_cnt <= 2) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
dev_warn(dev->dev,
"timeout waiting for bus ready");
to_cnt ++;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
}
else {
to_cnt = 0;
/* Send the NACK to the slave */
dev->regs->icmdr |= DAVINCI_I2C_ICMDR_NACKMOD_MASK;
/* Disable I2C */
PINMUX1 &= (~(1 << 7));
/* Set the GPIO direction register */
GPIO23_DIR &= ~0x0800;
/* Send high and low on the SCL line */
for (i = 0; i < 10; i++) {
GPIO23_SET |= 0x0800;
udelay(25);
GPIO23_CLR |= 0x0800;
udelay(25);
}
/* Re-enable I2C */
PINMUX1 |= (1 << 7);
i2c_davinci_reset(dev);
init_completion(&dev->cmd_complete);
}
if (allow_sleep) if (allow_sleep)
schedule_timeout(1); schedule_timeout(1);
} }
...@@ -166,11 +206,14 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -166,11 +206,14 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
{ {
struct i2c_davinci_device *dev = i2c_get_adapdata(adap); struct i2c_davinci_device *dev = i2c_get_adapdata(adap);
u8 zero_byte = 0; u8 zero_byte = 0;
u32 flag = 0, stat = 0, cnt = 2000;
int r; int r;
/* Introduce a 20musec delay. Required for Davinci EVM */ u32 flag = 0, stat = 0;
while (cnt--); int i;
/* Introduce a 100musec delay. Required for Davinci EVM board only */
if (machine_is_davinci_evm())
udelay(100);
/* set the slave address */ /* set the slave address */
dev->regs->icsar = msg->addr; dev->regs->icsar = msg->addr;
...@@ -211,15 +254,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -211,15 +254,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
if (stop) if (stop)
flag |= DAVINCI_I2C_ICMDR_STP_MASK; flag |= DAVINCI_I2C_ICMDR_STP_MASK;
/* write the data into mode register */
dev->regs->icmdr = flag;
/* Enable receive and transmit interrupts */ /* Enable receive and transmit interrupts */
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICRRDY_MASK; dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICRRDY_MASK;
else else
dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICXRDY_MASK; dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICXRDY_MASK;
/* write the data into mode register */
dev->regs->icmdr = flag;
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
DAVINCI_I2C_TIMEOUT); DAVINCI_I2C_TIMEOUT);
dev->buf_len = 0; dev->buf_len = 0;
...@@ -227,6 +270,25 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -227,6 +270,25 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
return r; return r;
if (r == 0) { if (r == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
/* Send the NACK to the slave */
dev->regs->icmdr |= DAVINCI_I2C_ICMDR_NACKMOD_MASK;
/* Disable I2C */
PINMUX1 &= (~(1 << 7));
/* Set the GPIO direction register */
GPIO23_DIR &= ~0x0800;
/* Send high and low on the SCL line */
for (i = 0; i < 10; i++) {
GPIO23_SET |= 0x0800;
udelay(25);
GPIO23_CLR |= 0x0800;
udelay(25);
}
/* Re-enable I2C */
PINMUX1 |= (1 << 7);
i2c_davinci_reset(dev); i2c_davinci_reset(dev);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -243,8 +305,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -243,8 +305,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev->regs->icmdr |= DAVINCI_I2C_ICMDR_STP_MASK; dev->regs->icmdr |= DAVINCI_I2C_ICMDR_STP_MASK;
return -EREMOTEIO; return -EREMOTEIO;
} }
if (dev->cmd_err & DAVINCI_I2C_ICSTR_AL_MASK || if (dev->cmd_err & DAVINCI_I2C_ICSTR_AL_MASK) {
dev->cmd_err & DAVINCI_I2C_ICSTR_RSFULL_MASK) {
i2c_davinci_reset(dev); i2c_davinci_reset(dev);
return -EIO; return -EIO;
} }
...@@ -273,7 +334,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -273,7 +334,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if (msgs[count].buf == NULL) if (msgs[count].buf == NULL)
return -EINVAL; return -EINVAL;
if ((ret = i2c_davinci_wait_for_bb(1)) < 0) { if ((ret = i2c_davinci_wait_for_bb(dev, 1)) < 0) {
dev_warn(dev->dev, "timeout waiting for bus ready"); dev_warn(dev->dev, "timeout waiting for bus ready");
return ret; return ret;
} }
...@@ -433,6 +494,19 @@ davinci_i2c_probe(struct platform_device *pdev) ...@@ -433,6 +494,19 @@ davinci_i2c_probe(struct platform_device *pdev)
init_waitqueue_head(&dev->cmd_wait); init_waitqueue_head(&dev->cmd_wait);
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
/*
* NOTE: On DaVinci EVM, the i2c bus frequency is set to 20kHz
* so that the MSP430, which is doing software i2c, has
* some extra processing time
*/
if (machine_is_davinci_evm())
bus_freq = 20;
else if (bus_freq > 200)
bus_freq = 400; /* Fast mode */
else
bus_freq = 100; /* Standard mode */
dev->clk = clk_get (&pdev->dev, "I2CCLK"); dev->clk = clk_get (&pdev->dev, "I2CCLK");
if (IS_ERR(dev->clk)) if (IS_ERR(dev->clk))
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment