X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=kernel%2Fdrivers%2Fi2c%2Fbusses%2Fi2c-sirf.c;fp=kernel%2Fdrivers%2Fi2c%2Fbusses%2Fi2c-sirf.c;h=13e51ef6af73dfb1285aa75362163b448a867bb1;hb=e09b41010ba33a20a87472ee821fa407a5b8da36;hp=1092d4eeeb5440691c9ca425ab40cd0780e4b416;hpb=f93b97fd65072de626c074dbe099a1fff05ce060;p=kvmfornfv.git diff --git a/kernel/drivers/i2c/busses/i2c-sirf.c b/kernel/drivers/i2c/busses/i2c-sirf.c index 1092d4eee..13e51ef6a 100644 --- a/kernel/drivers/i2c/busses/i2c-sirf.c +++ b/kernel/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)