summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaolong Zhu <jg_daolongzhu@mediatek.corp-partner.google.com>2021-03-03 16:42:27 +0800
committerPatrick Georgi <pgeorgi@google.com>2021-03-16 11:19:24 +0000
commit7c7d0b108480be9eec5d2fd9b0f18e8ee1c343b9 (patch)
tree2127b6205da0a2f1dd43177bba3c07996b710743 /src
parentca2e7161d10e23d85184bc12c71e02e523528ccf (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>
Diffstat (limited to 'src')
-rw-r--r--src/soc/mediatek/mt8192/i2c.c32
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)