mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 01:11:14 +00:00
213b728276
Pick accepted patches from upstream Linux tree instead of having to maintain our slightly different downstream patches. Import pending patch fixing I2C on MT7981 by making sure all clocks are enabled before accessing I2C registers. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
133 lines
4.1 KiB
Diff
133 lines
4.1 KiB
Diff
From f606aab3f1a49d723d66e14e545f6ca45005bda6 Mon Sep 17 00:00:00 2001
|
|
From: Kewei Xu <kewei.xu@mediatek.com>
|
|
Date: Thu, 17 Feb 2022 20:22:43 +0800
|
|
Subject: [PATCH 04/16] 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.
|
|
|
|
Signed-off-by: Kewei Xu <kewei.xu@mediatek.com>
|
|
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
|
Reviewed-by: Qii Wang <qii.wang@mediatek.com>
|
|
Signed-off-by: Wolfram Sang <wsa@kernel.org>
|
|
---
|
|
drivers/i2c/busses/i2c-mt65xx.c | 51 ++++++++++++++++++++++++++-------
|
|
1 file changed, 41 insertions(+), 10 deletions(-)
|
|
|
|
--- a/drivers/i2c/busses/i2c-mt65xx.c
|
|
+++ b/drivers/i2c/busses/i2c-mt65xx.c
|
|
@@ -67,11 +67,12 @@
|
|
|
|
#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)
|
|
@@ -604,6 +605,31 @@ static int mtk_i2c_max_step_cnt(unsigned
|
|
return MAX_STEP_CNT_DIV;
|
|
}
|
|
|
|
+static int mtk_i2c_get_clk_div_restri(struct mtk_i2c *i2c,
|
|
+ unsigned int sample_cnt)
|
|
+{
|
|
+ int clk_div_restri = 0;
|
|
+
|
|
+ if (i2c->dev_comp->ltiming_adjust == 0)
|
|
+ return 0;
|
|
+
|
|
+ if (sample_cnt == 1) {
|
|
+ if (i2c->ac_timing.inter_clk_div == 0)
|
|
+ clk_div_restri = 0;
|
|
+ else
|
|
+ clk_div_restri = 1;
|
|
+ } else {
|
|
+ if (i2c->ac_timing.inter_clk_div == 0)
|
|
+ clk_div_restri = -1;
|
|
+ else if (i2c->ac_timing.inter_clk_div == 1)
|
|
+ clk_div_restri = 0;
|
|
+ else
|
|
+ clk_div_restri = 1;
|
|
+ }
|
|
+
|
|
+ return clk_div_restri;
|
|
+}
|
|
+
|
|
/*
|
|
* Check and Calculate i2c ac-timing
|
|
*
|
|
@@ -732,6 +758,7 @@ static int mtk_i2c_calculate_speed(struc
|
|
unsigned int best_mul;
|
|
unsigned int cnt_mul;
|
|
int ret = -EINVAL;
|
|
+ int clk_div_restri = 0;
|
|
|
|
if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
|
|
target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;
|
|
@@ -749,7 +776,8 @@ static int mtk_i2c_calculate_speed(struc
|
|
* optimizing for sample_cnt * step_cnt being minimal
|
|
*/
|
|
for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
|
|
- step_cnt = DIV_ROUND_UP(opt_div, sample_cnt);
|
|
+ clk_div_restri = mtk_i2c_get_clk_div_restri(i2c, sample_cnt);
|
|
+ step_cnt = DIV_ROUND_UP(opt_div + clk_div_restri, sample_cnt);
|
|
cnt_mul = step_cnt * sample_cnt;
|
|
if (step_cnt > max_step_cnt)
|
|
continue;
|
|
@@ -763,7 +791,7 @@ static int mtk_i2c_calculate_speed(struc
|
|
best_mul = cnt_mul;
|
|
base_sample_cnt = sample_cnt;
|
|
base_step_cnt = step_cnt;
|
|
- if (best_mul == opt_div)
|
|
+ if (best_mul == (opt_div + clk_div_restri))
|
|
break;
|
|
}
|
|
}
|
|
@@ -774,7 +802,8 @@ static int mtk_i2c_calculate_speed(struc
|
|
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 - clk_div_restri))) >
|
|
+ target_speed) {
|
|
/* In this case, hardware can't support such
|
|
* low i2c_bus_freq
|
|
*/
|
|
@@ -803,13 +832,16 @@ static int mtk_i2c_set_speed(struct mtk_
|
|
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 */
|
|
@@ -856,7 +888,6 @@ static int mtk_i2c_set_speed(struct mtk_
|
|
break;
|
|
}
|
|
|
|
- i2c->ac_timing.inter_clk_div = clk_div - 1;
|
|
|
|
return 0;
|
|
}
|