diff options
author | Daolong Zhu <jg_daolongzhu@mediatek.corp-partner.google.com> | 2021-03-03 16:42:27 +0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-03-16 11:19:24 +0000 |
commit | 7c7d0b108480be9eec5d2fd9b0f18e8ee1c343b9 (patch) | |
tree | 2127b6205da0a2f1dd43177bba3c07996b710743 | |
parent | ca2e7161d10e23d85184bc12c71e02e523528ccf (diff) |
soc/mediatek/mt8192: adjust i2c "tLOW" and "tSU,STO"
The i2c actiming with the default reg setting cannot meet spec,
so we need to set some regs.
1. adjust the ratio of SCL high and low level, to adjust "tLOW".
2. modify ext_conf reg to adjust "tSU,STO".
BUG=b:179000159
TEST=Test on asurada (MT8192), boot pass,
timing pass.
Signed-off-by: Daolong Zhu <jg_daolongzhu@mediatek.corp-partner.google.com>
Change-Id: Ifbe97edbc38972af5b782fb93342ee0616127dd8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51024
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r-- | src/soc/mediatek/mt8192/i2c.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/src/soc/mediatek/mt8192/i2c.c b/src/soc/mediatek/mt8192/i2c.c index e38cbb617d..572c2808d2 100644 --- a/src/soc/mediatek/mt8192/i2c.c +++ b/src/soc/mediatek/mt8192/i2c.c @@ -7,6 +7,10 @@ #include <soc/gpio.h> #define I2C_CLK_HZ (UNIVPLL_HZ / 20) +#define I2C_FULL_DUTY 100 +#define I2C_HALF_DUTY 50 +#define I2C_ADJUSTED_DUTY 45 +#define I2C_FS_START_CON 0x601 struct mtk_i2c mtk_i2c_bus_controller[] = { [0] = { .i2c_regs = (void *)(I2C_BASE + 0x250000), @@ -129,25 +133,47 @@ static void mtk_i2c_speed_init(uint8_t bus) const uint8_t clock_div = 5; const uint8_t sample_div = 1; uint32_t i2c_freq; + uint32_t tar_speed = 400; + uint32_t tar_speed_high; + uint32_t tar_speed_low; assert(bus < I2C_BUS_NUMBER); + /* Adjust ratio of high/low level */ + tar_speed_high = tar_speed * I2C_HALF_DUTY / I2C_ADJUSTED_DUTY; + /* Calculate i2c frequency */ step_div = DIV_ROUND_UP(I2C_CLK_HZ, - (400 * KHz * sample_div * 2) * clock_div); + (tar_speed_high * KHz * sample_div * 2) * clock_div); i2c_freq = I2C_CLK_HZ / (step_div * sample_div * 2 * clock_div); - assert(sample_div < 8 && step_div < 64 && i2c_freq <= 400 * KHz && - i2c_freq >= 380 * KHz); + assert(sample_div < 8 && step_div < 64 && + i2c_freq <= tar_speed_high * KHz && + i2c_freq >= (tar_speed_high - 20) * KHz); /* Init i2c bus timing register */ write32(&mtk_i2c_bus_controller[bus].i2c_regs->timing, (sample_div - 1) << 8 | (step_div - 1)); + + /* Adjust ratio of high/low level */ + tar_speed_low = tar_speed * I2C_HALF_DUTY / + (I2C_FULL_DUTY - I2C_ADJUSTED_DUTY); + + /* Calculate i2c frequency */ + step_div = DIV_ROUND_UP(I2C_CLK_HZ, + (tar_speed_low * KHz * sample_div * 2) * clock_div); + i2c_freq = I2C_CLK_HZ / (step_div * sample_div * 2 * clock_div); + assert(sample_div < 8 && step_div < 64 && + i2c_freq <= tar_speed_low * KHz && + i2c_freq >= (tar_speed_low - 20) * KHz); write32(&mtk_i2c_bus_controller[bus].i2c_regs->ltiming, (sample_div - 1) << 6 | (step_div - 1)); /* Init i2c bus clock_div register */ write32(&mtk_i2c_bus_controller[bus].i2c_regs->clock_div, clock_div - 1); + + /* Adjust tSU,STA/tHD,STA/tSU,STO */ + write32(&mtk_i2c_bus_controller[bus].i2c_regs->ext_conf, I2C_FS_START_CON); } void mtk_i2c_bus_init(uint8_t bus) |