summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorGuoying Zhang <Guoying.Zhang@csr.com>2015-09-09 12:30:32 +0200
committerWolfram Sang <wsa@the-dreams.de>2015-10-23 22:48:45 +0200
commitd64d45cb95e6f9edf58fab49cfc5a7a60ff1a122 (patch)
tree7d3d95f3ea4edfc07c5189b3211b242f6f5d61a7 /drivers/i2c
parenti2c: imx: Use -ENXIO as error in the NACK case (diff)
downloadlinux-d64d45cb95e6f9edf58fab49cfc5a7a60ff1a122.tar.xz
linux-d64d45cb95e6f9edf58fab49cfc5a7a60ff1a122.zip
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>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-sirf.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 1092d4eeeb54..13e51ef6af73 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -358,11 +358,29 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
if (err < 0)
bitrate = SIRFSOC_I2C_DEFAULT_SPEED;
- if (bitrate < 100000)
- regval =
- (2 * ctrl_speed) / (bitrate * 11);
- else
+ /*
+ * Due to some hardware design issues, we need to tune the formula.
+ * 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.
+ * Through the actual tests, use the different user_div value(which
+ * in the divider formular 'Fio / (Fi2c * user_div)') to adapt
+ * the different ranges of i2c bus clock frequency, to make the SCL
+ * more accurate.
+ */
+ if (bitrate <= 30000)
regval = ctrl_speed / (bitrate * 5);
+ else if (bitrate > 30000 && bitrate <= 280000)
+ regval = (2 * ctrl_speed) / (bitrate * 11);
+ else
+ regval = ctrl_speed / (bitrate * 6);
writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL);
if (regval > 0xFF)