Commit 1d432616 authored by Troy Kisky's avatar Troy Kisky Committed by Kevin Hilman

ARM: DaVinci: misc i2c fixups

davinci-i2c: fix lost interrupt
DAVINCI_I2C_STR_REG is a write 1 to clear register,
so don't use a read/modify/write cycle.
EVM doesn't have platform data yet, make bus_delay default correct
Ensure psc value gives a clock between 7-12 Mhz
Make sure no interrupts are pending before starting transfer
Signed-off-by: default avatarTroy Kisky <troy.kisky@boundarydevices.com>
Acked-by: default avatarDirk Behme <dirk.behme@gmail.com>
Signed-off-by: default avatarKevin Hilman <khilman@mvista.com>
parent 3272aab9
......@@ -123,7 +123,7 @@ struct davinci_i2c_dev {
/* default platform data to use if not supplied in the platform_device */
static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = {
.bus_freq = 100,
.bus_delay = 0,
.bus_delay = 100,
};
static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev,
......@@ -147,6 +147,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u16 psc;
u32 clk;
u32 d;
u32 clkh;
u32 clkl;
u32 input_clock = clk_get_rate(dev->clk);
......@@ -176,23 +177,26 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
* if PSC > 1 , d = 5
*/
psc = 26; /* To get 1MHz clock */
psc = (input_clock/7000000)-1; /* To get minimum of 7 MHz clock */
if ( (input_clock/(psc+1)) > 12000000) psc++; /* maximum of 12Mhz */
d = (psc>=2)? 5 : 7 - psc;
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - 10;
clkh = (50 * clk) / 100;
clk = ((input_clock/(psc+1)) / (pdata->bus_freq * 1000)) - (d<<1);
clkh = clk>>1;
clkl = clk - clkh;
davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
dev_dbg(dev->dev, "CLK = %d\n", clk);
dev_dbg(dev->dev, "input_clock=%d, CLK = %d\n", input_clock,clk);
dev_dbg(dev->dev, "PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
dev_dbg(dev->dev, "CLKL = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
dev_dbg(dev->dev, "CLKH = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
dev_dbg(dev->dev, "bus_freq = %dKHz bus_delay = %d\n",pdata->bus_freq,pdata->bus_delay);
/* Take the I2C module out of reset: */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
......@@ -278,7 +282,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev->cmd_err = 0;
/* Clear any pending interrupts by reading the IVR */
stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG);
do {
stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG);
} while (stat);
/* Take I2C out of reset, configure it as master and set the
* start bit */
......@@ -358,12 +364,10 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
for (i = 0; i < num; i++) {
ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1)));
dev_dbg(dev->dev, "%s ret: %d\n", __FUNCTION__, ret);
if (ret < 0)
return ret;
}
dev_dbg(dev->dev, "%s:%d ret: %d\n", __FUNCTION__, __LINE__, ret);
return num;
}
......@@ -406,9 +410,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
break;
case DAVINCI_I2C_IVR_ARDY:
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG);
MOD_REG_BIT(w, DAVINCI_I2C_STR_ARDY, 1);
davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, w);
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY);
complete(&dev->cmd_complete);
break;
......@@ -421,12 +424,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
if (dev->buf_len)
continue;
w = davinci_i2c_read_reg(dev,
DAVINCI_I2C_STR_REG);
MOD_REG_BIT(w, DAVINCI_I2C_IMR_RRDY, 0);
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG,
w);
DAVINCI_I2C_STR_REG,DAVINCI_I2C_IMR_RRDY);
} else
dev_err(dev->dev, "RDR IRQ while no "
"data requested\n");
......@@ -452,9 +451,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
break;
case DAVINCI_I2C_IVR_SCD:
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG);
MOD_REG_BIT(w, DAVINCI_I2C_STR_SCD, 1);
davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, w);
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD);
complete(&dev->cmd_complete);
break;
......
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