From 17c5d247e3e4708cac05ff087c8013c0dda383a2 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 16 May 2026 02:41:19 +0300 Subject: [PATCH 01/14] i2c: qcom-cci: Do not check return value of cci_init() The cci_init() function is not supposed to fail, and it never returns a non-zero, so it'd make sense to convert its signature to void. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Loic Poulain Reviewed-by: Konrad Dybcio Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260515234121.1607425-3-vladimir.zapolskiy@linaro.org --- drivers/i2c/busses/i2c-qcom-cci.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 01e440b6585d..be41a53e30c6 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -243,7 +243,7 @@ static int cci_reset(struct cci *cci) return 0; } -static int cci_init(struct cci *cci) +static void cci_init(struct cci *cci) { u32 val = CCI_IRQ_MASK_0_I2C_M0_RD_DONE | CCI_IRQ_MASK_0_I2C_M0_Q0_REPORT | @@ -284,8 +284,6 @@ static int cci_init(struct cci *cci) val = hw->scl_stretch_en << 8 | hw->trdhld << 4 | hw->tsp; writel(val, cci->base + CCI_I2C_Mm_MISC_CTL(i)); } - - return 0; } static int cci_run_queue(struct cci *cci, u8 master, u8 queue) @@ -611,9 +609,7 @@ static int cci_probe(struct platform_device *pdev) if (ret < 0) goto error; - ret = cci_init(cci); - if (ret < 0) - goto error; + cci_init(cci); pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(dev); From 697d58d457e999a03c7c395ff0fbf13e765f0997 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 16 May 2026 02:41:20 +0300 Subject: [PATCH 02/14] i2c: qcom-cci: Move cci_init() under cci_reset() function On probe or runtime errors cci_reset() is called and it should be coupled with cci_init(), instead of doing this on caller's side, embed cci_init() directly into the cci_reset() function. This is a non-functional change, cci_reset() and cci_init() function bodies are reordered. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Loic Poulain Reviewed-by: Konrad Dybcio Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260515234121.1607425-4-vladimir.zapolskiy@linaro.org --- drivers/i2c/busses/i2c-qcom-cci.c | 41 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index be41a53e30c6..2d73903f14d3 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -225,24 +225,6 @@ static int cci_halt(struct cci *cci, u8 master_num) return 0; } -static int cci_reset(struct cci *cci) -{ - /* - * we reset the whole controller, here and for implicity use - * master[0].xxx for waiting on it. - */ - reinit_completion(&cci->master[0].irq_complete); - writel(CCI_RESET_CMD_MASK, cci->base + CCI_RESET_CMD); - - if (!wait_for_completion_timeout(&cci->master[0].irq_complete, - CCI_TIMEOUT)) { - dev_err(cci->dev, "CCI reset timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - static void cci_init(struct cci *cci) { u32 val = CCI_IRQ_MASK_0_I2C_M0_RD_DONE | @@ -286,6 +268,26 @@ static void cci_init(struct cci *cci) } } +static int cci_reset(struct cci *cci) +{ + /* + * we reset the whole controller, here and for implicity use + * master[0].xxx for waiting on it. + */ + reinit_completion(&cci->master[0].irq_complete); + writel(CCI_RESET_CMD_MASK, cci->base + CCI_RESET_CMD); + + if (!wait_for_completion_timeout(&cci->master[0].irq_complete, + CCI_TIMEOUT)) { + dev_err(cci->dev, "CCI reset timeout\n"); + return -ETIMEDOUT; + } + + cci_init(cci); + + return 0; +} + static int cci_run_queue(struct cci *cci, u8 master, u8 queue) { u32 val; @@ -302,7 +304,6 @@ static int cci_run_queue(struct cci *cci, u8 master, u8 queue) dev_err(cci->dev, "master %d queue %d timeout\n", master, queue); cci_reset(cci); - cci_init(cci); return -ETIMEDOUT; } @@ -609,8 +610,6 @@ static int cci_probe(struct platform_device *pdev) if (ret < 0) goto error; - cci_init(cci); - pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(dev); pm_runtime_set_active(dev); From f0285c286bca5a1e018ba25040cef6c7806c31ef Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 16 May 2026 02:41:21 +0300 Subject: [PATCH 03/14] i2c: qcom-cci: Remove overcautious disable_irq() calls In cci_probe() the controller's interrupt is requested using a devres managed API, and in cci_probe() error path and cci_remove() it'd be safe to rely on devres mechanism to free and shutdown the interrupt, thus explicit disable_irq() calls can be removed as unnecessary ones. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Loic Poulain Reviewed-by: Konrad Dybcio Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260515234121.1607425-5-vladimir.zapolskiy@linaro.org --- drivers/i2c/busses/i2c-qcom-cci.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 2d73903f14d3..4d64895a9e9e 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -608,7 +608,7 @@ static int cci_probe(struct platform_device *pdev) ret = cci_reset(cci); if (ret < 0) - goto error; + goto disable_clocks; pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(dev); @@ -638,8 +638,6 @@ static int cci_probe(struct platform_device *pdev) of_node_put(cci->master[i].adap.dev.of_node); } } -error: - disable_irq(cci->irq); disable_clocks: cci_disable_clocks(cci); @@ -659,7 +657,6 @@ static void cci_remove(struct platform_device *pdev) } } - disable_irq(cci->irq); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); } From e43f32816a1b1fe5a86279411626fe3a9be56d45 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 10 Jun 2026 11:05:13 +0800 Subject: [PATCH 04/14] i2c: davinci: Unregister cpufreq notifier on probe failure davinci_i2c_probe() registers a cpufreq transition notifier before adding the I2C adapter. If i2c_add_numbered_adapter() fails, the probe error path releases the device resources without unregistering the notifier. Add a dedicated error path to unregister the cpufreq notifier after i2c_add_numbered_adapter() fails. Fixes: 82c0de11b734 ("i2c: davinci: Add cpufreq support") Signed-off-by: Haoxiang Li Cc: # v2.6.36+ Reviewed-by: Bartosz Golaszewski Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260610030513.2651018-1-haoxiang_li2024@163.com --- drivers/i2c/busses/i2c-davinci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 66c23535656b..0617f416cb0b 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -818,12 +818,14 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); if (r) - goto err_unuse_clocks; + goto err_cpufreq; pm_runtime_put_autosuspend(dev->dev); return 0; +err_cpufreq: + i2c_davinci_cpufreq_deregister(dev); err_unuse_clocks: pm_runtime_dont_use_autosuspend(dev->dev); pm_runtime_put_sync(dev->dev); From 5da26ab52ac5502b09b7c20970ee08291130673f Mon Sep 17 00:00:00 2001 From: Abdurrahman Hussain Date: Mon, 8 Jun 2026 12:17:39 -0700 Subject: [PATCH 05/14] dt-bindings: i2c: convert i2c-mux-reg to DT schema Convert Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt to the YAML schema so the i2c-mux-reg binding is validated by dt_binding_check. Faithful port of the existing properties; no semantic change. Signed-off-by: Abdurrahman Hussain Acked-by: Conor Dooley Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260608-i2c-mux-reg-base-bus-num-v2-1-776e313f213a@nexthop.ai --- .../devicetree/bindings/i2c/i2c-mux-reg.txt | 74 --------------- .../devicetree/bindings/i2c/i2c-mux-reg.yaml | 92 +++++++++++++++++++ 2 files changed, 92 insertions(+), 74 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-reg.yaml diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt deleted file mode 100644 index b9d9755e4172..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt +++ /dev/null @@ -1,74 +0,0 @@ -Register-based I2C Bus Mux - -This binding describes an I2C bus multiplexer that uses a single register -to route the I2C signals. - -Required properties: -- compatible: i2c-mux-reg -- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side - port is connected to. -* Standard I2C mux properties. See i2c-mux.yaml in this directory. -* I2C child bus nodes. See i2c-mux.yaml in this directory. - -Optional properties: -- reg: this pair of specifies the register to control the mux. - The depends on its parent node. It can be any memory-mapped - address. The size must be either 1, 2, or 4 bytes. If reg is omitted, the - resource of this device will be used. -- little-endian: The existence indicates the register is in little endian. -- big-endian: The existence indicates the register is in big endian. - If both little-endian and big-endian are omitted, the endianness of the - CPU will be used. -- write-only: The existence indicates the register is write-only. -- idle-state: value to set the muxer to when idle. When no value is - given, it defaults to the last value used. - -Whenever an access is made to a device on a child bus, the value set -in the relevant node's reg property will be output to the register. - -If an idle state is defined, using the idle-state (optional) property, -whenever an access is not being made to a device on a child bus, the -register will be set according to the idle value. - -If an idle state is not defined, the most recently used value will be -left programmed into the register. - -Example of a mux on PCIe card, the host is a powerpc SoC (big endian): - - i2c-mux { - /* the depends on the address translation - * of the parent device. If omitted, device resource - * will be used instead. The size is to determine - * whether iowrite32, iowrite16, or iowrite8 will be used. - */ - reg = <0x6028 0x4>; - little-endian; /* little endian register on PCIe */ - compatible = "i2c-mux-reg"; - #address-cells = <1>; - #size-cells = <0>; - i2c-parent = <&i2c1>; - i2c@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - si5338: clock-generator@70 { - compatible = "silabs,si5338"; - reg = <0x70>; - /* other stuff */ - }; - }; - - i2c@1 { - /* data is written using iowrite32 */ - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - - si5338: clock-generator@70 { - compatible = "silabs,si5338"; - reg = <0x70>; - /* other stuff */ - }; - }; - }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-reg.yaml b/Documentation/devicetree/bindings/i2c/i2c-mux-reg.yaml new file mode 100644 index 000000000000..01ade0771c60 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-reg.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/i2c-mux-reg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Register-based I2C Bus Mux + +maintainers: + - Peter Rosin + +description: | + This binding describes an I2C bus multiplexer that uses a single + memory-mapped register to route the I2C signals. + + Whenever an access is made to a device on a child bus, the value + set in the relevant node's reg property is output to the register. + + If an idle state is defined via the idle-state property, the + register is set to that value whenever no access is being made. + Otherwise the most recently used value is left programmed. + +allOf: + - $ref: /schemas/i2c/i2c-mux.yaml# + +properties: + compatible: + const: i2c-mux-reg + + reg: + maxItems: 1 + description: | + Offset and size of the register that selects the active child + bus, relative to the parent node's address space. The size + determines the access width and must be 1, 2, or 4 bytes. If + omitted, the platform device's own memory resource is used + instead. + + i2c-parent: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle of the I2C bus that this multiplexer's master-side port + is connected to. + + little-endian: + type: boolean + description: Register is accessed in little-endian byte order. + + big-endian: + type: boolean + description: Register is accessed in big-endian byte order. + + write-only: + type: boolean + description: + Register is write-only; the driver must not read back the + current selection. + + idle-state: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Value to write to the register when no child bus is selected. + +required: + - compatible + - i2c-parent + +unevaluatedProperties: false + +examples: + - | + i2c-mux@6028 { + compatible = "i2c-mux-reg"; + reg = <0x6028 0x4>; + little-endian; + #address-cells = <1>; + #size-cells = <0>; + i2c-parent = <&i2c1>; + + i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +... From e1e5c40a408b09d6e7bd603c51bb5b34868b54e7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 16 Jun 2026 08:07:59 +0200 Subject: [PATCH 06/14] dt-bindings: i2c: i2c-mux-pinctrl: change maintainer The YAML conversion added me as maintainer but I can't recall being asked nor do I want to maintain it. Thierry has created the YAML file and works for the company which contributed the driver. Signed-off-by: Wolfram Sang Acked-by: Conor Dooley Acked-by: Thierry Reding Acked-by: Krzysztof Kozlowski Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260616060910.1480-2-wsa+renesas@sang-engineering.com --- Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.yaml b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.yaml index 2e3d555eb96c..99812a893476 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Pinctrl-based I2C Bus Mux maintainers: - - Wolfram Sang + - Thierry Reding description: | This binding describes an I2C bus multiplexer that uses pin multiplexing to route the I2C From bb0301f856bfc0ea8192b8d2bd5a79bdc6d3d3f1 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 11 May 2026 12:49:13 +0200 Subject: [PATCH 07/14] i2c: algo: bit: use str_plural helper in bit_xfer Replace the manual ternary "s" pluralizations with str_plural() to simplify the code. Signed-off-by: Thorsten Blum Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260511104911.183606-3-thorsten.blum@linux.dev --- drivers/i2c/algos/i2c-algo-bit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 6544d27e4419..d1d9a6c1a1e2 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -562,7 +563,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, ret = readbytes(i2c_adap, pmsg); if (ret >= 1) bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n", - ret, ret == 1 ? "" : "s"); + ret, str_plural(ret)); if (ret < pmsg->len) { if (ret >= 0) ret = -EIO; @@ -573,7 +574,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, ret = sendbytes(i2c_adap, pmsg); if (ret >= 1) bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n", - ret, ret == 1 ? "" : "s"); + ret, str_plural(ret)); if (ret < pmsg->len) { if (ret >= 0) ret = -EIO; From 1e696bc33c30acda698e5e921adcc7f7e61976f7 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 11 Jun 2026 23:55:02 +0200 Subject: [PATCH 08/14] i2c: atr: annotate i2c_atr_adap_desc->aliases with __counted_by_ptr Add the __counted_by_ptr() compiler attribute to ->aliases to improve bounds checking via CONFIG_UBSAN_BOUNDS and CONFIG_FORTIFY_SOURCE. Signed-off-by: Thorsten Blum Reviewed-by: Luca Ceresoli Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260611215501.464405-3-thorsten.blum@linux.dev --- include/linux/i2c-atr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/i2c-atr.h b/include/linux/i2c-atr.h index 2bb54dc87c8e..b52a7b9ec536 100644 --- a/include/linux/i2c-atr.h +++ b/include/linux/i2c-atr.h @@ -71,7 +71,7 @@ struct i2c_atr_adap_desc { struct device *parent; struct fwnode_handle *bus_handle; size_t num_aliases; - u16 *aliases; + u16 *aliases __counted_by_ptr(num_aliases); }; /** From 6ee2ba9dcefe5bb41d179e183919531c8da01d14 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 6 May 2026 16:40:15 +0100 Subject: [PATCH 09/14] i2c: ls2x-v2: return IRQ_HANDLED after servicing an error The event ISR reads SR1 and, when an error flag (ARLO/AF/BERR) is set, calls loongson2_i2c_isr_error() which clears the offending flag, issues STOP for the AF case, records msg->result, masks every CR2 interrupt enable and completes the waiter. The handler then returns IRQ_NONE, declaring to the IRQ core that the device did not interrupt. That report is wrong. The device did interrupt and the handler fully serviced it. Because the IRQ is requested with IRQF_SHARED, the genirq spurious-IRQ tracker counts each error as unhandled. A bus that emits sporadic NACKs, arbitration losses or bus errors will therefore march toward the spurious-IRQ threshold and the line can end up disabled, wedging the controller. Return IRQ_HANDLED on this path. The other IRQ_NONE site, taken when neither an event nor an error bit is set, remains correct. Fixes: 6d1b0785f6d5 ("i2c: ls2x-v2: Add driver for Loongson-2K0300 I2C controller") Signed-off-by: David Carlier Assisted-by: Codex:GPT-5.5 Reviewed-by: Binbin Zhou Tested-by: Binbin Zhou Reviewed-by: Andy Shevchenko Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260506154015.94815-1-devnexen@gmail.com --- drivers/i2c/busses/i2c-ls2x-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ls2x-v2.c b/drivers/i2c/busses/i2c-ls2x-v2.c index 517760d70169..9df73557ecc4 100644 --- a/drivers/i2c/busses/i2c-ls2x-v2.c +++ b/drivers/i2c/busses/i2c-ls2x-v2.c @@ -304,7 +304,7 @@ static irqreturn_t loongson2_i2c_isr_event(int irq, void *data) regmap_read(priv->regmap, LOONGSON2_I2C_SR1, &status); if (status & LOONGSON2_I2C_SR1_ITERREN_MASK) { loongson2_i2c_isr_error(status, data); - return IRQ_NONE; + return IRQ_HANDLED; } regmap_read(priv->regmap, LOONGSON2_I2C_CR2, &cr2); From 36904931a1c23db42f1d7078713206874cc10d97 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 23 Apr 2026 19:35:50 +0200 Subject: [PATCH 10/14] i2c: qcom: Unify user-visible "Qualcomm" name Various names for Qualcomm as a company are used in user-visible config options: QCOM, Qualcomm and Qualcomm Technologies. Switch to unified "Qualcomm" so it will be easier for users to identify the options when for example running menuconfig. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260423173550.92317-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Andi Shyti --- drivers/i2c/busses/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 3123ab75600b..d35456994280 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1058,7 +1058,7 @@ config I2C_QCOM_CCI will be called i2c-qcom-cci. config I2C_QCOM_GENI - tristate "Qualcomm Technologies Inc.'s GENI based I2C controller" + tristate "Qualcomm GENI based I2C controller" depends on ARCH_QCOM || COMPILE_TEST depends on QCOM_GENI_SE help From 1589352a0c848682d7b3c15f7ca196a5c1841276 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 6 May 2026 16:00:46 +0100 Subject: [PATCH 11/14] dt-bindings: i2c: microchip,corei2c: permit resets Both CoreI2C and the hardened versions of it on mpfs and pic64gx have a reset pin. For the former, usually this is wired to a common fabric reset not managed by software and for the latter two the platform firmware takes them out of reset on first-party boards (or those using modified versions of the vendor firmware), but not all boards may take this approach. Permit providing a reset in devicetree for Linux, or other devicetree-consuming software, to use. Signed-off-by: Conor Dooley Reviewed-by: Krzysztof Kozlowski Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260506-bronchial-kitten-e3697fb66ba7@spud --- Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml b/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml index 6ff58b64d496..bd63c70aac6b 100644 --- a/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml +++ b/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml @@ -37,6 +37,9 @@ properties: modes are supported, possible values are 100000 and 400000. enum: [100000, 400000] + resets: + maxItems: 1 + required: - compatible - reg From 111bb7f9f4a90b32e495d70a607c67b137f3074a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Rodr=C3=ADguez?= Date: Thu, 11 Jun 2026 12:48:56 +0200 Subject: [PATCH 12/14] i2c: stm32f7: truncate clock period instead of rounding it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stm32f7_i2c_compute_timing() derives the I2C clock source period (i2cclk) with DIV_ROUND_CLOSEST, which may round it up. When the period is overestimated, all timings computed from it (SCLDEL, SDADEL, SCLL, SCLH) come out shorter on the wire than calculated, and the resulting bus rate can exceed the requested speed, violating the I2C specification minimums for tLOW and tHIGH. For example, with a 104.45 MHz clock source (e.g. PCLK1, the reset-default I2C clock source on STM32MP1), i2cclk is rounded from 9.574 ns up to 10 ns. Requesting a 400 kHz fast mode bus with 72/27 ns rise/fall times and no analog/digital filters then produces an actual bus rate of 415.6 kHz with tLOW = 1254 ns, violating both the 400 kHz maximum rate and the 1300 ns tLOW minimum of the specification. Truncate the period instead, so that it can only be underestimated. The error then falls on the safe side: the programmed timings come out slightly longer than computed and the bus runs marginally below the target rate (375.3 kHz in the example above) while meeting the specification. i2cbus is left rounded-to-closest: it is only used as the target of the clk_error comparison and is never multiplied into the programmed timings, so nearest rounding remains accurate there. Fixes: aeb068c57214 ("i2c: i2c-stm32f7: add driver") Signed-off-by: Guillermo Rodríguez Cc: # v4.14+ Acked-by: Alain Volmat Reviewed-by: Pierre-Yves MORDRET Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260611104857.242153-1-guille.rodriguez@gmail.com --- drivers/i2c/busses/i2c-stm32f7.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 16c6e61c7e11..d6d993b436cb 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -464,8 +464,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, { struct stm32f7_i2c_spec *specs; u32 p_prev = STM32F7_PRESC_MAX; - u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, - setup->clock_src); + /* + * Truncate instead of rounding to closest: if the clock period is + * overestimated, the computed SCL timings will come out shorter on + * the wire, which can push the bus above the target rate and below + * the spec's tLOW/tHIGH minimums. + */ + u32 i2cclk = NSEC_PER_SEC / setup->clock_src; u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->speed_freq); u32 clk_error_prev = i2cbus; From 218cfe364b55b2768221629bd4a69ad190b7fbbc Mon Sep 17 00:00:00 2001 From: Carlos Song Date: Mon, 25 May 2026 11:14:50 +0800 Subject: [PATCH 13/14] i2c: imx-lpi2c: mark I2C adapter when hardware is powered down On some i.MX platforms, certain I2C client drivers keep a periodic workqueue which continues to trigger I2C transfers. During system suspend/resume, there exists a time window between: - suspend_noirq and the system entering suspend - the system starting to resume and resume_noirq In this window, the I2C controller resources such as clock and pinctrl may already be disabled or not yet restored. If a workqueue triggers an I2C transfer in this period, the driver attempts to access I2C registers while the hardware resources are unavailable, which may lead to system hang. Mark the I2C adapter as suspended during noirq suspend and block new transfers until resume, ensuring that I2C transfers are only issued when hardware resources are available. Fixes: 1ee867e465c1 ("i2c: imx-lpi2c: add target mode support") Signed-off-by: Carlos Song Cc: # v6.14+ Acked-by: Mukesh Savaliya Reviewed-by: Frank Li Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260525031450.3183421-1-carlos.song@oss.nxp.com --- drivers/i2c/busses/i2c-imx-lpi2c.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index cd4da50c4dd9..e6c24a9d934d 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -1646,7 +1646,18 @@ static int __maybe_unused lpi2c_runtime_resume(struct device *dev) static int __maybe_unused lpi2c_suspend_noirq(struct device *dev) { - return pm_runtime_force_suspend(dev); + struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); + int ret; + + i2c_mark_adapter_suspended(&lpi2c_imx->adapter); + + ret = pm_runtime_force_suspend(dev); + if (ret) { + i2c_mark_adapter_resumed(&lpi2c_imx->adapter); + return ret; + } + + return 0; } static int __maybe_unused lpi2c_resume_noirq(struct device *dev) @@ -1666,6 +1677,8 @@ static int __maybe_unused lpi2c_resume_noirq(struct device *dev) if (lpi2c_imx->target) lpi2c_imx_target_init(lpi2c_imx); + i2c_mark_adapter_resumed(&lpi2c_imx->adapter); + return 0; } From ac930b80c1e0eba283d7843180964e6d2a87369d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Wed, 17 Jun 2026 11:37:36 +0200 Subject: [PATCH 14/14] i2c: pxa: Use named initializers for the platform_device_id array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Named initializers are better readable and more robust to changes of the struct definition. This robustness is relevant for a planned change to struct platform_device_id replacing .driver_data by an anonymous union. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/827657abb02edb39bc90f7336194f614d383770e.1781688767.git.u.kleine-koenig@baylibre.com --- drivers/i2c/busses/i2c-pxa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 9a8b154ab69e..c9927a389aaf 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -214,11 +214,11 @@ static const struct of_device_id i2c_pxa_dt_ids[] = { MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); static const struct platform_device_id i2c_pxa_id_table[] = { - { "pxa2xx-i2c", REGS_PXA2XX }, - { "pxa3xx-pwri2c", REGS_PXA3XX }, - { "ce4100-i2c", REGS_CE4100 }, - { "pxa910-i2c", REGS_PXA910 }, - { "armada-3700-i2c", REGS_A3700 }, + { .name = "pxa2xx-i2c", .driver_data = REGS_PXA2XX }, + { .name = "pxa3xx-pwri2c", .driver_data = REGS_PXA3XX }, + { .name = "ce4100-i2c", .driver_data = REGS_CE4100 }, + { .name = "pxa910-i2c", .driver_data = REGS_PXA910 }, + { .name = "armada-3700-i2c", .driver_data = REGS_A3700 }, { } }; MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);