* [PATCH v2 1/3] bus: ti-sysc: fix I2C quirk for OMAP3 variants
2026-11-10 20:56 [PATCH v2 0/3] ARM: OMAP2+: Convert OMAP3 I2C to ti-sysc Andreas Kemnade
@ 2026-11-10 20:56 ` Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 2/3] ARM: dts: ti/omap: describe omap3 i2c via ti-sysc Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 3/3] ARM: OMAP2+: remove i2c from OMAP3 hwmods list Andreas Kemnade
2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-11-10 20:56 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andi Shyti,
Thomas Richard, Wolfram Sang, Paul Walmsley, Russell King
Cc: Sicelo, linux-omap, linux-kernel, devicetree, linux-arm-kernel,
Andreas Kemnade
OMAP3 has only one revision register, not split across two registers.
Do not try to interpret the interrupt enable register but instead
use the size of the revision register as indicator.
Specifying a fake 8 byte range and the original quirk only works if
u-boot has not messed around with the interrupt enable register.
Fixes: 4e23be473e306 ("bus: ti-sysc: Add support for module specific reset quirks")
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
drivers/bus/ti-sysc.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 12285ad9ef51f..400259d1fc2da 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -122,6 +122,7 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = {
* @cookie: data used by legacy platform callbacks
* @name: name if available
* @revision: interconnect target module revision
+ * @revision_doubleword: revision is stored across two words
* @sysconfig: saved sysconfig register value
* @reserved: target module is reserved and already in use
* @enabled: sysc runtime enabled status
@@ -153,6 +154,7 @@ struct sysc {
struct ti_sysc_cookie cookie;
const char *name;
u32 revision;
+ bool revision_doubleword;
u32 sysconfig;
unsigned int reserved:1;
unsigned int enabled:1;
@@ -179,7 +181,8 @@ static void sysc_write(struct sysc *ddata, int offset, u32 value)
/* Only i2c revision has LO and HI register with stride of 4 */
if (ddata->offsets[SYSC_REVISION] >= 0 &&
- offset == ddata->offsets[SYSC_REVISION]) {
+ offset == ddata->offsets[SYSC_REVISION] &&
+ ddata->revision_doubleword) {
u16 hi = value >> 16;
writew_relaxed(hi, ddata->module_va + offset + 4);
@@ -200,7 +203,8 @@ static u32 sysc_read(struct sysc *ddata, int offset)
/* Only i2c revision has LO and HI register with stride of 4 */
if (ddata->offsets[SYSC_REVISION] >= 0 &&
- offset == ddata->offsets[SYSC_REVISION]) {
+ offset == ddata->offsets[SYSC_REVISION] &&
+ ddata->revision_doubleword) {
u16 tmp = readw_relaxed(ddata->module_va + offset + 4);
val |= tmp << 16;
@@ -761,8 +765,10 @@ static void sysc_check_children(struct sysc *ddata)
*/
static void sysc_check_quirk_16bit(struct sysc *ddata, struct resource *res)
{
- if (resource_size(res) == 8)
+ if (resource_size(res) == 8) {
ddata->cfg.quirks |= SYSC_QUIRK_16BIT | SYSC_QUIRK_USE_CLOCKACT;
+ ddata->revision_doubleword = true;
+ }
}
/**
@@ -1527,9 +1533,11 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff,
SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff,
- SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
+ SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE |
+ SYSC_QUIRK_16BIT | SYSC_QUIRK_USE_CLOCKACT),
SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff,
- SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
+ SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE |
+ SYSC_QUIRK_16BIT | SYSC_QUIRK_USE_CLOCKACT),
SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,
SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE),
SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0),
@@ -1872,7 +1880,7 @@ static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable)
u16 val;
/* I2C_CON, omap2/3 is different from omap4 and later */
- if ((ddata->revision & 0xffffff00) == 0x001f0000)
+ if (!ddata->revision_doubleword)
offset = 0x24;
else
offset = 0xa4;
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2 2/3] ARM: dts: ti/omap: describe omap3 i2c via ti-sysc
2026-11-10 20:56 [PATCH v2 0/3] ARM: OMAP2+: Convert OMAP3 I2C to ti-sysc Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 1/3] bus: ti-sysc: fix I2C quirk for OMAP3 variants Andreas Kemnade
@ 2026-11-10 20:56 ` Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 3/3] ARM: OMAP2+: remove i2c from OMAP3 hwmods list Andreas Kemnade
2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-11-10 20:56 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andi Shyti,
Thomas Richard, Wolfram Sang, Paul Walmsley, Russell King
Cc: Sicelo, linux-omap, linux-kernel, devicetree, linux-arm-kernel,
Andreas Kemnade
ti,hwmods is deprecated, and the power management there is working a bit
different than the one in the ti-sysc way. So if something is changed
with pm incfluence, it has to be tested on both. To reduce that maintenance
work, convert to ti-sysc. Also fixes an actual crash with OMAP3 and
suspend. That was caused by a commit enabling i2c access in later phases
of suspend until the noirq phase. But that causes some state expectation
mismatch between omap_device.c code and the i2c code leading to the
following:
Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa060004
[...]
PC is at omap_i2c_runtime_suspend+0x1c/0xd8
[...]
Call trace:
omap_i2c_runtime_suspend from _od_suspend_noirq+0x44/0xe0
_od_suspend_noirq from dpm_run_callback+0x4c/0x1f0
dpm_run_callback from device_suspend_noirq+0x208/0x594
device_suspend_noirq from dpm_suspend_noirq+0x1c8/0x3a4
dpm_suspend_noirq from suspend_devices_and_enter+0x10c/0x840
suspend_devices_and_enter from pm_suspend+0x25c/0x3fc
pm_suspend from state_store+0x114/0x130
Fixes: 7da7fd7e66ac9 ("i2c: omap: wakeup the controller during suspend() callback")
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
arch/arm/boot/dts/ti/omap/omap3.dtsi | 96 +++++++++++++++++++++++++++++-------
1 file changed, 78 insertions(+), 18 deletions(-)
diff --git a/arch/arm/boot/dts/ti/omap/omap3.dtsi b/arch/arm/boot/dts/ti/omap/omap3.dtsi
index 447736d2e53ca..2ee5fd4888ce5 100644
--- a/arch/arm/boot/dts/ti/omap/omap3.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3.dtsi
@@ -396,31 +396,91 @@ uart3: serial@49020000 {
clock-frequency = <48000000>;
};
- i2c1: i2c@48070000 {
- compatible = "ti,omap3-i2c";
- reg = <0x48070000 0x80>;
- interrupts = <56>;
+ i2c1_target: target-module@48070000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
+ reg = <0x48070000 0x4>,
+ <0x48070020 0x4>,
+ <0x48070010 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+ SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&i2c1_fck>, <&i2c1_ick>;
+ clock-names = "fck", "ick";
#address-cells = <1>;
- #size-cells = <0>;
- ti,hwmods = "i2c1";
+ #size-cells = <1>;
+ ranges = <0 0x48070000 0x1000>;
+
+ i2c1: i2c@0 {
+ compatible = "ti,omap3-i2c";
+ reg = <0x0 0x80>;
+ interrupts = <56>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
- i2c2: i2c@48072000 {
- compatible = "ti,omap3-i2c";
- reg = <0x48072000 0x80>;
- interrupts = <57>;
+ i2c2_target: target-module@48072000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
+ reg = <0x48072000 0x4>,
+ <0x48072020 0x4>,
+ <0x48072010 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+ SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&i2c2_fck>, <&i2c2_ick>;
+ clock-names = "fck", "ick";
#address-cells = <1>;
- #size-cells = <0>;
- ti,hwmods = "i2c2";
+ #size-cells = <1>;
+ ranges = <0 0x48072000 0x1000>;
+
+ i2c2: i2c@0 {
+ compatible = "ti,omap3-i2c";
+ reg = <0x0 0x80>;
+ interrupts = <57>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
- i2c3: i2c@48060000 {
- compatible = "ti,omap3-i2c";
- reg = <0x48060000 0x80>;
- interrupts = <61>;
+ i2c3_target: target-module@48060000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
+ reg = <0x48060000 0x4>,
+ <0x48060020 0x4>,
+ <0x48060010 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+ SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&i2c3_fck>, <&i2c3_ick>;
+ clock-names = "fck", "ick";
#address-cells = <1>;
- #size-cells = <0>;
- ti,hwmods = "i2c3";
+ #size-cells = <1>;
+ ranges = <0 0x48060000 0x1000>;
+
+ i2c3: i2c@0 {
+ compatible = "ti,omap3-i2c";
+ reg = <0x0 0x80>;
+ interrupts = <61>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
mailbox: mailbox@48094000 {
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2 3/3] ARM: OMAP2+: remove i2c from OMAP3 hwmods list
2026-11-10 20:56 [PATCH v2 0/3] ARM: OMAP2+: Convert OMAP3 I2C to ti-sysc Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 1/3] bus: ti-sysc: fix I2C quirk for OMAP3 variants Andreas Kemnade
2026-11-10 20:56 ` [PATCH v2 2/3] ARM: dts: ti/omap: describe omap3 i2c via ti-sysc Andreas Kemnade
@ 2026-11-10 20:56 ` Andreas Kemnade
2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-11-10 20:56 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andi Shyti,
Thomas Richard, Wolfram Sang, Paul Walmsley, Russell King
Cc: Sicelo, linux-omap, linux-kernel, devicetree, linux-arm-kernel,
Andreas Kemnade
Not need anymore due to ti-sysc transition, so clean up here.
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 112 -----------------------------
1 file changed, 112 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 5cbdf58ad59f7..022019ff4a398 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -299,18 +299,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
.sysc_fields = &omap_hwmod_sysc_type1,
};
-/* I2C common */
-static struct omap_hwmod_class_sysconfig i2c_sysc = {
- .rev_offs = 0x00,
- .sysc_offs = 0x20,
- .syss_offs = 0x10,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap3xxx_wd_timer_sysc,
@@ -431,12 +419,6 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
.class = &omap2_uart_class,
};
-static struct omap_hwmod_class i2c_class = {
- .name = "i2c",
- .sysc = &i2c_sysc,
- .reset = &omap_i2c_reset,
-};
-
/* dss */
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
/*
@@ -592,51 +574,6 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
.flags = HWMOD_NO_IDLEST,
};
-/* I2C1 */
-static struct omap_hwmod omap3xxx_i2c1_hwmod = {
- .name = "i2c1",
- .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
- .main_clk = "i2c1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP3430_ST_I2C1_SHIFT,
- },
- },
- .class = &i2c_class,
-};
-
-/* I2C2 */
-static struct omap_hwmod omap3xxx_i2c2_hwmod = {
- .name = "i2c2",
- .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
- .main_clk = "i2c2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP3430_ST_I2C2_SHIFT,
- },
- },
- .class = &i2c_class,
-};
-
-/* I2C3 */
-static struct omap_hwmod omap3xxx_i2c3_hwmod = {
- .name = "i2c3",
- .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
- .main_clk = "i2c3_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP3430_ST_I2C3_SHIFT,
- },
- },
- .class = &i2c_class,
-};
-
/*
* 'gpio' class
* general purpose io module
@@ -1605,52 +1542,6 @@ static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c1_hwmod,
- .clk = "i2c1_ick",
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C1_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- },
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c2_hwmod,
- .clk = "i2c2_ick",
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C2_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- },
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C3 interface */
-
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c3_hwmod,
- .clk = "i2c3_ick",
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C3_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- },
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
/* L4 CORE -> SR1 interface */
static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = {
.master = &omap3xxx_l4_core_hwmod,
@@ -2300,9 +2191,6 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
&omap3_l4_core__uart1,
&omap3_l4_core__uart2,
&omap3_l4_per__uart3,
- &omap3_l4_core__i2c1,
- &omap3_l4_core__i2c2,
- &omap3_l4_core__i2c3,
&omap3xxx_l4_wkup__l4_sec,
&omap3xxx_l4_per__timer3,
&omap3xxx_l4_per__timer4,
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread