mediatek: cleanly backport and add fix for I2C driver mt7981-i2c-clk-fix
authorDaniel Golle <daniel@makrotopia.org>
Fri, 26 May 2023 12:49:02 +0000 (13:49 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Fri, 26 May 2023 13:31:36 +0000 (14:31 +0100)
Pick accepted patches from upstream Linux tree instead of having to
maintain our slightly different downstream patches.
Import pending patch fixing I2C on MT7981.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
19 files changed:
target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi
target/linux/mediatek/patches-5.15/803-i2c-busses-add-mt7986-support.patch [deleted file]
target/linux/mediatek/patches-5.15/810-i2c-mediatek-add-support-for-MT7981-SoC.patch [deleted file]
target/linux/mediatek/patches-5.15/840-01-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-02-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-03-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-04-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-05-v5.18-i2c-mediatek-remove-redundant-null-check.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-06-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-07-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-08-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-09-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-10-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-11-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-12-v6.2-i2c-mediatek-add-mt7986-support.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-13-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-14-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-15-next-i2c-mediatek-add-support-for-MT7981-SoC.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/840-16-pending-i2c-mt65xx-add-additional-clocks.patch [new file with mode: 0644]

index 95b548143b43b0964110d75fb8293cf9e5301a2f..07a8c06979e58f40d5a9d6d48b431b4432605257 100644 (file)
                interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
                clock-div = <1>;
                clocks = <&infracfg CLK_INFRA_I2C0_CK>,
-                        <&infracfg CLK_INFRA_AP_DMA_CK>;
-               clock-names = "main", "dma";
+                        <&infracfg CLK_INFRA_AP_DMA_CK>,
+                        <&infracfg CLK_INFRA_I2C_MCK_CK>,
+                        <&infracfg CLK_INFRA_I2C_PCK_CK>;
+               clock-names = "main", "dma", "mck", "pck";
                #address-cells = <1>;
                #size-cells = <0>;
                status = "disabled";
diff --git a/target/linux/mediatek/patches-5.15/803-i2c-busses-add-mt7986-support.patch b/target/linux/mediatek/patches-5.15/803-i2c-busses-add-mt7986-support.patch
deleted file mode 100644 (file)
index 1860a6d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
---- a/drivers/i2c/busses/i2c-mt65xx.c
-+++ b/drivers/i2c/busses/i2c-mt65xx.c
-@@ -365,6 +365,19 @@ static const struct mtk_i2c_compatible m
-       .max_dma_support = 32,
- };
-+static const struct mtk_i2c_compatible mt7986_compat = {
-+      .quirks = &mt7622_i2c_quirks,
-+      .regs = mt_i2c_regs_v1,
-+      .pmic_i2c = 0,
-+      .dcm = 1,
-+      .auto_restart = 1,
-+      .aux_len_reg = 1,
-+      .max_dma_support = 32,
-+      .timing_adjust = 0,
-+      .dma_sync = 1,
-+      .ltiming_adjust = 0,
-+};
-+
- static const struct mtk_i2c_compatible mt8173_compat = {
-       .regs = mt_i2c_regs_v1,
-       .pmic_i2c = 0,
-@@ -411,6 +424,7 @@ static const struct of_device_id mtk_i2c
-       { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
-       { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
-       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
-+      { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
-       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
-       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
-       { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
diff --git a/target/linux/mediatek/patches-5.15/810-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-5.15/810-i2c-mediatek-add-support-for-MT7981-SoC.patch
deleted file mode 100644 (file)
index f9ad79c..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From bd4f7dae6a1f2fd65bb2112783c92ffe0839bc77 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Tue, 28 Feb 2023 23:53:56 +0000
-Subject: [PATCH] i2c: mediatek: add support for MT7981 SoC
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
---- a/drivers/i2c/busses/i2c-mt65xx.c
-+++ b/drivers/i2c/busses/i2c-mt65xx.c
-@@ -202,6 +202,34 @@ static const u16 mt_i2c_regs_v2[] = {
-       [OFFSET_DCM_EN] = 0xf88,
- };
-+static const u16 mt_i2c_regs_v3[] = {
-+      [OFFSET_DATA_PORT] = 0x0,
-+      [OFFSET_INTR_MASK] = 0x8,
-+      [OFFSET_INTR_STAT] = 0xc,
-+      [OFFSET_CONTROL] = 0x10,
-+      [OFFSET_TRANSFER_LEN] = 0x14,
-+      [OFFSET_TRANSAC_LEN] = 0x18,
-+      [OFFSET_DELAY_LEN] = 0x1c,
-+      [OFFSET_TIMING] = 0x20,
-+      [OFFSET_START] = 0x24,
-+      [OFFSET_EXT_CONF] = 0x28,
-+      [OFFSET_LTIMING] = 0x2c,
-+      [OFFSET_HS] = 0x30,
-+      [OFFSET_IO_CONFIG] = 0x34,
-+      [OFFSET_FIFO_ADDR_CLR] = 0x38,
-+      [OFFSET_SDA_TIMING] = 0x3c,
-+      [OFFSET_TRANSFER_LEN_AUX] = 0x44,
-+      [OFFSET_CLOCK_DIV] = 0x48,
-+      [OFFSET_SOFTRESET] = 0x50,
-+      [OFFSET_SCL_MIS_COMP_POINT] = 0x90,
-+      [OFFSET_SLAVE_ADDR] = 0x94,
-+      [OFFSET_DEBUGSTAT] = 0xe4,
-+      [OFFSET_DEBUGCTRL] = 0xe8,
-+      [OFFSET_FIFO_STAT] = 0xf4,
-+      [OFFSET_FIFO_THRESH] = 0xf8,
-+      [OFFSET_DCM_EN] = 0xf88,
-+};
-+
- struct mtk_i2c_compatible {
-       const struct i2c_adapter_quirks *quirks;
-       const u16 *regs;
-@@ -365,6 +393,18 @@ static const struct mtk_i2c_compatible m
-       .max_dma_support = 32,
- };
-+static const struct mtk_i2c_compatible mt7981_compat = {
-+      .regs = mt_i2c_regs_v3,
-+      .pmic_i2c = 0,
-+      .dcm = 0,
-+      .auto_restart = 1,
-+      .aux_len_reg = 1,
-+      .timing_adjust = 1,
-+      .dma_sync = 1,
-+      .ltiming_adjust = 1,
-+      .max_dma_support = 33
-+};
-+
- static const struct mtk_i2c_compatible mt7986_compat = {
-       .quirks = &mt7622_i2c_quirks,
-       .regs = mt_i2c_regs_v1,
-@@ -424,6 +464,7 @@ static const struct of_device_id mtk_i2c
-       { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
-       { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
-       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
-+      { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat },
-       { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
-       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
-       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
diff --git a/target/linux/mediatek/patches-5.15/840-01-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch b/target/linux/mediatek/patches-5.15/840-01-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch
new file mode 100644 (file)
index 0000000..8b01196
--- /dev/null
@@ -0,0 +1,74 @@
+From 95e4dfbf33dc0a0843ba20db811f7ea271235e1e Mon Sep 17 00:00:00 2001
+From: Kewei Xu <kewei.xu@mediatek.com>
+Date: Sun, 10 Oct 2021 15:05:12 +0800
+Subject: [PATCH 01/16] i2c: mediatek: Reset the handshake signal between i2c
+ and dma
+
+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 <kewei.xu@mediatek.com>
+Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -15,6 +15,7 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
++#include <linux/iopoll.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+@@ -49,6 +50,8 @@
+ #define I2C_RD_TRANAC_VALUE           0x0001
+ #define I2C_SCL_MIS_COMP_VALUE                0x0000
+ #define I2C_CHN_CLR_FLAG              0x0000
++#define I2C_RELIABILITY               0x0010
++#define I2C_DMAACK_ENABLE             0x0008
+ #define I2C_DMA_CON_TX                        0x0000
+ #define I2C_DMA_CON_RX                        0x0001
+@@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mt
+       u16 restart_flag = 0;
+       u16 dma_sync = 0;
+       u32 reg_4g_mode;
++      u32 reg_dma_reset;
+       u8 *dma_rd_buf = NULL;
+       u8 *dma_wr_buf = NULL;
+       dma_addr_t rpaddr = 0;
+@@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mt
+       reinit_completion(&i2c->msg_complete);
++      if (i2c->dev_comp->apdma_sync &&
++          i2c->op != I2C_MASTER_WRRD && num > 1) {
++              mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL);
++              writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
++                     i2c->pdmabase + OFFSET_RST);
++
++              ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST,
++                                       reg_dma_reset,
++                                       !(reg_dma_reset & I2C_DMA_WARM_RST),
++                                       0, 100);
++              if (ret) {
++                      dev_err(i2c->dev, "DMA warm reset timeout\n");
++                      return -ETIMEDOUT;
++              }
++
++              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))
diff --git a/target/linux/mediatek/patches-5.15/840-02-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch b/target/linux/mediatek/patches-5.15/840-02-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch
new file mode 100644 (file)
index 0000000..a2d2521
--- /dev/null
@@ -0,0 +1,102 @@
+From 5b8e29e566e086ef9b5b9ea0d054370a295e1d05 Mon Sep 17 00:00:00 2001
+From: Kewei Xu <kewei.xu@mediatek.com>
+Date: Sun, 10 Oct 2021 15:05:13 +0800
+Subject: [PATCH 02/16] i2c: mediatek: Dump i2c/dma register when a timeout
+ occurs
+
+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 <kewei.xu@mediatek.com>
+Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 54 +++++++++++++++++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -130,6 +130,7 @@ enum I2C_REGS_OFFSET {
+       OFFSET_HS,
+       OFFSET_SOFTRESET,
+       OFFSET_DCM_EN,
++      OFFSET_MULTI_DMA,
+       OFFSET_PATH_DIR,
+       OFFSET_DEBUGSTAT,
+       OFFSET_DEBUGCTRL,
+@@ -197,6 +198,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,
+@@ -845,6 +847,57 @@ static int mtk_i2c_set_speed(struct mtk_
+       return 0;
+ }
++static void i2c_dump_register(struct mtk_i2c *i2c)
++{
++      dev_dbg(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_dbg(i2c->dev, "INTR_STAT: 0x%x, CONTROL: 0x%x\n",
++              mtk_i2c_readw(i2c, OFFSET_INTR_STAT),
++              mtk_i2c_readw(i2c, OFFSET_CONTROL));
++      dev_dbg(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_dbg(i2c->dev, "DELAY_LEN: 0x%x, HTIMING: 0x%x\n",
++              mtk_i2c_readw(i2c, OFFSET_DELAY_LEN),
++              mtk_i2c_readw(i2c, OFFSET_TIMING));
++      dev_dbg(i2c->dev, "START: 0x%x, EXT_CONF: 0x%x\n",
++              mtk_i2c_readw(i2c, OFFSET_START),
++              mtk_i2c_readw(i2c, OFFSET_EXT_CONF));
++      dev_dbg(i2c->dev, "HS: 0x%x, IO_CONFIG: 0x%x\n",
++              mtk_i2c_readw(i2c, OFFSET_HS),
++              mtk_i2c_readw(i2c, OFFSET_IO_CONFIG));
++      dev_dbg(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_dbg(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_dbg(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_dbg(i2c->dev, "LTIMING: 0x%x, MULTI_DMA: 0x%x\n",
++                      mtk_i2c_readw(i2c, OFFSET_LTIMING),
++                      mtk_i2c_readw(i2c, OFFSET_MULTI_DMA));
++      }
++      dev_dbg(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_dbg(i2c->dev, "DMA_EN: 0x%x, DMA_CON: 0x%x\n",
++              readl(i2c->pdmabase + OFFSET_EN),
++              readl(i2c->pdmabase + OFFSET_CON));
++      dev_dbg(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_dbg(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_dbg(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)
+ {
+@@ -1075,6 +1128,7 @@ static int mtk_i2c_do_transfer(struct mt
+       if (ret == 0) {
+               dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
++              i2c_dump_register(i2c);
+               mtk_i2c_init_hw(i2c);
+               return -ETIMEDOUT;
+       }
diff --git a/target/linux/mediatek/patches-5.15/840-03-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch b/target/linux/mediatek/patches-5.15/840-03-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch
new file mode 100644 (file)
index 0000000..184fe94
--- /dev/null
@@ -0,0 +1,45 @@
+From 83630e3c6147bf7bb18a18f3d5a99462464f450b Mon Sep 17 00:00:00 2001
+From: Kewei Xu <kewei.xu@mediatek.com>
+Date: Tue, 25 Jan 2022 19:04:13 +0800
+Subject: [PATCH 03/16] i2c: mediatek: Add i2c compatible for Mediatek MT8186
+
+Add i2c compatible for MT8186. Compare to MT8192 i2c controller,
+MT8186 doesn't need handshake signal witch apdma.
+
+Signed-off-by: Kewei Xu <kewei.xu@mediatek.com>
+Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -397,6 +397,19 @@ static const struct mtk_i2c_compatible m
+       .max_dma_support = 33,
+ };
++static const struct mtk_i2c_compatible mt8186_compat = {
++      .regs = mt_i2c_regs_v2,
++      .pmic_i2c = 0,
++      .dcm = 0,
++      .auto_restart = 1,
++      .aux_len_reg = 1,
++      .timing_adjust = 1,
++      .dma_sync = 0,
++      .ltiming_adjust = 1,
++      .apdma_sync = 0,
++      .max_dma_support = 36,
++};
++
+ static const struct mtk_i2c_compatible mt8192_compat = {
+       .quirks = &mt8183_i2c_quirks,
+       .regs = mt_i2c_regs_v2,
+@@ -418,6 +431,7 @@ static const struct of_device_id mtk_i2c
+       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
+       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
++      { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat },
+       { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
+       {}
+ };
diff --git a/target/linux/mediatek/patches-5.15/840-04-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch b/target/linux/mediatek/patches-5.15/840-04-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch
new file mode 100644 (file)
index 0000000..0ace4a6
--- /dev/null
@@ -0,0 +1,132 @@
+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;
+ }
diff --git a/target/linux/mediatek/patches-5.15/840-05-v5.18-i2c-mediatek-remove-redundant-null-check.patch b/target/linux/mediatek/patches-5.15/840-05-v5.18-i2c-mediatek-remove-redundant-null-check.patch
new file mode 100644 (file)
index 0000000..8f3c965
--- /dev/null
@@ -0,0 +1,41 @@
+From eb4a2ae019815946f574cd9f8209e12bdcd8fd34 Mon Sep 17 00:00:00 2001
+From: Xu Wang <vulab@iscas.ac.cn>
+Date: Wed, 30 Sep 2020 08:42:33 +0000
+Subject: [PATCH 05/16] i2c: mediatek: remove redundant null check
+
+Because clk_disable_unprepare already checked NULL clock parameter,
+so the additional checks are unnecessary, just remove it
+
+Signed-off-by: Xu Wang <vulab@iscas.ac.cn>
+Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -476,8 +476,7 @@ static int mtk_i2c_clock_enable(struct m
+       return 0;
+ err_arb:
+-      if (i2c->have_pmic)
+-              clk_disable_unprepare(i2c->clk_pmic);
++      clk_disable_unprepare(i2c->clk_pmic);
+ err_pmic:
+       clk_disable_unprepare(i2c->clk_main);
+ err_main:
+@@ -488,11 +487,9 @@ err_main:
+ static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+ {
+-      if (i2c->clk_arb)
+-              clk_disable_unprepare(i2c->clk_arb);
++      clk_disable_unprepare(i2c->clk_arb);
+-      if (i2c->have_pmic)
+-              clk_disable_unprepare(i2c->clk_pmic);
++      clk_disable_unprepare(i2c->clk_pmic);
+       clk_disable_unprepare(i2c->clk_main);
+       clk_disable_unprepare(i2c->clk_dma);
diff --git a/target/linux/mediatek/patches-5.15/840-06-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch b/target/linux/mediatek/patches-5.15/840-06-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch
new file mode 100644 (file)
index 0000000..71d083f
--- /dev/null
@@ -0,0 +1,234 @@
+From cc6faa5e0772296d815fd298c231277d47308a6a Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Thu, 3 Mar 2022 10:15:47 +0100
+Subject: [PATCH 06/16] i2c: mt65xx: Simplify with clk-bulk
+
+Since depending on the SoC or specific bus functionality some clocks
+may be optional, we cannot get the benefit of using devm_clk_bulk_get()
+but, by migrating to clk-bulk, we are able to remove the custom functions
+mtk_i2c_clock_enable() and mtk_i2c_clock_disable(), increasing common
+APIs usage, hence (lightly) decreasing kernel footprint.
+
+Signed-off-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 | 124 +++++++++++++-------------------
+ 1 file changed, 51 insertions(+), 73 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -86,6 +86,27 @@
+ #define I2C_DRV_NAME          "i2c-mt65xx"
++/**
++ * enum i2c_mt65xx_clks - Clocks enumeration for MT65XX I2C
++ *
++ * @I2C_MT65XX_CLK_MAIN: main clock for i2c bus
++ * @I2C_MT65XX_CLK_DMA:  DMA clock for i2c via DMA
++ * @I2C_MT65XX_CLK_PMIC: PMIC clock for i2c from PMIC
++ * @I2C_MT65XX_CLK_ARB:  Arbitrator clock for i2c
++ * @I2C_MT65XX_CLK_MAX:  Number of supported clocks
++ */
++enum i2c_mt65xx_clks {
++      I2C_MT65XX_CLK_MAIN = 0,
++      I2C_MT65XX_CLK_DMA,
++      I2C_MT65XX_CLK_PMIC,
++      I2C_MT65XX_CLK_ARB,
++      I2C_MT65XX_CLK_MAX
++};
++
++static const char * const i2c_mt65xx_clk_ids[I2C_MT65XX_CLK_MAX] = {
++      "main", "dma", "pmic", "arb"
++};
++
+ enum DMA_REGS_OFFSET {
+       OFFSET_INT_FLAG = 0x0,
+       OFFSET_INT_EN = 0x04,
+@@ -244,10 +265,7 @@ struct mtk_i2c {
+       /* set in i2c probe */
+       void __iomem *base;             /* i2c base addr */
+       void __iomem *pdmabase;         /* dma base address*/
+-      struct clk *clk_main;           /* main clock for i2c bus */
+-      struct clk *clk_dma;            /* DMA clock for i2c via DMA */
+-      struct clk *clk_pmic;           /* PMIC clock for i2c from PMIC */
+-      struct clk *clk_arb;            /* Arbitrator clock for i2c */
++      struct clk_bulk_data clocks[I2C_MT65XX_CLK_MAX]; /* clocks for i2c */
+       bool have_pmic;                 /* can use i2c pins from PMIC */
+       bool use_push_pull;             /* IO config push-pull mode */
+@@ -449,52 +467,6 @@ static void mtk_i2c_writew(struct mtk_i2
+       writew(val, i2c->base + i2c->dev_comp->regs[reg]);
+ }
+-static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
+-{
+-      int ret;
+-
+-      ret = clk_prepare_enable(i2c->clk_dma);
+-      if (ret)
+-              return ret;
+-
+-      ret = clk_prepare_enable(i2c->clk_main);
+-      if (ret)
+-              goto err_main;
+-
+-      if (i2c->have_pmic) {
+-              ret = clk_prepare_enable(i2c->clk_pmic);
+-              if (ret)
+-                      goto err_pmic;
+-      }
+-
+-      if (i2c->clk_arb) {
+-              ret = clk_prepare_enable(i2c->clk_arb);
+-              if (ret)
+-                      goto err_arb;
+-      }
+-
+-      return 0;
+-
+-err_arb:
+-      clk_disable_unprepare(i2c->clk_pmic);
+-err_pmic:
+-      clk_disable_unprepare(i2c->clk_main);
+-err_main:
+-      clk_disable_unprepare(i2c->clk_dma);
+-
+-      return ret;
+-}
+-
+-static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+-{
+-      clk_disable_unprepare(i2c->clk_arb);
+-
+-      clk_disable_unprepare(i2c->clk_pmic);
+-
+-      clk_disable_unprepare(i2c->clk_main);
+-      clk_disable_unprepare(i2c->clk_dma);
+-}
+-
+ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
+ {
+       u16 control_reg;
+@@ -1191,7 +1163,7 @@ static int mtk_i2c_transfer(struct i2c_a
+       int left_num = num;
+       struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+-      ret = mtk_i2c_clock_enable(i2c);
++      ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       if (ret)
+               return ret;
+@@ -1245,7 +1217,7 @@ static int mtk_i2c_transfer(struct i2c_a
+       ret = num;
+ err_exit:
+-      mtk_i2c_clock_disable(i2c);
++      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       return ret;
+ }
+@@ -1323,9 +1295,8 @@ static int mtk_i2c_probe(struct platform
+ {
+       int ret = 0;
+       struct mtk_i2c *i2c;
+-      struct clk *clk;
+       struct resource *res;
+-      int irq;
++      int i, irq, speed_clk;
+       i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+@@ -1371,35 +1342,42 @@ static int mtk_i2c_probe(struct platform
+       if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
+               return -EINVAL;
+-      i2c->clk_main = devm_clk_get(&pdev->dev, "main");
+-      if (IS_ERR(i2c->clk_main)) {
++      /* Fill in clk-bulk IDs */
++      for (i = 0; i < I2C_MT65XX_CLK_MAX; i++)
++              i2c->clocks[i].id = i2c_mt65xx_clk_ids[i];
++
++      /* Get clocks one by one, some may be optional */
++      i2c->clocks[I2C_MT65XX_CLK_MAIN].clk = devm_clk_get(&pdev->dev, "main");
++      if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk)) {
+               dev_err(&pdev->dev, "cannot get main clock\n");
+-              return PTR_ERR(i2c->clk_main);
++              return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk);
+       }
+-      i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
+-      if (IS_ERR(i2c->clk_dma)) {
++      i2c->clocks[I2C_MT65XX_CLK_DMA].clk = devm_clk_get(&pdev->dev, "dma");
++      if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk)) {
+               dev_err(&pdev->dev, "cannot get dma clock\n");
+-              return PTR_ERR(i2c->clk_dma);
++              return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk);
+       }
+-      i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
+-      if (IS_ERR(i2c->clk_arb))
+-              i2c->clk_arb = NULL;
++      i2c->clocks[I2C_MT65XX_CLK_ARB].clk = devm_clk_get_optional(&pdev->dev, "arb");
++      if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk))
++              return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk);
+-      clk = i2c->clk_main;
+       if (i2c->have_pmic) {
+-              i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
+-              if (IS_ERR(i2c->clk_pmic)) {
++              i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic");
++              if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {
+                       dev_err(&pdev->dev, "cannot get pmic clock\n");
+-                      return PTR_ERR(i2c->clk_pmic);
++                      return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk);
+               }
+-              clk = i2c->clk_pmic;
++              speed_clk = I2C_MT65XX_CLK_PMIC;
++      } else {
++              i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL;
++              speed_clk = I2C_MT65XX_CLK_MAIN;
+       }
+       strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+-      ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk));
++      ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk));
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to set the speed.\n");
+               return -EINVAL;
+@@ -1414,13 +1392,13 @@ static int mtk_i2c_probe(struct platform
+               }
+       }
+-      ret = mtk_i2c_clock_enable(i2c);
++      ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       if (ret) {
+               dev_err(&pdev->dev, "clock enable failed!\n");
+               return ret;
+       }
+       mtk_i2c_init_hw(i2c);
+-      mtk_i2c_clock_disable(i2c);
++      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+                              IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
+@@ -1465,7 +1443,7 @@ static int mtk_i2c_resume_noirq(struct d
+       int ret;
+       struct mtk_i2c *i2c = dev_get_drvdata(dev);
+-      ret = mtk_i2c_clock_enable(i2c);
++      ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       if (ret) {
+               dev_err(dev, "clock enable failed!\n");
+               return ret;
+@@ -1473,7 +1451,7 @@ static int mtk_i2c_resume_noirq(struct d
+       mtk_i2c_init_hw(i2c);
+-      mtk_i2c_clock_disable(i2c);
++      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       i2c_mark_adapter_resumed(&i2c->adap);
diff --git a/target/linux/mediatek/patches-5.15/840-07-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch b/target/linux/mediatek/patches-5.15/840-07-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch
new file mode 100644 (file)
index 0000000..fe5be94
--- /dev/null
@@ -0,0 +1,46 @@
+From de054c03f90b3ea22bc346fbf78ac716df192b2d Mon Sep 17 00:00:00 2001
+From: Kewei Xu <kewei.xu@mediatek.com>
+Date: Mon, 7 Mar 2022 11:36:49 +0800
+Subject: [PATCH 07/16] i2c: mediatek: Add i2c compatible for Mediatek MT8168
+
+Add i2c compatible for MT8168. Compare to MT2712 i2c controller,
+MT8168 need to synchronize signal with dma.
+
+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 | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -389,6 +389,19 @@ static const struct mtk_i2c_compatible m
+       .max_dma_support = 32,
+ };
++static const struct mtk_i2c_compatible mt8168_compat = {
++      .regs = mt_i2c_regs_v1,
++      .pmic_i2c = 0,
++      .dcm = 1,
++      .auto_restart = 1,
++      .aux_len_reg = 1,
++      .timing_adjust = 1,
++      .dma_sync = 1,
++      .ltiming_adjust = 0,
++      .apdma_sync = 0,
++      .max_dma_support = 33,
++};
++
+ static const struct mtk_i2c_compatible mt8173_compat = {
+       .regs = mt_i2c_regs_v1,
+       .pmic_i2c = 0,
+@@ -448,6 +461,7 @@ static const struct of_device_id mtk_i2c
+       { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
+       { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
+       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
++      { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat },
+       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
+       { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat },
diff --git a/target/linux/mediatek/patches-5.15/840-08-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch b/target/linux/mediatek/patches-5.15/840-08-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch
new file mode 100644 (file)
index 0000000..5c4ce40
--- /dev/null
@@ -0,0 +1,101 @@
+From 2831f9a53ec3a16012d2d23590e3ebad6084b763 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Mon, 11 Apr 2022 15:21:07 +0200
+Subject: [PATCH 08/16] i2c: mediatek: Optimize master_xfer() and avoid
+ circular locking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Especially (but not only) during probe, it may happen that multiple
+devices are communicating via i2c (or multiple i2c busses) and
+sometimes while others are probing asynchronously.
+For example, a Cr50 TPM may be filling entropy (or userspace may be
+reading random data) while the rt5682 (i2c) codec driver reads/sets
+some registers, like while getting/setting a clock's rate, which
+happens both during probe and during system operation.
+
+In this driver, the mtk_i2c_transfer() function (which is the i2c
+.master_xfer() callback) was granularly managing the clocks by
+performing a clk_bulk_prepare_enable() to start them and its inverse.
+This is not only creating possible circular locking dependencies in
+the some cases (like former explanation), but it's also suboptimal,
+as clk_core prepare/unprepare operations are using mutex locking,
+which creates a bit of unwanted overhead (for example, i2c trackpads
+will call master_xfer() every few milliseconds!).
+
+With this commit, we avoid both the circular locking and additional
+overhead by changing how we handle the clocks in this driver:
+- Prepare the clocks during probe (and PM resume)
+- Enable/disable clocks in mtk_i2c_transfer()
+- Unprepare the clocks only for driver removal (and PM suspend)
+
+For the sake of providing a full explanation: during probe, the
+clocks are not only prepared but also enabled, as this is needed
+for some hardware initialization but, after that, we are disabling
+but not unpreparing them, leaving an expected state for the
+aforementioned clock handling strategy.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -1177,7 +1177,7 @@ static int mtk_i2c_transfer(struct i2c_a
+       int left_num = num;
+       struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+-      ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
++      ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       if (ret)
+               return ret;
+@@ -1231,7 +1231,7 @@ static int mtk_i2c_transfer(struct i2c_a
+       ret = num;
+ err_exit:
+-      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
++      clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       return ret;
+ }
+@@ -1412,7 +1412,7 @@ static int mtk_i2c_probe(struct platform
+               return ret;
+       }
+       mtk_i2c_init_hw(i2c);
+-      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
++      clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+                              IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
+@@ -1439,6 +1439,8 @@ static int mtk_i2c_remove(struct platfor
+       i2c_del_adapter(&i2c->adap);
++      clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
++
+       return 0;
+ }
+@@ -1448,6 +1450,7 @@ static int mtk_i2c_suspend_noirq(struct
+       struct mtk_i2c *i2c = dev_get_drvdata(dev);
+       i2c_mark_adapter_suspended(&i2c->adap);
++      clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       return 0;
+ }
+@@ -1465,7 +1468,7 @@ static int mtk_i2c_resume_noirq(struct d
+       mtk_i2c_init_hw(i2c);
+-      clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
++      clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+       i2c_mark_adapter_resumed(&i2c->adap);
diff --git a/target/linux/mediatek/patches-5.15/840-09-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch b/target/linux/mediatek/patches-5.15/840-09-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch
new file mode 100644 (file)
index 0000000..354f12e
--- /dev/null
@@ -0,0 +1,48 @@
+From 6f3a5814c7aaea4176e0ac8b1ec6dc0a65aa2808 Mon Sep 17 00:00:00 2001
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Date: Sun, 22 May 2022 14:22:07 +0200
+Subject: [PATCH 09/16] i2c: mediatek: Fix an error handling path in
+ mtk_i2c_probe()
+
+The clsk are prepared, enabled, then disabled. So if an error occurs after
+the disable step, they are still prepared.
+
+Add an error handling path to unprepare the clks in such a case, as already
+done in the .remove function.
+
+Fixes: 8b4fc246c3ff ("i2c: mediatek: Optimize master_xfer() and avoid circular locking")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+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 | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -1420,17 +1420,22 @@ static int mtk_i2c_probe(struct platform
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Request I2C IRQ %d fail\n", irq);
+-              return ret;
++              goto err_bulk_unprepare;
+       }
+       i2c_set_adapdata(&i2c->adap, i2c);
+       ret = i2c_add_adapter(&i2c->adap);
+       if (ret)
+-              return ret;
++              goto err_bulk_unprepare;
+       platform_set_drvdata(pdev, i2c);
+       return 0;
++
++err_bulk_unprepare:
++      clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
++
++      return ret;
+ }
+ static int mtk_i2c_remove(struct platform_device *pdev)
diff --git a/target/linux/mediatek/patches-5.15/840-10-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch b/target/linux/mediatek/patches-5.15/840-10-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch
new file mode 100644 (file)
index 0000000..744aa96
--- /dev/null
@@ -0,0 +1,82 @@
+From 94c7f8af2c0a399c8aa66f2522b60c5784b5be6c Mon Sep 17 00:00:00 2001
+From: Kewei Xu <kewei.xu@mediatek.com>
+Date: Sat, 6 Aug 2022 18:02:49 +0800
+Subject: [PATCH 10/16] i2c: mediatek: add i2c compatible for MT8188
+
+Add i2c compatible for MT8188 and added mt_i2c_regs_v3[], since
+MT8188 i2c OFFSET_SLAVE_ADDR register changed from 0x04 to 0x94.
+
+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 | 43 +++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -229,6 +229,35 @@ static const u16 mt_i2c_regs_v2[] = {
+       [OFFSET_DCM_EN] = 0xf88,
+ };
++static const u16 mt_i2c_regs_v3[] = {
++      [OFFSET_DATA_PORT] = 0x0,
++      [OFFSET_INTR_MASK] = 0x8,
++      [OFFSET_INTR_STAT] = 0xc,
++      [OFFSET_CONTROL] = 0x10,
++      [OFFSET_TRANSFER_LEN] = 0x14,
++      [OFFSET_TRANSAC_LEN] = 0x18,
++      [OFFSET_DELAY_LEN] = 0x1c,
++      [OFFSET_TIMING] = 0x20,
++      [OFFSET_START] = 0x24,
++      [OFFSET_EXT_CONF] = 0x28,
++      [OFFSET_LTIMING] = 0x2c,
++      [OFFSET_HS] = 0x30,
++      [OFFSET_IO_CONFIG] = 0x34,
++      [OFFSET_FIFO_ADDR_CLR] = 0x38,
++      [OFFSET_SDA_TIMING] = 0x3c,
++      [OFFSET_TRANSFER_LEN_AUX] = 0x44,
++      [OFFSET_CLOCK_DIV] = 0x48,
++      [OFFSET_SOFTRESET] = 0x50,
++      [OFFSET_MULTI_DMA] = 0x8c,
++      [OFFSET_SCL_MIS_COMP_POINT] = 0x90,
++      [OFFSET_SLAVE_ADDR] = 0x94,
++      [OFFSET_DEBUGSTAT] = 0xe4,
++      [OFFSET_DEBUGCTRL] = 0xe8,
++      [OFFSET_FIFO_STAT] = 0xf4,
++      [OFFSET_FIFO_THRESH] = 0xf8,
++      [OFFSET_DCM_EN] = 0xf88,
++};
++
+ struct mtk_i2c_compatible {
+       const struct i2c_adapter_quirks *quirks;
+       const u16 *regs;
+@@ -442,6 +471,19 @@ static const struct mtk_i2c_compatible m
+       .max_dma_support = 36,
+ };
++static const struct mtk_i2c_compatible mt8188_compat = {
++      .regs = mt_i2c_regs_v3,
++      .pmic_i2c = 0,
++      .dcm = 0,
++      .auto_restart = 1,
++      .aux_len_reg = 1,
++      .timing_adjust = 1,
++      .dma_sync = 0,
++      .ltiming_adjust = 1,
++      .apdma_sync = 1,
++      .max_dma_support = 36,
++};
++
+ static const struct mtk_i2c_compatible mt8192_compat = {
+       .quirks = &mt8183_i2c_quirks,
+       .regs = mt_i2c_regs_v2,
+@@ -465,6 +507,7 @@ static const struct of_device_id mtk_i2c
+       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
+       { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat },
++      { .compatible = "mediatek,mt8188-i2c", .data = &mt8188_compat },
+       { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
+       {}
+ };
diff --git a/target/linux/mediatek/patches-5.15/840-11-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch b/target/linux/mediatek/patches-5.15/840-11-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch
new file mode 100644 (file)
index 0000000..5066899
--- /dev/null
@@ -0,0 +1,579 @@
+From 2f4ca256a98cc19787b7c861109dd1150a21b0bf Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Date: Thu, 11 Aug 2022 09:10:30 +0200
+Subject: [PATCH 11/16] i2c: move drivers from strlcpy to strscpy
+
+Follow the advice of the below link and prefer 'strscpy'. Conversion is
+easy because no driver used the return value and has been done with a
+simple sed invocation.
+
+Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-altera.c         | 2 +-
+ drivers/i2c/busses/i2c-aspeed.c         | 2 +-
+ drivers/i2c/busses/i2c-au1550.c         | 2 +-
+ drivers/i2c/busses/i2c-axxia.c          | 2 +-
+ drivers/i2c/busses/i2c-bcm-kona.c       | 2 +-
+ drivers/i2c/busses/i2c-cbus-gpio.c      | 2 +-
+ drivers/i2c/busses/i2c-cht-wc.c         | 2 +-
+ drivers/i2c/busses/i2c-cros-ec-tunnel.c | 2 +-
+ drivers/i2c/busses/i2c-davinci.c        | 2 +-
+ drivers/i2c/busses/i2c-digicolor.c      | 2 +-
+ drivers/i2c/busses/i2c-eg20t.c          | 2 +-
+ drivers/i2c/busses/i2c-emev2.c          | 2 +-
+ drivers/i2c/busses/i2c-exynos5.c        | 2 +-
+ drivers/i2c/busses/i2c-gpio.c           | 2 +-
+ drivers/i2c/busses/i2c-highlander.c     | 2 +-
+ drivers/i2c/busses/i2c-hix5hd2.c        | 2 +-
+ drivers/i2c/busses/i2c-i801.c           | 4 ++--
+ drivers/i2c/busses/i2c-ibm_iic.c        | 2 +-
+ drivers/i2c/busses/i2c-icy.c            | 2 +-
+ drivers/i2c/busses/i2c-imx-lpi2c.c      | 2 +-
+ drivers/i2c/busses/i2c-lpc2k.c          | 2 +-
+ drivers/i2c/busses/i2c-meson.c          | 2 +-
+ drivers/i2c/busses/i2c-mt65xx.c         | 2 +-
+ drivers/i2c/busses/i2c-mt7621.c         | 2 +-
+ drivers/i2c/busses/i2c-mv64xxx.c        | 2 +-
+ drivers/i2c/busses/i2c-mxs.c            | 2 +-
+ drivers/i2c/busses/i2c-nvidia-gpu.c     | 2 +-
+ drivers/i2c/busses/i2c-omap.c           | 2 +-
+ drivers/i2c/busses/i2c-opal.c           | 4 ++--
+ drivers/i2c/busses/i2c-parport.c        | 2 +-
+ drivers/i2c/busses/i2c-pxa.c            | 2 +-
+ drivers/i2c/busses/i2c-qcom-geni.c      | 2 +-
+ drivers/i2c/busses/i2c-qup.c            | 2 +-
+ drivers/i2c/busses/i2c-rcar.c           | 2 +-
+ drivers/i2c/busses/i2c-riic.c           | 2 +-
+ drivers/i2c/busses/i2c-rk3x.c           | 2 +-
+ drivers/i2c/busses/i2c-s3c2410.c        | 2 +-
+ drivers/i2c/busses/i2c-sh_mobile.c      | 2 +-
+ drivers/i2c/busses/i2c-simtec.c         | 2 +-
+ drivers/i2c/busses/i2c-taos-evm.c       | 2 +-
+ drivers/i2c/busses/i2c-tegra-bpmp.c     | 2 +-
+ drivers/i2c/busses/i2c-tegra.c          | 2 +-
+ drivers/i2c/busses/i2c-uniphier-f.c     | 2 +-
+ drivers/i2c/busses/i2c-uniphier.c       | 2 +-
+ drivers/i2c/busses/i2c-versatile.c      | 2 +-
+ drivers/i2c/busses/i2c-wmt.c            | 2 +-
+ 46 files changed, 48 insertions(+), 48 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-altera.c
++++ b/drivers/i2c/busses/i2c-altera.c
+@@ -447,7 +447,7 @@ static int altr_i2c_probe(struct platfor
+       mutex_unlock(&idev->isr_mutex);
+       i2c_set_adapdata(&idev->adapter, idev);
+-      strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
++      strscpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
+       idev->adapter.owner = THIS_MODULE;
+       idev->adapter.algo = &altr_i2c_algo;
+       idev->adapter.dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -1024,7 +1024,7 @@ static int aspeed_i2c_probe_bus(struct p
+       bus->adap.algo = &aspeed_i2c_algo;
+       bus->adap.dev.parent = &pdev->dev;
+       bus->adap.dev.of_node = pdev->dev.of_node;
+-      strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
++      strscpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
+       i2c_set_adapdata(&bus->adap, bus);
+       bus->dev = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-au1550.c
++++ b/drivers/i2c/busses/i2c-au1550.c
+@@ -321,7 +321,7 @@ i2c_au1550_probe(struct platform_device
+       priv->adap.algo = &au1550_algo;
+       priv->adap.algo_data = priv;
+       priv->adap.dev.parent = &pdev->dev;
+-      strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
++      strscpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
+       /* Now, set up the PSC for SMBus PIO mode. */
+       i2c_au1550_setup(priv);
+--- a/drivers/i2c/busses/i2c-axxia.c
++++ b/drivers/i2c/busses/i2c-axxia.c
+@@ -783,7 +783,7 @@ static int axxia_i2c_probe(struct platfo
+       }
+       i2c_set_adapdata(&idev->adapter, idev);
+-      strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
++      strscpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
+       idev->adapter.owner = THIS_MODULE;
+       idev->adapter.algo = &axxia_i2c_algo;
+       idev->adapter.bus_recovery_info = &axxia_i2c_recovery_info;
+--- a/drivers/i2c/busses/i2c-bcm-kona.c
++++ b/drivers/i2c/busses/i2c-bcm-kona.c
+@@ -849,7 +849,7 @@ static int bcm_kona_i2c_probe(struct pla
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+-      strlcpy(adap->name, "Broadcom I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "Broadcom I2C adapter", sizeof(adap->name));
+       adap->algo = &bcm_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->dev.of_node = pdev->dev.of_node;
+--- a/drivers/i2c/busses/i2c-cbus-gpio.c
++++ b/drivers/i2c/busses/i2c-cbus-gpio.c
+@@ -245,7 +245,7 @@ static int cbus_i2c_probe(struct platfor
+       adapter->nr             = pdev->id;
+       adapter->timeout        = HZ;
+       adapter->algo           = &cbus_i2c_algo;
+-      strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name));
++      strscpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name));
+       spin_lock_init(&chost->lock);
+       chost->dev = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-cht-wc.c
++++ b/drivers/i2c/busses/i2c-cht-wc.c
+@@ -334,7 +334,7 @@ static int cht_wc_i2c_adap_i2c_probe(str
+       adap->adapter.class = I2C_CLASS_HWMON;
+       adap->adapter.algo = &cht_wc_i2c_adap_algo;
+       adap->adapter.lock_ops = &cht_wc_i2c_adap_lock_ops;
+-      strlcpy(adap->adapter.name, "PMIC I2C Adapter",
++      strscpy(adap->adapter.name, "PMIC I2C Adapter",
+               sizeof(adap->adapter.name));
+       adap->adapter.dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
++++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+@@ -267,7 +267,7 @@ static int ec_i2c_probe(struct platform_
+       bus->dev = dev;
+       bus->adap.owner = THIS_MODULE;
+-      strlcpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name));
++      strscpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name));
+       bus->adap.algo = &ec_i2c_algorithm;
+       bus->adap.algo_data = bus;
+       bus->adap.dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-davinci.c
++++ b/drivers/i2c/busses/i2c-davinci.c
+@@ -847,7 +847,7 @@ static int davinci_i2c_probe(struct plat
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_DEPRECATED;
+-      strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
+       adap->algo = &i2c_davinci_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->timeout = DAVINCI_I2C_TIMEOUT;
+--- a/drivers/i2c/busses/i2c-digicolor.c
++++ b/drivers/i2c/busses/i2c-digicolor.c
+@@ -322,7 +322,7 @@ static int dc_i2c_probe(struct platform_
+       if (ret < 0)
+               return ret;
+-      strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter",
++      strscpy(i2c->adap.name, "Conexant Digicolor I2C adapter",
+               sizeof(i2c->adap.name));
+       i2c->adap.owner = THIS_MODULE;
+       i2c->adap.algo = &dc_i2c_algorithm;
+--- a/drivers/i2c/busses/i2c-eg20t.c
++++ b/drivers/i2c/busses/i2c-eg20t.c
+@@ -773,7 +773,7 @@ static int pch_i2c_probe(struct pci_dev
+               pch_adap->owner = THIS_MODULE;
+               pch_adap->class = I2C_CLASS_HWMON;
+-              strlcpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name));
++              strscpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name));
+               pch_adap->algo = &pch_algorithm;
+               pch_adap->algo_data = &adap_info->pch_data[i];
+--- a/drivers/i2c/busses/i2c-emev2.c
++++ b/drivers/i2c/busses/i2c-emev2.c
+@@ -371,7 +371,7 @@ static int em_i2c_probe(struct platform_
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+-      strlcpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name));
++      strscpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name));
+       priv->sclk = devm_clk_get(&pdev->dev, "sclk");
+       if (IS_ERR(priv->sclk))
+--- a/drivers/i2c/busses/i2c-exynos5.c
++++ b/drivers/i2c/busses/i2c-exynos5.c
+@@ -751,7 +751,7 @@ static int exynos5_i2c_probe(struct plat
+       if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock))
+               i2c->op_clock = I2C_MAX_STANDARD_MODE_FREQ;
+-      strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
+       i2c->adap.owner   = THIS_MODULE;
+       i2c->adap.algo    = &exynos5_i2c_algorithm;
+       i2c->adap.retries = 3;
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -436,7 +436,7 @@ static int i2c_gpio_probe(struct platfor
+       adap->owner = THIS_MODULE;
+       if (np)
+-              strlcpy(adap->name, dev_name(dev), sizeof(adap->name));
++              strscpy(adap->name, dev_name(dev), sizeof(adap->name));
+       else
+               snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+--- a/drivers/i2c/busses/i2c-highlander.c
++++ b/drivers/i2c/busses/i2c-highlander.c
+@@ -402,7 +402,7 @@ static int highlander_i2c_probe(struct p
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+-      strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name));
+       adap->algo = &highlander_i2c_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->nr = pdev->id;
+--- a/drivers/i2c/busses/i2c-hix5hd2.c
++++ b/drivers/i2c/busses/i2c-hix5hd2.c
+@@ -423,7 +423,7 @@ static int hix5hd2_i2c_probe(struct plat
+       }
+       clk_prepare_enable(priv->clk);
+-      strlcpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name));
++      strscpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name));
+       priv->dev = &pdev->dev;
+       priv->adap.owner = THIS_MODULE;
+       priv->adap.algo = &hix5hd2_i2c_algorithm;
+--- a/drivers/i2c/busses/i2c-i801.c
++++ b/drivers/i2c/busses/i2c-i801.c
+@@ -1111,7 +1111,7 @@ static void dmi_check_onboard_device(u8
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               info.addr = dmi_devices[i].i2c_addr;
+-              strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
++              strscpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
+               i2c_new_client_device(adap, &info);
+               break;
+       }
+@@ -1267,7 +1267,7 @@ static void register_dell_lis3lv02d_i2c_
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       info.addr = dell_lis3lv02d_devices[i].i2c_addr;
+-      strlcpy(info.type, "lis3lv02d", I2C_NAME_SIZE);
++      strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE);
+       i2c_new_client_device(&priv->adapter, &info);
+ }
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -738,7 +738,7 @@ static int iic_probe(struct platform_dev
+       adap = &dev->adap;
+       adap->dev.parent = &ofdev->dev;
+       adap->dev.of_node = of_node_get(np);
+-      strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
++      strscpy(adap->name, "IBM IIC", sizeof(adap->name));
+       i2c_set_adapdata(adap, dev);
+       adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+       adap->algo = &iic_algo;
+--- a/drivers/i2c/busses/i2c-icy.c
++++ b/drivers/i2c/busses/i2c-icy.c
+@@ -141,7 +141,7 @@ static int icy_probe(struct zorro_dev *z
+       i2c->adapter.owner = THIS_MODULE;
+       /* i2c->adapter.algo assigned by i2c_pcf_add_bus() */
+       i2c->adapter.algo_data = algo_data;
+-      strlcpy(i2c->adapter.name, "ICY I2C Zorro adapter",
++      strscpy(i2c->adapter.name, "ICY I2C Zorro adapter",
+               sizeof(i2c->adapter.name));
+       if (!devm_request_mem_region(&z->dev,
+--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
++++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
+@@ -564,7 +564,7 @@ static int lpi2c_imx_probe(struct platfo
+       lpi2c_imx->adapter.algo         = &lpi2c_imx_algo;
+       lpi2c_imx->adapter.dev.parent   = &pdev->dev;
+       lpi2c_imx->adapter.dev.of_node  = pdev->dev.of_node;
+-      strlcpy(lpi2c_imx->adapter.name, pdev->name,
++      strscpy(lpi2c_imx->adapter.name, pdev->name,
+               sizeof(lpi2c_imx->adapter.name));
+       lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
+--- a/drivers/i2c/busses/i2c-lpc2k.c
++++ b/drivers/i2c/busses/i2c-lpc2k.c
+@@ -417,7 +417,7 @@ static int i2c_lpc2k_probe(struct platfo
+       i2c_set_adapdata(&i2c->adap, i2c);
+       i2c->adap.owner = THIS_MODULE;
+-      strlcpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name));
+       i2c->adap.algo = &i2c_lpc2k_algorithm;
+       i2c->adap.dev.parent = &pdev->dev;
+       i2c->adap.dev.of_node = pdev->dev.of_node;
+--- a/drivers/i2c/busses/i2c-meson.c
++++ b/drivers/i2c/busses/i2c-meson.c
+@@ -451,7 +451,7 @@ static int meson_i2c_probe(struct platfo
+               return ret;
+       }
+-      strlcpy(i2c->adap.name, "Meson I2C adapter",
++      strscpy(i2c->adap.name, "Meson I2C adapter",
+               sizeof(i2c->adap.name));
+       i2c->adap.owner = THIS_MODULE;
+       i2c->adap.algo = &meson_i2c_algorithm;
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -1432,7 +1432,7 @@ static int mtk_i2c_probe(struct platform
+               speed_clk = I2C_MT65XX_CLK_MAIN;
+       }
+-      strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+       ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk));
+       if (ret) {
+--- a/drivers/i2c/busses/i2c-mt7621.c
++++ b/drivers/i2c/busses/i2c-mt7621.c
+@@ -315,7 +315,7 @@ static int mtk_i2c_probe(struct platform
+       adap->dev.parent = &pdev->dev;
+       i2c_set_adapdata(adap, i2c);
+       adap->dev.of_node = pdev->dev.of_node;
+-      strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
++      strscpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
+       platform_set_drvdata(pdev, i2c);
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -989,7 +989,7 @@ mv64xxx_i2c_probe(struct platform_device
+       if (IS_ERR(drv_data->reg_base))
+               return PTR_ERR(drv_data->reg_base);
+-      strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
++      strscpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+               sizeof(drv_data->adapter.name));
+       init_waitqueue_head(&drv_data->waitq);
+--- a/drivers/i2c/busses/i2c-mxs.c
++++ b/drivers/i2c/busses/i2c-mxs.c
+@@ -838,7 +838,7 @@ static int mxs_i2c_probe(struct platform
+               return err;
+       adap = &i2c->adapter;
+-      strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
+       adap->owner = THIS_MODULE;
+       adap->algo = &mxs_i2c_algo;
+       adap->quirks = &mxs_i2c_quirks;
+--- a/drivers/i2c/busses/i2c-nvidia-gpu.c
++++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
+@@ -319,7 +319,7 @@ static int gpu_i2c_probe(struct pci_dev
+       i2c_set_adapdata(&i2cd->adapter, i2cd);
+       i2cd->adapter.owner = THIS_MODULE;
+-      strlcpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter",
++      strscpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter",
+               sizeof(i2cd->adapter.name));
+       i2cd->adapter.algo = &gpu_i2c_algorithm;
+       i2cd->adapter.quirks = &gpu_i2c_quirks;
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -1488,7 +1488,7 @@ omap_i2c_probe(struct platform_device *p
+       i2c_set_adapdata(adap, omap);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_DEPRECATED;
+-      strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       adap->algo = &omap_i2c_algo;
+       adap->quirks = &omap_i2c_quirks;
+       adap->dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-opal.c
++++ b/drivers/i2c/busses/i2c-opal.c
+@@ -220,9 +220,9 @@ static int i2c_opal_probe(struct platfor
+       adapter->dev.of_node = of_node_get(pdev->dev.of_node);
+       pname = of_get_property(pdev->dev.of_node, "ibm,port-name", NULL);
+       if (pname)
+-              strlcpy(adapter->name, pname, sizeof(adapter->name));
++              strscpy(adapter->name, pname, sizeof(adapter->name));
+       else
+-              strlcpy(adapter->name, "opal", sizeof(adapter->name));
++              strscpy(adapter->name, "opal", sizeof(adapter->name));
+       platform_set_drvdata(pdev, adapter);
+       rc = i2c_add_adapter(adapter);
+--- a/drivers/i2c/busses/i2c-parport.c
++++ b/drivers/i2c/busses/i2c-parport.c
+@@ -308,7 +308,7 @@ static void i2c_parport_attach(struct pa
+       /* Fill the rest of the structure */
+       adapter->adapter.owner = THIS_MODULE;
+       adapter->adapter.class = I2C_CLASS_HWMON;
+-      strlcpy(adapter->adapter.name, "Parallel port adapter",
++      strscpy(adapter->adapter.name, "Parallel port adapter",
+               sizeof(adapter->adapter.name));
+       adapter->algo_data = parport_algo_data;
+       /* Slow down if we can't sense SCL */
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -1403,7 +1403,7 @@ static int i2c_pxa_probe(struct platform
+       spin_lock_init(&i2c->lock);
+       init_waitqueue_head(&i2c->wait);
+-      strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
+       i2c->clk = devm_clk_get(&dev->dev, NULL);
+       if (IS_ERR(i2c->clk)) {
+--- a/drivers/i2c/busses/i2c-qcom-geni.c
++++ b/drivers/i2c/busses/i2c-qcom-geni.c
+@@ -577,7 +577,7 @@ static int geni_i2c_probe(struct platfor
+       i2c_set_adapdata(&gi2c->adap, gi2c);
+       gi2c->adap.dev.parent = dev;
+       gi2c->adap.dev.of_node = dev->of_node;
+-      strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
++      strscpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
+       ret = geni_icc_get(&gi2c->se, "qup-memory");
+       if (ret)
+--- a/drivers/i2c/busses/i2c-qup.c
++++ b/drivers/i2c/busses/i2c-qup.c
+@@ -1878,7 +1878,7 @@ nodma:
+       qup->adap.dev.of_node = pdev->dev.of_node;
+       qup->is_last = true;
+-      strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name));
++      strscpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name));
+       pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC);
+       pm_runtime_use_autosuspend(qup->dev);
+--- a/drivers/i2c/busses/i2c-rcar.c
++++ b/drivers/i2c/busses/i2c-rcar.c
+@@ -1059,7 +1059,7 @@ static int rcar_i2c_probe(struct platfor
+       adap->bus_recovery_info = &rcar_i2c_bri;
+       adap->quirks = &rcar_i2c_quirks;
+       i2c_set_adapdata(adap, priv);
+-      strlcpy(adap->name, pdev->name, sizeof(adap->name));
++      strscpy(adap->name, pdev->name, sizeof(adap->name));
+       /* Init DMA */
+       sg_init_table(&priv->sg, 1);
+--- a/drivers/i2c/busses/i2c-riic.c
++++ b/drivers/i2c/busses/i2c-riic.c
+@@ -447,7 +447,7 @@ static int riic_i2c_probe(struct platfor
+       adap = &riic->adapter;
+       i2c_set_adapdata(adap, riic);
+-      strlcpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name));
++      strscpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name));
+       adap->owner = THIS_MODULE;
+       adap->algo = &riic_algo;
+       adap->dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-rk3x.c
++++ b/drivers/i2c/busses/i2c-rk3x.c
+@@ -1240,7 +1240,7 @@ static int rk3x_i2c_probe(struct platfor
+       /* use common interface to get I2C timing properties */
+       i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
+-      strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
+       i2c->adap.owner = THIS_MODULE;
+       i2c->adap.algo = &rk3x_i2c_algorithm;
+       i2c->adap.retries = 3;
+--- a/drivers/i2c/busses/i2c-s3c2410.c
++++ b/drivers/i2c/busses/i2c-s3c2410.c
+@@ -1076,7 +1076,7 @@ static int s3c24xx_i2c_probe(struct plat
+       else
+               s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
+-      strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
+       i2c->adap.owner = THIS_MODULE;
+       i2c->adap.algo = &s3c24xx_i2c_algorithm;
+       i2c->adap.retries = 2;
+--- a/drivers/i2c/busses/i2c-sh_mobile.c
++++ b/drivers/i2c/busses/i2c-sh_mobile.c
+@@ -930,7 +930,7 @@ static int sh_mobile_i2c_probe(struct pl
+       adap->nr = dev->id;
+       adap->dev.of_node = dev->dev.of_node;
+-      strlcpy(adap->name, dev->name, sizeof(adap->name));
++      strscpy(adap->name, dev->name, sizeof(adap->name));
+       spin_lock_init(&pd->lock);
+       init_waitqueue_head(&pd->wait);
+--- a/drivers/i2c/busses/i2c-simtec.c
++++ b/drivers/i2c/busses/i2c-simtec.c
+@@ -99,7 +99,7 @@ static int simtec_i2c_probe(struct platf
+       pd->adap.algo_data = &pd->bit;
+       pd->adap.dev.parent = &dev->dev;
+-      strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
++      strscpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
+       pd->bit.data = pd;
+       pd->bit.setsda = simtec_i2c_setsda;
+--- a/drivers/i2c/busses/i2c-taos-evm.c
++++ b/drivers/i2c/busses/i2c-taos-evm.c
+@@ -239,7 +239,7 @@ static int taos_connect(struct serio *se
+               dev_err(&serio->dev, "TAOS EVM identification failed\n");
+               goto exit_close;
+       }
+-      strlcpy(adapter->name, name, sizeof(adapter->name));
++      strscpy(adapter->name, name, sizeof(adapter->name));
+       /* Turn echo off for better performance */
+       taos->state = TAOS_STATE_EOFF;
+--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
++++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
+@@ -305,7 +305,7 @@ static int tegra_bpmp_i2c_probe(struct p
+       i2c_set_adapdata(&i2c->adapter, i2c);
+       i2c->adapter.owner = THIS_MODULE;
+-      strlcpy(i2c->adapter.name, "Tegra BPMP I2C adapter",
++      strscpy(i2c->adapter.name, "Tegra BPMP I2C adapter",
+               sizeof(i2c->adapter.name));
+       i2c->adapter.algo = &tegra_bpmp_i2c_algo;
+       i2c->adapter.dev.parent = &pdev->dev;
+--- a/drivers/i2c/busses/i2c-tegra.c
++++ b/drivers/i2c/busses/i2c-tegra.c
+@@ -1799,7 +1799,7 @@ static int tegra_i2c_probe(struct platfo
+       if (i2c_dev->hw->supports_bus_clear)
+               i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
+-      strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev),
++      strscpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev),
+               sizeof(i2c_dev->adapter.name));
+       err = i2c_add_numbered_adapter(&i2c_dev->adapter);
+--- a/drivers/i2c/busses/i2c-uniphier-f.c
++++ b/drivers/i2c/busses/i2c-uniphier-f.c
+@@ -564,7 +564,7 @@ static int uniphier_fi2c_probe(struct pl
+       priv->adap.algo = &uniphier_fi2c_algo;
+       priv->adap.dev.parent = dev;
+       priv->adap.dev.of_node = dev->of_node;
+-      strlcpy(priv->adap.name, "UniPhier FI2C", sizeof(priv->adap.name));
++      strscpy(priv->adap.name, "UniPhier FI2C", sizeof(priv->adap.name));
+       priv->adap.bus_recovery_info = &uniphier_fi2c_bus_recovery_info;
+       i2c_set_adapdata(&priv->adap, priv);
+       platform_set_drvdata(pdev, priv);
+--- a/drivers/i2c/busses/i2c-uniphier.c
++++ b/drivers/i2c/busses/i2c-uniphier.c
+@@ -358,7 +358,7 @@ static int uniphier_i2c_probe(struct pla
+       priv->adap.algo = &uniphier_i2c_algo;
+       priv->adap.dev.parent = dev;
+       priv->adap.dev.of_node = dev->of_node;
+-      strlcpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name));
++      strscpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name));
+       priv->adap.bus_recovery_info = &uniphier_i2c_bus_recovery_info;
+       i2c_set_adapdata(&priv->adap, priv);
+       platform_set_drvdata(pdev, priv);
+--- a/drivers/i2c/busses/i2c-versatile.c
++++ b/drivers/i2c/busses/i2c-versatile.c
+@@ -79,7 +79,7 @@ static int i2c_versatile_probe(struct pl
+       writel(SCL | SDA, i2c->base + I2C_CONTROLS);
+       i2c->adap.owner = THIS_MODULE;
+-      strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
++      strscpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
+       i2c->adap.algo_data = &i2c->algo;
+       i2c->adap.dev.parent = &dev->dev;
+       i2c->adap.dev.of_node = dev->dev.of_node;
+--- a/drivers/i2c/busses/i2c-wmt.c
++++ b/drivers/i2c/busses/i2c-wmt.c
+@@ -413,7 +413,7 @@ static int wmt_i2c_probe(struct platform
+       adap = &i2c_dev->adapter;
+       i2c_set_adapdata(adap, i2c_dev);
+-      strlcpy(adap->name, "WMT I2C adapter", sizeof(adap->name));
++      strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name));
+       adap->owner = THIS_MODULE;
+       adap->algo = &wmt_i2c_algo;
+       adap->dev.parent = &pdev->dev;
diff --git a/target/linux/mediatek/patches-5.15/840-12-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-5.15/840-12-v6.2-i2c-mediatek-add-mt7986-support.patch
new file mode 100644 (file)
index 0000000..4c398c5
--- /dev/null
@@ -0,0 +1,44 @@
+From 11f9a0f4e51887ad7b4a2898a368fcd0c2984e89 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Sun, 9 Oct 2022 12:16:31 +0200
+Subject: [PATCH 12/16] i2c: mediatek: add mt7986 support
+
+Add i2c support for MT7986 SoC.
+
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible m
+       .max_dma_support = 33,
+ };
++static const struct mtk_i2c_compatible mt7986_compat = {
++      .quirks = &mt7622_i2c_quirks,
++      .regs = mt_i2c_regs_v1,
++      .pmic_i2c = 0,
++      .dcm = 1,
++      .auto_restart = 1,
++      .aux_len_reg = 1,
++      .timing_adjust = 0,
++      .dma_sync = 1,
++      .ltiming_adjust = 0,
++      .max_dma_support = 32,
++};
++
+ static const struct mtk_i2c_compatible mt8173_compat = {
+       .regs = mt_i2c_regs_v1,
+       .pmic_i2c = 0,
+@@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c
+       { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
+       { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
+       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
++      { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
+       { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat },
+       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+       { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
diff --git a/target/linux/mediatek/patches-5.15/840-13-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-5.15/840-13-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch
new file mode 100644 (file)
index 0000000..18c66cd
--- /dev/null
@@ -0,0 +1,42 @@
+From 98204ccafd45a8a6109ff2d60e2c179b95d92578 Mon Sep 17 00:00:00 2001
+From: ye xingchen <ye.xingchen@zte.com.cn>
+Date: Thu, 19 Jan 2023 17:19:58 +0800
+Subject: [PATCH 13/16] i2c: mt65xx: Use
+ devm_platform_get_and_ioremap_resource()
+
+Convert platform_get_resource(), devm_ioremap_resource() to a single
+call to devm_platform_get_and_ioremap_resource(), as this is exactly
+what this function does.
+
+Signed-off-by: ye xingchen <ye.xingchen@zte.com.cn>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform
+ {
+       int ret = 0;
+       struct mtk_i2c *i2c;
+-      struct resource *res;
+       int i, irq, speed_clk;
+       i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      i2c->base = devm_ioremap_resource(&pdev->dev, res);
++      i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+       if (IS_ERR(i2c->base))
+               return PTR_ERR(i2c->base);
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-      i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
++      i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
+       if (IS_ERR(i2c->pdmabase))
+               return PTR_ERR(i2c->pdmabase);
diff --git a/target/linux/mediatek/patches-5.15/840-14-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-5.15/840-14-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch
new file mode 100644 (file)
index 0000000..d000d53
--- /dev/null
@@ -0,0 +1,33 @@
+From 8106fa2e0ae6082833fe1df97829c46c0183eaea Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Sat, 11 Mar 2023 12:16:54 +0100
+Subject: [PATCH 14/16] i2c: mt65xx: drop of_match_ptr for ID table
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The driver can match only via the DT table so the table should be always
+used and the of_match_ptr does not have any sense (this also allows ACPI
+matching via PRP0001, even though it might not be relevant here).
+
+  drivers/i2c/busses/i2c-mt65xx.c:514:34: error: ‘mtk_i2c_of_match’ defined but not used [-Werror=unused-const-variable=]
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Guenter Roeck <groeck@chromium.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -1546,7 +1546,7 @@ static struct platform_driver mtk_i2c_dr
+       .driver = {
+               .name = I2C_DRV_NAME,
+               .pm = &mtk_i2c_pm,
+-              .of_match_table = of_match_ptr(mtk_i2c_of_match),
++              .of_match_table = mtk_i2c_of_match,
+       },
+ };
diff --git a/target/linux/mediatek/patches-5.15/840-15-next-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-5.15/840-15-next-i2c-mediatek-add-support-for-MT7981-SoC.patch
new file mode 100644 (file)
index 0000000..e097374
--- /dev/null
@@ -0,0 +1,47 @@
+From f69f3d662ba3bf999c36d9ac1e684540c4487bc3 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Mon, 10 Apr 2023 17:19:38 +0100
+Subject: [PATCH 15/16] i2c: mediatek: add support for MT7981 SoC
+
+Add support for the I2C units found in the MediaTek MT7981 and MT7988
+SoCs. Just like other recent MediaTek I2C units that also uses v3
+register offsets (which differ from v2 only by OFFSET_SLAVE_ADDR being
+0x94 instead of 0x4).
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible m
+       .max_dma_support = 33,
+ };
++static const struct mtk_i2c_compatible mt7981_compat = {
++      .regs = mt_i2c_regs_v3,
++      .pmic_i2c = 0,
++      .dcm = 0,
++      .auto_restart = 1,
++      .aux_len_reg = 1,
++      .timing_adjust = 1,
++      .dma_sync = 1,
++      .ltiming_adjust = 1,
++      .max_dma_support = 33
++};
++
+ static const struct mtk_i2c_compatible mt7986_compat = {
+       .quirks = &mt7622_i2c_quirks,
+       .regs = mt_i2c_regs_v1,
+@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c
+       { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
+       { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
+       { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
++      { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat },
+       { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
+       { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat },
+       { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
diff --git a/target/linux/mediatek/patches-5.15/840-16-pending-i2c-mt65xx-add-additional-clocks.patch b/target/linux/mediatek/patches-5.15/840-16-pending-i2c-mt65xx-add-additional-clocks.patch
new file mode 100644 (file)
index 0000000..de95657
--- /dev/null
@@ -0,0 +1,46 @@
+From 0d98d8e0053d00273e612aa323387241b1b1e628 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Fri, 26 May 2023 10:29:45 +0100
+Subject: [PATCH 16/16] i2c: mt65xx: add additional clocks
+
+On MT7981 additional clocks are required when accessing I2C registers.
+Add MCK and PCK optional clocks to i2c-mt65xx driver so we don't have
+to always have them enabled, but really only if I2C is used.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -100,11 +100,13 @@ enum i2c_mt65xx_clks {
+       I2C_MT65XX_CLK_DMA,
+       I2C_MT65XX_CLK_PMIC,
+       I2C_MT65XX_CLK_ARB,
++      I2C_MT65XX_CLK_MCK,
++      I2C_MT65XX_CLK_PCK,
+       I2C_MT65XX_CLK_MAX
+ };
+ static const char * const i2c_mt65xx_clk_ids[I2C_MT65XX_CLK_MAX] = {
+-      "main", "dma", "pmic", "arb"
++      "main", "dma", "pmic", "arb", "mck", "pck"
+ };
+ enum DMA_REGS_OFFSET {
+@@ -1444,6 +1446,14 @@ static int mtk_i2c_probe(struct platform
+       if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk))
+               return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk);
++      i2c->clocks[I2C_MT65XX_CLK_MCK].clk = devm_clk_get_optional(&pdev->dev, "mck");
++      if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_MCK].clk))
++              return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_MCK].clk);
++
++      i2c->clocks[I2C_MT65XX_CLK_PCK].clk = devm_clk_get_optional(&pdev->dev, "pck");
++      if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PCK].clk))
++              return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PCK].clk);
++
+       if (i2c->have_pmic) {
+               i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic");
+               if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {