mediatek: cleanly backport and add fix for I2C driver
authorDaniel Golle <daniel@makrotopia.org>
Fri, 26 May 2023 12:49:02 +0000 (13:49 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Sat, 27 May 2023 01:06:57 +0000 (02:06 +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 by making sure all clocks
are enabled before accessing I2C registers.

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-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/848-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/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/851-v6.2-i2c-mediatek-add-mt7986-support.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/855-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-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch b/target/linux/mediatek/patches-5.15/840-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/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch b/target/linux/mediatek/patches-5.15/841-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/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch b/target/linux/mediatek/patches-5.15/842-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/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch b/target/linux/mediatek/patches-5.15/843-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/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch b/target/linux/mediatek/patches-5.15/844-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/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch b/target/linux/mediatek/patches-5.15/845-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/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch b/target/linux/mediatek/patches-5.15/846-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/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch b/target/linux/mediatek/patches-5.15/847-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/848-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch b/target/linux/mediatek/patches-5.15/848-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/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch b/target/linux/mediatek/patches-5.15/849-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/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch b/target/linux/mediatek/patches-5.15/850-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/851-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-5.15/851-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/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-5.15/852-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/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-5.15/853-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/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-5.15/854-v6.4-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/855-pending-i2c-mt65xx-add-additional-clocks.patch b/target/linux/mediatek/patches-5.15/855-pending-i2c-mt65xx-add-additional-clocks.patch
new file mode 100644 (file)
index 0000000..1ed8d1a
--- /dev/null
@@ -0,0 +1,55 @@
+From 94bf61df9201195d6d8ce82e299fb231b31fbaae Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Fri, 26 May 2023 10:29:45 +0100
+Subject: [PATCH] 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 | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -93,6 +93,8 @@
+  * @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_MCK:  MCK clock for i2c
++ * @I2C_MT65XX_CLK_PCK:  PCK clock for i2c
+  * @I2C_MT65XX_CLK_MAX:  Number of supported clocks
+  */
+ enum i2c_mt65xx_clks {
+@@ -100,11 +102,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 +1448,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)) {