From: Rustam Adilov Date: Fri, 10 Jul 2026 13:09:46 +0000 (+0500) Subject: realtek: watchdog: backport upstream regmap patch X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ff901f165cf923968089a0dc2510c1cbe95d02a;p=thirdparty%2Fopenwrt.git realtek: watchdog: backport upstream regmap patch The patch to replace mmio access in the realtek watchdog driver with regmap API has been accepted upstream [1]. Backport them here as this is one of the steps required for a working system with SWAP_IO_SPACE config enabled. [1] https://lore.kernel.org/linux-watchdog/20260710074316.46643-1-adilov@disroot.org/ Signed-off-by: Rustam Adilov Link: https://github.com/openwrt/openwrt/pull/24169 Signed-off-by: Jonas Jelonek --- diff --git a/target/linux/realtek/patches-6.18/035-v7.3-watchdog-realtek-otto-change-to-use-regmap-API.patch b/target/linux/realtek/patches-6.18/035-v7.3-watchdog-realtek-otto-change-to-use-regmap-API.patch new file mode 100644 index 00000000000..63e34af2a16 --- /dev/null +++ b/target/linux/realtek/patches-6.18/035-v7.3-watchdog-realtek-otto-change-to-use-regmap-API.patch @@ -0,0 +1,206 @@ +From f8b38cdf3c84b60096a99398c1e9b2d5c68714a2 Mon Sep 17 00:00:00 2001 +From: Rustam Adilov +Date: Fri, 10 Jul 2026 12:43:16 +0500 +Subject: watchdog: realtek-otto: Change to use regmap API + +To make the realtek watchdog driver functional when SWAP_IO_SPACE +config is enabled, change all of the register access to be done +by regmap API which helps us to tweak endianness with big-endian +or little-endian property from within the device tree node. + +Add the REGMAP_MMIO as a select to REALTEK_OTTO_WDT now that the +regmap is used. + +Signed-off-by: Rustam Adilov +Link: https://lore.kernel.org/r/20260710074316.46643-2-adilov@disroot.org +Signed-off-by: Guenter Roeck +--- + drivers/watchdog/Kconfig | 1 + + drivers/watchdog/realtek_otto_wdt.c | 74 +++++++++++++++++++------------------ + 2 files changed, 39 insertions(+), 36 deletions(-) + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1068,6 +1068,7 @@ config REALTEK_OTTO_WDT + depends on MACH_REALTEK_RTL || COMPILE_TEST + depends on COMMON_CLK + select WATCHDOG_CORE ++ select REGMAP_MMIO + default MACH_REALTEK_RTL + help + Say Y here to include support for the watchdog timer on Realtek +--- a/drivers/watchdog/realtek_otto_wdt.c ++++ b/drivers/watchdog/realtek_otto_wdt.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #define OTTO_WDT_REG_CNTR 0x0 +@@ -66,7 +67,7 @@ + struct otto_wdt_ctrl { + struct watchdog_device wdev; + struct device *dev; +- void __iomem *base; ++ struct regmap *regmap; + unsigned int clk_rate_khz; + int irq_phase1; + }; +@@ -74,24 +75,17 @@ struct otto_wdt_ctrl { + static int otto_wdt_start(struct watchdog_device *wdev) + { + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); +- u32 v; +- +- v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); +- v |= OTTO_WDT_CTRL_ENABLE; +- iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); + ++ regmap_set_bits(ctrl->regmap, OTTO_WDT_REG_CTRL, OTTO_WDT_CTRL_ENABLE); + return 0; + } + + static int otto_wdt_stop(struct watchdog_device *wdev) + { + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); +- u32 v; +- +- v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); +- v &= ~OTTO_WDT_CTRL_ENABLE; +- iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); + ++ regmap_clear_bits(ctrl->regmap, OTTO_WDT_REG_CTRL, ++ OTTO_WDT_CTRL_ENABLE); + return 0; + } + +@@ -99,8 +93,7 @@ static int otto_wdt_ping(struct watchdog + { + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); + +- iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR); +- ++ regmap_write(ctrl->regmap, OTTO_WDT_REG_CNTR, OTTO_WDT_CNTR_PING); + return 0; + } + +@@ -126,7 +119,7 @@ static int otto_wdt_determine_timeouts(s + unsigned int total_ticks; + unsigned int prescale; + unsigned int tick_ms; +- u32 v; ++ u32 mask, val; + + do { + prescale = prescale_next; +@@ -142,14 +135,11 @@ static int otto_wdt_determine_timeouts(s + } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX + || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX); + +- v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); +- +- v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2); +- v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1); +- v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1); +- v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale); +- +- iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ mask = OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2; ++ val = FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1); ++ val |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1); ++ val |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale); ++ regmap_update_bits(ctrl->regmap, OTTO_WDT_REG_CTRL, mask, val); + + timeout_ms = total_ticks * tick_ms; + ctrl->wdev.timeout = timeout_ms / 1000; +@@ -193,7 +183,7 @@ static int otto_wdt_restart(struct watch + + /* Configure for shortest timeout and wait for reset to occur */ + v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE; +- iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ regmap_write(ctrl->regmap, OTTO_WDT_REG_CTRL, v); + + mdelay(3 * otto_wdt_tick_ms(ctrl, 0)); + +@@ -204,7 +194,7 @@ static irqreturn_t otto_wdt_phase1_isr(i + { + struct otto_wdt_ctrl *ctrl = dev_id; + +- iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR); ++ regmap_write(ctrl->regmap, OTTO_WDT_REG_INTR, OTTO_WDT_INTR_PHASE_1); + dev_crit(ctrl->dev, "phase 1 timeout\n"); + watchdog_notify_pretimeout(&ctrl->wdev); + +@@ -250,7 +240,6 @@ static int otto_wdt_probe_reset_mode(str + const struct fwnode_handle *node = ctrl->dev->fwnode; + int mode_count; + u32 mode; +- u32 v; + + if (!node) + return -ENXIO; +@@ -272,19 +261,25 @@ static int otto_wdt_probe_reset_mode(str + else + return -EINVAL; + +- v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); +- v &= ~OTTO_WDT_CTRL_RST_MODE; +- v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode); +- iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); +- ++ regmap_update_bits(ctrl->regmap, OTTO_WDT_REG_CTRL, ++ OTTO_WDT_CTRL_RST_MODE, ++ FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode)); + return 0; + } + ++static const struct regmap_config realtek_otto_wdt_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .disable_locking = true, ++}; ++ + static int otto_wdt_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct otto_wdt_ctrl *ctrl; + unsigned int max_tick_ms; ++ void __iomem *base; + int ret; + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); +@@ -292,18 +287,25 @@ static int otto_wdt_probe(struct platfor + return -ENOMEM; + + ctrl->dev = dev; +- ctrl->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(ctrl->base)) +- return PTR_ERR(ctrl->base); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ ctrl->regmap = devm_regmap_init_mmio(dev, base, ++ &realtek_otto_wdt_regmap_config); ++ if (IS_ERR(ctrl->regmap)) { ++ dev_err(dev, "regmap init failed\n"); ++ return PTR_ERR(ctrl->regmap); ++ } + + ret = otto_wdt_probe_clk(ctrl); + if (ret) + return ret; + + /* Clear any old interrupts and reset initial state */ +- iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2, +- ctrl->base + OTTO_WDT_REG_INTR); +- iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL); ++ regmap_write(ctrl->regmap, OTTO_WDT_REG_INTR, ++ OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2); ++ regmap_write(ctrl->regmap, OTTO_WDT_REG_CTRL, OTTO_WDT_CTRL_DEFAULT); + + ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1"); + if (ctrl->irq_phase1 < 0)