v4:
1. Remove the repeated assignment of the inter_clk_div parameter
2. Modify the wrong assignment of OFFSET_MULTI_DMA
3. Unify the log print format of the i2c_dump_register() and drop the extra outer parentheses
4. Place the fixes at the very least
5. Add fixed tags 25708278f810 ("i2c: mediatek: Add i2c support for MediaTek MT8183")
6. Add "i2c: mediatek: modify bus speed calculation formula"
7. Fix single line characters exceeding 80 characters
8. Combine two different series of patches.
v3:
1. Fix code errors caused by v2 modification
v2:
1. Add "dt-bindings: i2c: add attribute default-timing-adjust"
2. Split the fix into sepatate patch.
Kewei Xu (8):
i2c: mediatek: fixing the incorrect register offset
dt-bindings: i2c: update bindings for MT8195 SoC
i2c: mediatek: Reset the handshake signal between i2c and dma
i2c: mediatek: Dump i2c/dma register when a timeout occurs
dt-bindings: i2c: add attribute default-timing-adjust
i2c: mediatek: Add OFFSET_EXT_CONF setting back
i2c: mediatek: Isolate speed setting via dts for special devices
i2c: mediatek: modify bus speed calculation formula
.../devicetree/bindings/i2c/i2c-mt65xx.txt | 3 +
drivers/i2c/busses/i2c-mt65xx.c | 194 ++++++++++++++++--
2 files changed, 180 insertions(+), 17 deletions(-)
--
2.18.0
The reason for the modification here is that the previous
offset information is incorrect, OFFSET_DEBUGSTAT = 0xE4 is
the correct value.
Fixes: 25708278f810 ("i2c: mediatek: Add i2c support for MediaTek MT8183")
Signed-off-by: Kewei Xu <[email protected]>
Reviewed-by: Chen-Yu Tsai <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 5ddfa4e56ee2..222ff765e55d 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -193,7 +193,7 @@ static const u16 mt_i2c_regs_v2[] = {
[OFFSET_CLOCK_DIV] = 0x48,
[OFFSET_SOFTRESET] = 0x50,
[OFFSET_SCL_MIS_COMP_POINT] = 0x90,
- [OFFSET_DEBUGSTAT] = 0xe0,
+ [OFFSET_DEBUGSTAT] = 0xe4,
[OFFSET_DEBUGCTRL] = 0xe8,
[OFFSET_FIFO_STAT] = 0xf4,
[OFFSET_FIFO_THRESH] = 0xf8,
--
2.18.0
Due to changes in the hardware design of the handshaking signal
between i2c and dma, it is necessary to reset the handshaking
signal before each transfer to ensure that the multi-msgs can
be transferred correctly.
Signed-off-by: Kewei Xu <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 222ff765e55d..c0108387f34b 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -47,6 +47,9 @@
#define I2C_RD_TRANAC_VALUE 0x0001
#define I2C_SCL_MIS_COMP_VALUE 0x0000
#define I2C_CHN_CLR_FLAG 0x0000
+#define I2C_CLR_DEBUGCTR 0x0000
+#define I2C_RELIABILITY 0x0010
+#define I2C_DMAACK_ENABLE 0x0008
#define I2C_DMA_CON_TX 0x0000
#define I2C_DMA_CON_RX 0x0001
@@ -850,6 +853,17 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
reinit_completion(&i2c->msg_complete);
+ if (i2c->dev_comp->apdma_sync) {
+ mtk_i2c_writew(i2c, I2C_CLR_DEBUGCTR, OFFSET_DEBUGCTRL);
+ writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
+ i2c->pdmabase + OFFSET_RST);
+ writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+ mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET);
+ mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
+ mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE,
+ OFFSET_DEBUGCTRL);
+ }
+
control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))
--
2.18.0
In the commit be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust
support"), we miss setting OFFSET_EXT_CONF register if
i2c->dev_comp->timing_adjust is false, now add it back.
Fixes: be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust support")
Signed-off-by: Kewei Xu <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index abdbf27b6eb4..a2a5a4ec1d81 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -41,6 +41,8 @@
#define I2C_HANDSHAKE_RST 0x0020
#define I2C_FIFO_ADDR_CLR 0x0001
#define I2C_DELAY_LEN 0x0002
+#define I2C_ST_START_CON 0x8001
+#define I2C_FS_START_CON 0x1800
#define I2C_TIME_CLR_VALUE 0x0000
#define I2C_TIME_DEFAULT_VALUE 0x0003
#define I2C_WRRD_TRANAC_VALUE 0x0002
@@ -484,6 +486,7 @@ static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
{
u16 control_reg;
+ u16 ext_conf_val;
if (i2c->dev_comp->apdma_sync) {
writel(I2C_DMA_WARM_RST, i2c->pdmabase + OFFSET_RST);
@@ -518,8 +521,13 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
if (i2c->dev_comp->ltiming_adjust)
mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
+ if (i2c->speed_hz <= I2C_MAX_STANDARD_MODE_FREQ)
+ ext_conf_val = I2C_ST_START_CON;
+ else
+ ext_conf_val = I2C_FS_START_CON;
+
if (i2c->dev_comp->timing_adjust) {
- mtk_i2c_writew(i2c, i2c->ac_timing.ext, OFFSET_EXT_CONF);
+ ext_conf_val = i2c->ac_timing.ext;
mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div,
OFFSET_CLOCK_DIV);
mtk_i2c_writew(i2c, I2C_SCL_MIS_COMP_VALUE,
@@ -544,6 +552,7 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
OFFSET_HS_STA_STO_AC_TIMING);
}
}
+ mtk_i2c_writew(i2c, ext_conf_val, OFFSET_EXT_CONF);
/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
if (i2c->have_pmic)
--
2.18.0
Add attribute default-timing-adjust for DT-binding document.
Fixes: be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust support")
Signed-off-by: Kewei Xu <[email protected]>
---
Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 7c4915bc4439..7b80a11d4d4c 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -33,6 +33,8 @@ Optional properties:
- mediatek,have-pmic: platform can control i2c form special pmic side.
Only mt6589 and mt8135 support this feature.
- mediatek,use-push-pull: IO config use push-pull mode.
+ - mediatek,default-timing-adjust: use default timing calculation, no timing
+ adjustment.
Example:
--
2.18.0
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 <[email protected]>
---
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
index 061775489380..45939f919085 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -68,11 +68,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.18.0
In the commit be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust
support"), the I2C timing calculation has been revised to support
ac-timing adjustment, however that will break on some I2C components.
As a result we want to introduce a new setting "default-adjust-timing"
so those components can choose to use the old (default) timing algorithm.
Fixes: be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust support")
Signed-off-by: Kewei Xu <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 77 +++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index a2a5a4ec1d81..061775489380 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -65,6 +65,7 @@
#define I2C_DMA_HARD_RST 0x0002
#define I2C_DMA_HANDSHAKE_RST 0x0004
+#define I2C_DEFAULT_CLK_DIV 5
#define MAX_SAMPLE_CNT_DIV 8
#define MAX_STEP_CNT_DIV 64
#define MAX_CLOCK_DIV 256
@@ -249,6 +250,7 @@ struct mtk_i2c {
struct clk *clk_arb; /* Arbitrator clock for i2c */
bool have_pmic; /* can use i2c pins from PMIC */
bool use_push_pull; /* IO config push-pull mode */
+ bool default_timing_adjust; /* no timing adjust mode */
u16 irq_stat; /* interrupt status */
unsigned int clk_src_div;
@@ -526,7 +528,11 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
else
ext_conf_val = I2C_FS_START_CON;
- if (i2c->dev_comp->timing_adjust) {
+ if (i2c->default_timing_adjust) {
+ if (i2c->dev_comp->timing_adjust)
+ mtk_i2c_writew(i2c, I2C_DEFAULT_CLK_DIV - 1,
+ OFFSET_CLOCK_DIV);
+ } else if (i2c->dev_comp->timing_adjust) {
ext_conf_val = i2c->ac_timing.ext;
mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div,
OFFSET_CLOCK_DIV);
@@ -609,7 +615,7 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
unsigned int sample_ns = div_u64(1000000000ULL * (sample_cnt + 1),
clk_src);
- if (!i2c->dev_comp->timing_adjust)
+ if (i2c->default_timing_adjust || !i2c->dev_comp->timing_adjust)
return 0;
if (i2c->dev_comp->ltiming_adjust)
@@ -769,7 +775,65 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
return 0;
}
-static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
+static int mtk_i2c_set_speed_default_timing(struct mtk_i2c *i2c,
+ unsigned int parent_clk)
+{
+ unsigned int clk_src;
+ unsigned int step_cnt;
+ unsigned int sample_cnt;
+ unsigned int l_step_cnt;
+ unsigned int l_sample_cnt;
+ unsigned int target_speed;
+ int ret;
+
+ if (i2c->dev_comp->timing_adjust)
+ i2c->clk_src_div *= I2C_DEFAULT_CLK_DIV;
+
+ clk_src = parent_clk / i2c->clk_src_div;
+ target_speed = i2c->speed_hz;
+
+ if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
+ /* Set master code speed register */
+ ret = mtk_i2c_calculate_speed(i2c, clk_src,
+ I2C_MAX_FAST_MODE_FREQ,
+ &l_step_cnt, &l_sample_cnt);
+ if (ret < 0)
+ return ret;
+
+ i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt;
+
+ /* Set the high speed mode register */
+ ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
+ &step_cnt, &sample_cnt);
+ if (ret < 0)
+ return ret;
+
+ i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+ (sample_cnt << 12) | (step_cnt << 8);
+
+ if (i2c->dev_comp->ltiming_adjust)
+ i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt |
+ (sample_cnt << 12) | (step_cnt << 9);
+ } else {
+ ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
+ &step_cnt, &sample_cnt);
+ if (ret < 0)
+ return ret;
+
+ i2c->timing_reg = (sample_cnt << 8) | step_cnt;
+
+ /* Disable the high speed transaction */
+ i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
+
+ if (i2c->dev_comp->ltiming_adjust)
+ i2c->ltiming_reg = (sample_cnt << 6) | step_cnt;
+ }
+
+ return 0;
+}
+
+static int mtk_i2c_set_speed_adjust_timing(struct mtk_i2c *i2c,
+ unsigned int parent_clk)
{
unsigned int clk_src;
unsigned int step_cnt;
@@ -1254,6 +1318,8 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
i2c->use_push_pull =
of_property_read_bool(np, "mediatek,use-push-pull");
+ i2c->default_timing_adjust =
+ of_property_read_bool(np, "mediatek,default-timing-adjust");
i2c_parse_fw_timings(i2c->dev, &i2c->timing_info, true);
@@ -1333,7 +1399,10 @@ static int mtk_i2c_probe(struct platform_device *pdev)
strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
- ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk));
+ if (i2c->default_timing_adjust)
+ ret = mtk_i2c_set_speed_default_timing(i2c, clk_get_rate(clk));
+ else
+ ret = mtk_i2c_set_speed_adjust_timing(i2c, clk_get_rate(clk));
if (ret) {
dev_err(&pdev->dev, "Failed to set the speed.\n");
return -EINVAL;
--
2.18.0
Add a DT binding documentation for the MT8195 soc.
Signed-off-by: Kewei Xu <[email protected]>
---
Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 7f0194fdd0cc..7c4915bc4439 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -15,6 +15,7 @@ Required properties:
"mediatek,mt8173-i2c": for MediaTek MT8173
"mediatek,mt8183-i2c": for MediaTek MT8183
"mediatek,mt8192-i2c": for MediaTek MT8192
+ "mediatek,mt8195-i2c", "mediatek,mt8192-i2c": for MediaTek MT8195
"mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516
- reg: physical base address of the controller and dma base, length of memory
mapped region.
--
2.18.0
When a timeout error occurs in i2c transter, it is usually related
to the i2c/dma IP hardware configuration. Therefore, the purpose of
this patch is to dump the key register values of i2c/dma when a
timeout occurs in i2c for debugging.
Signed-off-by: Kewei Xu <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 56 ++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index c0108387f34b..abdbf27b6eb4 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -128,6 +128,7 @@ enum I2C_REGS_OFFSET {
OFFSET_HS,
OFFSET_SOFTRESET,
OFFSET_DCM_EN,
+ OFFSET_MULTI_DMA,
OFFSET_PATH_DIR,
OFFSET_DEBUGSTAT,
OFFSET_DEBUGCTRL,
@@ -195,6 +196,7 @@ static const u16 mt_i2c_regs_v2[] = {
[OFFSET_TRANSFER_LEN_AUX] = 0x44,
[OFFSET_CLOCK_DIV] = 0x48,
[OFFSET_SOFTRESET] = 0x50,
+ [OFFSET_MULTI_DMA] = 0x8c,
[OFFSET_SCL_MIS_COMP_POINT] = 0x90,
[OFFSET_DEBUGSTAT] = 0xe4,
[OFFSET_DEBUGCTRL] = 0xe8,
@@ -831,6 +833,57 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
return 0;
}
+static void i2c_dump_register(struct mtk_i2c *i2c)
+{
+ dev_err(i2c->dev, "SLAVE_ADDR: 0x%x, INTR_MASK: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_SLAVE_ADDR),
+ mtk_i2c_readw(i2c, OFFSET_INTR_MASK));
+ dev_err(i2c->dev, "INTR_STAT: 0x%x, CONTROL: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_INTR_STAT),
+ mtk_i2c_readw(i2c, OFFSET_CONTROL));
+ dev_err(i2c->dev, "TRANSFER_LEN: 0x%x, TRANSAC_LEN: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN),
+ mtk_i2c_readw(i2c, OFFSET_TRANSAC_LEN));
+ dev_err(i2c->dev, "DELAY_LEN: 0x%x, HTIMING: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_DELAY_LEN),
+ mtk_i2c_readw(i2c, OFFSET_TIMING));
+ dev_err(i2c->dev, "START: 0x%x, EXT_CONF: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_START),
+ mtk_i2c_readw(i2c, OFFSET_EXT_CONF));
+ dev_err(i2c->dev, "HS: 0x%x, IO_CONFIG: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_HS),
+ mtk_i2c_readw(i2c, OFFSET_IO_CONFIG));
+ dev_err(i2c->dev, "DCM_EN: 0x%x, TRANSFER_LEN_AUX: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_DCM_EN),
+ mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN_AUX));
+ dev_err(i2c->dev, "CLOCK_DIV: 0x%x, FIFO_STAT: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_CLOCK_DIV),
+ mtk_i2c_readw(i2c, OFFSET_FIFO_STAT));
+ dev_err(i2c->dev, "DEBUGCTRL : 0x%x, DEBUGSTAT: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_DEBUGCTRL),
+ mtk_i2c_readw(i2c, OFFSET_DEBUGSTAT));
+ if (i2c->dev_comp->regs == mt_i2c_regs_v2) {
+ dev_err(i2c->dev, "LTIMING: 0x%x, MULTI_DMA: 0x%x\n",
+ mtk_i2c_readw(i2c, OFFSET_LTIMING),
+ mtk_i2c_readw(i2c, OFFSET_MULTI_DMA));
+ }
+ dev_err(i2c->dev, "\nDMA_INT_FLAG: 0x%x, DMA_INT_EN: 0x%x\n",
+ readl(i2c->pdmabase + OFFSET_INT_FLAG),
+ readl(i2c->pdmabase + OFFSET_INT_EN));
+ dev_err(i2c->dev, "DMA_EN: 0x%x, DMA_CON: 0x%x\n",
+ readl(i2c->pdmabase + OFFSET_EN),
+ readl(i2c->pdmabase + OFFSET_CON));
+ dev_err(i2c->dev, "DMA_TX_MEM_ADDR: 0x%x, DMA_RX_MEM_ADDR: 0x%x\n",
+ readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR),
+ readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR));
+ dev_err(i2c->dev, "DMA_TX_LEN: 0x%x, DMA_RX_LEN: 0x%x\n",
+ readl(i2c->pdmabase + OFFSET_TX_LEN),
+ readl(i2c->pdmabase + OFFSET_RX_LEN));
+ dev_err(i2c->dev, "DMA_TX_4G_MODE: 0x%x, DMA_RX_4G_MODE: 0x%x",
+ readl(i2c->pdmabase + OFFSET_TX_4G_MODE),
+ readl(i2c->pdmabase + OFFSET_RX_4G_MODE));
+}
+
static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
int num, int left_num)
{
@@ -1048,7 +1101,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
}
if (ret == 0) {
- dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+ dev_err(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+ i2c_dump_register(i2c);
mtk_i2c_init_hw(i2c);
return -ETIMEDOUT;
}
--
2.18.0
On Sat, Jul 17, 2021 at 06:17:56PM +0800, Kewei Xu wrote:
> Add attribute default-timing-adjust for DT-binding document.
>
> Fixes: be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust support")
> Signed-off-by: Kewei Xu <[email protected]>
> ---
> Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> index 7c4915bc4439..7b80a11d4d4c 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> @@ -33,6 +33,8 @@ Optional properties:
> - mediatek,have-pmic: platform can control i2c form special pmic side.
> Only mt6589 and mt8135 support this feature.
> - mediatek,use-push-pull: IO config use push-pull mode.
> + - mediatek,default-timing-adjust: use default timing calculation, no timing
> + adjustment.
'mediatek,use-default-timing' perhaps as it means don't adjust anything.
>
> Example:
>
> --
> 2.18.0
>
>
Hi,
On Sat, Jul 17, 2021 at 6:29 PM Kewei Xu <[email protected]> wrote:
>
> Due to changes in the hardware design of the handshaking signal
> between i2c and dma, it is necessary to reset the handshaking
> signal before each transfer to ensure that the multi-msgs can
> be transferred correctly.
This also affects MT8192. Has this been tested on that SoC as well?
> Signed-off-by: Kewei Xu <[email protected]>
> ---
> drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 222ff765e55d..c0108387f34b 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -47,6 +47,9 @@
> #define I2C_RD_TRANAC_VALUE 0x0001
> #define I2C_SCL_MIS_COMP_VALUE 0x0000
> #define I2C_CHN_CLR_FLAG 0x0000
> +#define I2C_CLR_DEBUGCTR 0x0000
> +#define I2C_RELIABILITY 0x0010
> +#define I2C_DMAACK_ENABLE 0x0008
>
> #define I2C_DMA_CON_TX 0x0000
> #define I2C_DMA_CON_RX 0x0001
> @@ -850,6 +853,17 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>
> reinit_completion(&i2c->msg_complete);
>
> + if (i2c->dev_comp->apdma_sync) {
> + mtk_i2c_writew(i2c, I2C_CLR_DEBUGCTR, OFFSET_DEBUGCTRL);
> + writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
> + i2c->pdmabase + OFFSET_RST);
> + writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
I2C_DMA_WARM_RST is self-clearing. Is I2C_DMA_HANDSHAKE_RST not
self-clearing? If both are self-clearing, don't you need to wait and
check for them to cleared? If they aren't self-clearing, do you need
to delay some time for them to complete?
> + mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET);
> + mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
Same here. No time delay needed?
> + mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE,
> + OFFSET_DEBUGCTRL);
A comment explaining what the section above does would be nice. AFAICU
this is force resetting the DMA handling.
Regards
ChenYu
> + }
> +
> control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
> ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
> if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))
> --
> 2.18.0
> _______________________________________________
> Linux-mediatek mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
On Wed, 2021-07-21 at 21:10 -0600, Rob Herring wrote:
> On Sat, Jul 17, 2021 at 06:17:56PM +0800, Kewei Xu wrote:
> > Add attribute default-timing-adjust for DT-binding document.
> >
> > Fixes: be5ce0e97cc7 ("i2c: mediatek: Add i2c ac-timing adjust
> > support")
> > Signed-off-by: Kewei Xu <[email protected]>
> > ---
> > Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > index 7c4915bc4439..7b80a11d4d4c 100644
> > --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > @@ -33,6 +33,8 @@ Optional properties:
> > - mediatek,have-pmic: platform can control i2c form special pmic
> > side.
> > Only mt6589 and mt8135 support this feature.
> > - mediatek,use-push-pull: IO config use push-pull mode.
> > + - mediatek,default-timing-adjust: use default timing
> > calculation, no timing
> > + adjustment.
>
> 'mediatek,use-default-timing' perhaps as it means don't adjust
> anything.
>
> >
> > Example:
> >
> > --
> > 2.18.0
> >
Hi Rob,
Thanks for your suggestion. We will use "mediatek,use-default-timing"
instead of "mediatek,default-timing-adjust" in the next version of
patch.
Thanks
kewei
On Wed, 2021-08-11 at 16:41 +0800, Chen-Yu Tsai wrote:
> Hi,
>
> On Sat, Jul 17, 2021 at 6:29 PM Kewei Xu <[email protected]>
> wrote:
> >
> > Due to changes in the hardware design of the handshaking signal
> > between i2c and dma, it is necessary to reset the handshaking
> > signal before each transfer to ensure that the multi-msgs can
> > be transferred correctly.
>
> This also affects MT8192. Has this been tested on that SoC as well?
Yes, It has been tested on MT8192.
>
> > Signed-off-by: Kewei Xu <[email protected]>
> > ---
> > drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
> > 1 file changed, 14 insertions(+)
> >
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index 222ff765e55d..c0108387f34b 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -47,6 +47,9 @@
> > #define I2C_RD_TRANAC_VALUE 0x0001
> > #define I2C_SCL_MIS_COMP_VALUE 0x0000
> > #define I2C_CHN_CLR_FLAG 0x0000
> > +#define I2C_CLR_DEBUGCTR 0x0000
> > +#define I2C_RELIABILITY 0x0010
> > +#define I2C_DMAACK_ENABLE 0x0008
> >
> > #define I2C_DMA_CON_TX 0x0000
> > #define I2C_DMA_CON_RX 0x0001
> > @@ -850,6 +853,17 @@ static int mtk_i2c_do_transfer(struct mtk_i2c
> > *i2c, struct i2c_msg *msgs,
> >
> > reinit_completion(&i2c->msg_complete);
> >
> > + if (i2c->dev_comp->apdma_sync) {
> > + mtk_i2c_writew(i2c, I2C_CLR_DEBUGCTR,
> > OFFSET_DEBUGCTRL);
> > + writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
> > + i2c->pdmabase + OFFSET_RST);
> > + writel(I2C_DMA_CLR_FLAG, i2c->pdmabase +
> > OFFSET_RST);
>
> I2C_DMA_WARM_RST is self-clearing. Is I2C_DMA_HANDSHAKE_RST not
> self-clearing? If both are self-clearing, don't you need to wait and
> check for them to cleared? If they aren't self-clearing, do you need
> to delay some time for them to complete?
>
Thank you for your suggestion. We will appropriately add the delay in
the next version of patch according to the hardware behavior
characteristics.
Regards
Kewei
> > + mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST,
> > OFFSET_SOFTRESET);
> > + mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG,
> > OFFSET_SOFTRESET);
>
> Same here. No time delay needed?
>
> > + mtk_i2c_writew(i2c, I2C_RELIABILITY |
> > I2C_DMAACK_ENABLE,
> > + OFFSET_DEBUGCTRL);
>
> A comment explaining what the section above does would be nice.
> AFAICU
> this is force resetting the DMA handling.
>
>
> Regards
> ChenYu
>
> > + }
> > +
> > control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
> > ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
> > if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) ||
> > (left_num >= 1))
> > --
> > 2.18.0
> > _______________________________________________
> > Linux-mediatek mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek