diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/i2c/busses/i2c-davinci.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/i2c/busses/i2c-davinci.c')
-rw-r--r-- | kernel/drivers/i2c/busses/i2c-davinci.c | 99 |
1 files changed, 68 insertions, 31 deletions
diff --git a/kernel/drivers/i2c/busses/i2c-davinci.c b/kernel/drivers/i2c/busses/i2c-davinci.c index 4788a32af..a8bdcb529 100644 --- a/kernel/drivers/i2c/busses/i2c-davinci.c +++ b/kernel/drivers/i2c/busses/i2c-davinci.c @@ -41,8 +41,8 @@ #define DAVINCI_I2C_TIMEOUT (1*HZ) #define DAVINCI_I2C_MAX_TRIES 2 -#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ - DAVINCI_I2C_IMR_SCD | \ +#define DAVINCI_I2C_OWN_ADDRESS 0x08 +#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_SCD | \ DAVINCI_I2C_IMR_ARDY | \ DAVINCI_I2C_IMR_NACK | \ DAVINCI_I2C_IMR_AL) @@ -181,6 +181,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) u32 clkh; u32 clkl; u32 input_clock = clk_get_rate(dev->clk); + struct device_node *of_node = dev->dev->of_node; /* NOTE: I2C Clock divider programming info * As per I2C specs the following formulas provide prescaler @@ -196,17 +197,51 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) * where if PSC == 0, d = 7, * if PSC == 1, d = 6 * if PSC > 1 , d = 5 + * + * Note: + * d is always 6 on Keystone I2C controller */ - /* get minimum of 7 MHz clock, but max of 12 MHz */ - psc = (input_clock / 7000000) - 1; + /* + * Both Davinci and current Keystone User Guides recommend a value + * between 7MHz and 12MHz. In reality 7MHz module clock doesn't + * always produce enough margin between SDA and SCL transitions. + * Measurements show that the higher the module clock is, the + * bigger is the margin, providing more reliable communication. + * So we better target for 12MHz. + */ + psc = (input_clock / 12000000) - 1; if ((input_clock / (psc + 1)) > 12000000) psc++; /* better to run under spec than over */ d = (psc >= 2) ? 5 : 7 - psc; - clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1); - clkh = clk >> 1; - clkl = clk - clkh; + if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c")) + d = 6; + + clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)); + /* Avoid driving the bus too fast because of rounding errors above */ + if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000) + clk++; + /* + * According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at + * least 1.3uS, which is not the case with 50% duty cycle. Driving HIGH + * to LOW ratio as 1 to 2 is more safe. + */ + if (pdata->bus_freq > 100) + clkl = (clk << 1) / 3; + else + clkl = (clk >> 1); + /* + * It's not always possible to have 1 to 2 ratio when d=7, so fall back + * to minimal possible clkh in this case. + */ + if (clk >= clkl + d) { + clkh = clk - clkl - d; + clkl -= d; + } else { + clkh = 0; + clkl = clk - (d << 1); + } davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); @@ -233,7 +268,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) /* Respond at reserved "SMBus Host" slave address" (and zero); * we seem to have no option to not respond... */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); + davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, DAVINCI_I2C_OWN_ADDRESS); dev_dbg(dev->dev, "PSC = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); @@ -350,29 +385,25 @@ static struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = { /* * Waiting for bus not busy */ -static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, - char allow_sleep) +static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev) { - unsigned long timeout; - static u16 to_cnt; - - timeout = jiffies + dev->adapter.timeout; - while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) - & DAVINCI_I2C_STR_BB) { - if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, - "timeout waiting for bus ready\n"); - to_cnt++; - return -ETIMEDOUT; - } else { - to_cnt = 0; - i2c_recover_bus(&dev->adapter); - } - } - if (allow_sleep) - schedule_timeout(1); - } + unsigned long timeout = jiffies + dev->adapter.timeout; + + do { + if (!(davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB)) + return 0; + schedule_timeout_uninterruptible(1); + } while (time_before_eq(jiffies, timeout)); + + dev_warn(dev->dev, "timeout waiting for bus ready\n"); + i2c_recover_bus(&dev->adapter); + + /* + * if bus is still "busy" here, it's most probably a HW problem like + * short-circuit + */ + if (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB) + return -EIO; return 0; } @@ -390,6 +421,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) u16 w; unsigned long time_left; + if (msg->addr == DAVINCI_I2C_OWN_ADDRESS) { + dev_warn(dev->dev, "transfer to own address aborted\n"); + return -EADDRNOTAVAIL; + } + /* Introduce a delay, required for some boards (e.g Davinci EVM) */ if (pdata->bus_delay) udelay(pdata->bus_delay); @@ -505,7 +541,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); - ret = i2c_davinci_wait_bus_not_busy(dev, 1); + ret = i2c_davinci_wait_bus_not_busy(dev); if (ret < 0) { dev_warn(dev->dev, "timeout waiting for bus ready\n"); return ret; @@ -704,6 +740,7 @@ static struct i2c_algorithm i2c_davinci_algo = { static const struct of_device_id davinci_i2c_of_match[] = { {.compatible = "ti,davinci-i2c", }, + {.compatible = "ti,keystone-i2c", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_i2c_of_match); |