i2c: davinci: Optimize SCL generation
Subsystems (2)
PATCH 1/1 i2c: davinci: Optimize SCL generation
There are several cases where current clock configuration algorithm produces not optimal results:
- truncation in "clk" calculation leads to the fact that actual BUS frequency will be always higher than spec except two exact module frequences 8MHz and 12MHz in the whole 7-12MHz range of permitted frequences
- driver configures SCL HIGH to LOW ratio always 1 to 1 and this doesn't work well in 400kHz case, namely minimum time of LOW state (according to I2C Spec 2.1) 1.3us will not be fulfilled. HIGH to LOW ratio 1 to 2 would be more approriate here.
---
Tested on custom Keystone II SoC-based board with complicated I2C network working on the edge of its HW specs (signal quality). In this case 1 to 2 HIGH to LOW relation really improves the reliability with 400kHz bus rate.
drivers/i2c/busses/i2c-davinci.c | 27 ++++++++++++++++++++++++--- 1 files changed, 24 insertions(+), 3 deletions(-)
drivers/i2c/busses/i2c-davinci.c +24 -3
@@ -211,9 +211,30 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) 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; + 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);
A message that is not in the archive (sent off-list or not yet received): [email protected]
Wolfram Sang
AppliedQuoted 10 lines · Alexander Sverdlin
There are several cases where current clock configuration algorithm produces not optimal results:
- truncation in "clk" calculation leads to the fact that actual BUS frequency will be always higher than spec except two exact module frequences 8MHz and 12MHz in the whole 7-12MHz range of permitted frequences
- driver configures SCL HIGH to LOW ratio always 1 to 1 and this doesn't work well in 400kHz case, namely minimum time of LOW state (according to I2C Spec 2.1) 1.3us will not be fulfilled. HIGH to LOW ratio 1 to 2 would be more approriate here.
Quoted 2 lines
Signed-off-by Michael Lawnick <[email protected]>Signed-off-by Alexander Sverdlin <[email protected]>
Applied to for-next, thanks!