Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: sirf: tune the divider to make i2c bus freq more accurate

In prima2 and atlas7, due to some hardware design issue. we
need to adjust the divider ratio a little according to i2c
bus frequency ranges.
Since i2c is open drain interface that allows the slave to
stall the transaction by holding the SCL line at '0', the RTL
implementation is waiting for SCL feedback from the pin after
setting it to High-Z ('1'). This wait adds to the high-time
interval counter few cycles of the input synchronization
(depending on the SCL_FILTER_REG field), and also the time it
takes for the board pull-up resistor to rise the SCL line.
For slow SCL settings these additions are negligible, but they
start to affect the speed when clock is set to faster frequencies.
This patch is based on the actual tests, and it makes SCL more
accurate.

Signed-off-by: Guoying Zhang <Guoying.Zhang@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

Guoying Zhang and committed by
Wolfram Sang
d64d45cb 4c0657ae

+22 -4
+22 -4
drivers/i2c/busses/i2c-sirf.c
··· 358 358 if (err < 0) 359 359 bitrate = SIRFSOC_I2C_DEFAULT_SPEED; 360 360 361 - if (bitrate < 100000) 362 - regval = 363 - (2 * ctrl_speed) / (bitrate * 11); 364 - else 361 + /* 362 + * Due to some hardware design issues, we need to tune the formula. 363 + * Since i2c is open drain interface that allows the slave to 364 + * stall the transaction by holding the SCL line at '0', the RTL 365 + * implementation is waiting for SCL feedback from the pin after 366 + * setting it to High-Z ('1'). This wait adds to the high-time 367 + * interval counter few cycles of the input synchronization 368 + * (depending on the SCL_FILTER_REG field), and also the time it 369 + * takes for the board pull-up resistor to rise the SCL line. 370 + * For slow SCL settings these additions are negligible, 371 + * but they start to affect the speed when clock is set to faster 372 + * frequencies. 373 + * Through the actual tests, use the different user_div value(which 374 + * in the divider formular 'Fio / (Fi2c * user_div)') to adapt 375 + * the different ranges of i2c bus clock frequency, to make the SCL 376 + * more accurate. 377 + */ 378 + if (bitrate <= 30000) 365 379 regval = ctrl_speed / (bitrate * 5); 380 + else if (bitrate > 30000 && bitrate <= 280000) 381 + regval = (2 * ctrl_speed) / (bitrate * 11); 382 + else 383 + regval = ctrl_speed / (bitrate * 6); 366 384 367 385 writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); 368 386 if (regval > 0xFF)