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>
This commit is contained in:
Daolong Zhu 2021-03-03 16:42:27 +08:00 committed by Patrick Georgi
parent ca2e7161d1
commit 7c7d0b1084
1 changed files with 29 additions and 3 deletions

View File

@ -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)