| From b8080b95eae142cd0d8b5a3197adcbf615ca404c Mon Sep 17 00:00:00 2001 |
| From: Daolong Zhu <jg_daolongzhu@mediatek.corp-partner.google.com> |
| Date: Sat, 24 Jul 2021 11:17:42 +0800 |
| Subject: [PATCH] FROMLIST: i2c: mediatek: modify bus speed calculation formula |
| |
| When clock-div is 0 or greater than 1, the bus speed calculated by the |
| old speed calculation formula will be larger than the target speed. So |
| we update the formula. |
| (am from https://patchwork.ozlabs.org/project/linux-i2c/patch/1626517079-9057-9-git-send-email-kewei.xu@mediatek.com/) |
| |
| BUG=b:192064394 |
| TEST=test pass on willow,cozmo,juniper,fennel(mt8183), timing pass, touchpad function ok. |
| |
| Signed-off-by: Daolong Zhu <jg_daolongzhu@mediatek.corp-partner.google.com> |
| Change-Id: Ia484b5f08ffc44da68602431b8fed2af508ada74 |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3051373 |
| Reviewed-by: Sean Paul <seanpaul@chromium.org> |
| Reviewed-by: Hsin-Yi Wang <hsinyi@chromium.org> |
| Tested-by: Hsin-Yi Wang <hsinyi@chromium.org> |
| Commit-Queue: Hsin-Yi Wang <hsinyi@chromium.org> |
| --- |
| drivers/i2c/busses/i2c-mt65xx.c | 35 +++++++++++++++++++++++---------- |
| 1 file changed, 25 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c |
| --- a/drivers/i2c/busses/i2c-mt65xx.c |
| +++ b/drivers/i2c/busses/i2c-mt65xx.c |
| @@ -65,11 +65,12 @@ |
| #define I2C_DEFAULT_CLK_DIV 5 |
| #define MAX_SAMPLE_CNT_DIV 8 |
| #define MAX_STEP_CNT_DIV 64 |
| -#define MAX_CLOCK_DIV 256 |
| +#define MAX_CLOCK_DIV_8BITS 256 |
| +#define MAX_CLOCK_DIV_5BITS 32 |
| #define MAX_HS_STEP_CNT_DIV 8 |
| -#define I2C_STANDARD_MODE_BUFFER (1000 / 2) |
| -#define I2C_FAST_MODE_BUFFER (300 / 2) |
| -#define I2C_FAST_MODE_PLUS_BUFFER (20 / 2) |
| +#define I2C_STANDARD_MODE_BUFFER (1000 / 3) |
| +#define I2C_FAST_MODE_BUFFER (300 / 3) |
| +#define I2C_FAST_MODE_PLUS_BUFFER (20 / 3) |
| |
| #define I2C_CONTROL_RS (0x1 << 1) |
| #define I2C_CONTROL_DMA_EN (0x1 << 2) |
| @@ -719,14 +720,26 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, |
| unsigned int best_mul; |
| unsigned int cnt_mul; |
| int ret = -EINVAL; |
| + int clock_div_constraint = 0; |
| |
| if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ) |
| target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ; |
| |
| + if (i2c->default_timing_adjust) { |
| + clock_div_constraint = 0; |
| + } else if (i2c->dev_comp->ltiming_adjust && |
| + i2c->ac_timing.inter_clk_div > 1) { |
| + clock_div_constraint = 1; |
| + } else if (i2c->dev_comp->ltiming_adjust && |
| + i2c->ac_timing.inter_clk_div == 0) { |
| + clock_div_constraint = -1; |
| + } |
| + |
| max_step_cnt = mtk_i2c_max_step_cnt(target_speed); |
| base_step_cnt = max_step_cnt; |
| /* Find the best combination */ |
| - opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed); |
| + opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed) + |
| + clock_div_constraint; |
| best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt; |
| |
| /* Search for the best pair (sample_cnt, step_cnt) with |
| @@ -761,7 +774,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, |
| sample_cnt = base_sample_cnt; |
| step_cnt = base_step_cnt; |
| |
| - if ((clk_src / (2 * sample_cnt * step_cnt)) > target_speed) { |
| + if ((clk_src / (2 * (sample_cnt * step_cnt - clock_div_constraint))) > |
| + target_speed) { |
| /* In this case, hardware can't support such |
| * low i2c_bus_freq |
| */ |
| @@ -848,13 +862,16 @@ static int mtk_i2c_set_speed_adjust_timing(struct mtk_i2c *i2c, |
| target_speed = i2c->speed_hz; |
| parent_clk /= i2c->clk_src_div; |
| |
| - if (i2c->dev_comp->timing_adjust) |
| - max_clk_div = MAX_CLOCK_DIV; |
| + if (i2c->dev_comp->timing_adjust && i2c->dev_comp->ltiming_adjust) |
| + max_clk_div = MAX_CLOCK_DIV_5BITS; |
| + else if (i2c->dev_comp->timing_adjust) |
| + max_clk_div = MAX_CLOCK_DIV_8BITS; |
| else |
| max_clk_div = 1; |
| |
| for (clk_div = 1; clk_div <= max_clk_div; clk_div++) { |
| clk_src = parent_clk / clk_div; |
| + i2c->ac_timing.inter_clk_div = clk_div - 1; |
| |
| if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) { |
| /* Set master code speed register */ |
| @@ -901,8 +918,6 @@ static int mtk_i2c_set_speed_adjust_timing(struct mtk_i2c *i2c, |
| break; |
| } |
| |
| - i2c->ac_timing.inter_clk_div = clk_div - 1; |
| - |
| return 0; |
| } |
| |
| -- |
| 2.33.0.685.g46640cef36-goog |
| |