From 96010bb17c0a15427f60b836165d50617f0dfb1c Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Thu, 22 Jun 2023 21:22:32 +0800 Subject: [PATCH] ramips: mt7621-wdt: use phandle to access system controller registers These patches allow the driver to access some watchdog registers via a phandle to the system controller node[1]. To apply these changes, we need to add "mediatek,sysctl" to the SoC dtsi. This commit also remove the redundent clocks, interrupts and resets properties. [1] https://lore.kernel.org/all/20230214103936.1061078-2-sergio.paracuellos@gmail.com Tested on Motorola MWR03 (MT7628) Signed-off-by: Shiji Yang --- target/linux/ramips/dts/mt7621.dtsi | 3 +- target/linux/ramips/dts/mt7628an.dtsi | 13 +- ...wdt-avoid-static-global-declarations.patch | 213 ++++++++++++++++++ ...wdt-avoid-ralink-architecture-depend.patch | 104 +++++++++ 4 files changed, 322 insertions(+), 11 deletions(-) create mode 100644 target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch create mode 100644 target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index 84a7b306a7..f1f77282b2 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -61,9 +61,10 @@ reg = <0x0 0x100>; }; - wdt: wdt@100 { + wdt: watchdog@100 { compatible = "mediatek,mt7621-wdt"; reg = <0x100 0x100>; + mediatek,sysctl = <&sysc>; }; gpio: gpio@600 { diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index 74d2c980b5..d6c3a47b0b 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -46,16 +46,9 @@ }; watchdog: watchdog@100 { - compatible = "ralink,mt7628an-wdt", "mediatek,mt7621-wdt"; - reg = <0x100 0x30>; - - clocks = <&sysc 6>; - - resets = <&sysc 8>; - reset-names = "wdt"; - - interrupt-parent = <&intc>; - interrupts = <24>; + compatible = "mediatek,mt7621-wdt"; + reg = <0x100 0x100>; + mediatek,sysctl = <&sysc>; }; intc: intc@200 { diff --git a/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch b/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch new file mode 100644 index 0000000000..e06d5621e1 --- /dev/null +++ b/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch @@ -0,0 +1,213 @@ +From 783c7cb4659b53b5e1b809dac5e8cdf250145919 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Tue, 14 Feb 2023 11:39:35 +0100 +Subject: [PATCH 1/2] watchdog: mt7621-wdt: avoid static global declarations + +Instead of using static global definitions in driver code, refactor code +introducing a new watchdog driver data structure and use it along the +code. + +Reviewed-by: Guenter Roeck +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20230214103936.1061078-5-sergio.paracuellos@gmail.com +[groeck: unsigned -> unsigned int] +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/mt7621_wdt.c | 102 +++++++++++++++++++++++++++--------------- + 1 file changed, 65 insertions(+), 37 deletions(-) + +--- a/drivers/watchdog/mt7621_wdt.c ++++ b/drivers/watchdog/mt7621_wdt.c +@@ -31,8 +31,11 @@ + #define TMR1CTL_RESTART BIT(9) + #define TMR1CTL_PRESCALE_SHIFT 16 + +-static void __iomem *mt7621_wdt_base; +-static struct reset_control *mt7621_wdt_reset; ++struct mt7621_wdt_data { ++ void __iomem *base; ++ struct reset_control *rst; ++ struct watchdog_device wdt; ++}; + + static bool nowayout = WATCHDOG_NOWAYOUT; + module_param(nowayout, bool, 0); +@@ -40,27 +43,31 @@ MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +-static inline void rt_wdt_w32(unsigned reg, u32 val) ++static inline void rt_wdt_w32(void __iomem *base, unsigned int reg, u32 val) + { +- iowrite32(val, mt7621_wdt_base + reg); ++ iowrite32(val, base + reg); + } + +-static inline u32 rt_wdt_r32(unsigned reg) ++static inline u32 rt_wdt_r32(void __iomem *base, unsigned int reg) + { +- return ioread32(mt7621_wdt_base + reg); ++ return ioread32(base + reg); + } + + static int mt7621_wdt_ping(struct watchdog_device *w) + { +- rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART); ++ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); ++ ++ rt_wdt_w32(drvdata->base, TIMER_REG_TMRSTAT, TMR1CTL_RESTART); + + return 0; + } + + static int mt7621_wdt_set_timeout(struct watchdog_device *w, unsigned int t) + { ++ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); ++ + w->timeout = t; +- rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000); ++ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1LOAD, t * 1000); + mt7621_wdt_ping(w); + + return 0; +@@ -68,29 +75,31 @@ static int mt7621_wdt_set_timeout(struct + + static int mt7621_wdt_start(struct watchdog_device *w) + { ++ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); + u32 t; + + /* set the prescaler to 1ms == 1000us */ +- rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); ++ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); + + mt7621_wdt_set_timeout(w, w->timeout); + +- t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); + t |= TMR1CTL_ENABLE; +- rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); + + return 0; + } + + static int mt7621_wdt_stop(struct watchdog_device *w) + { ++ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); + u32 t; + + mt7621_wdt_ping(w); + +- t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); + t &= ~TMR1CTL_ENABLE; +- rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); + + return 0; + } +@@ -105,7 +114,9 @@ static int mt7621_wdt_bootcause(void) + + static int mt7621_wdt_is_running(struct watchdog_device *w) + { +- return !!(rt_wdt_r32(TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); ++ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); ++ ++ return !!(rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); + } + + static const struct watchdog_info mt7621_wdt_info = { +@@ -121,30 +132,39 @@ static const struct watchdog_ops mt7621_ + .set_timeout = mt7621_wdt_set_timeout, + }; + +-static struct watchdog_device mt7621_wdt_dev = { +- .info = &mt7621_wdt_info, +- .ops = &mt7621_wdt_ops, +- .min_timeout = 1, +- .max_timeout = 0xfffful / 1000, +-}; +- + static int mt7621_wdt_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- mt7621_wdt_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(mt7621_wdt_base)) +- return PTR_ERR(mt7621_wdt_base); +- +- mt7621_wdt_reset = devm_reset_control_get_exclusive(dev, NULL); +- if (!IS_ERR(mt7621_wdt_reset)) +- reset_control_deassert(mt7621_wdt_reset); +- +- mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause(); +- +- watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout, +- dev); +- watchdog_set_nowayout(&mt7621_wdt_dev, nowayout); +- if (mt7621_wdt_is_running(&mt7621_wdt_dev)) { ++ struct watchdog_device *mt7621_wdt; ++ struct mt7621_wdt_data *drvdata; ++ int err; ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(drvdata->base)) ++ return PTR_ERR(drvdata->base); ++ ++ drvdata->rst = devm_reset_control_get_exclusive(dev, NULL); ++ if (!IS_ERR(drvdata->rst)) ++ reset_control_deassert(drvdata->rst); ++ ++ mt7621_wdt = &drvdata->wdt; ++ mt7621_wdt->info = &mt7621_wdt_info; ++ mt7621_wdt->ops = &mt7621_wdt_ops; ++ mt7621_wdt->min_timeout = 1; ++ mt7621_wdt->max_timeout = 0xfffful / 1000; ++ mt7621_wdt->parent = dev; ++ ++ mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); ++ ++ watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); ++ watchdog_set_nowayout(mt7621_wdt, nowayout); ++ watchdog_set_drvdata(mt7621_wdt, drvdata); ++ ++ if (mt7621_wdt_is_running(mt7621_wdt)) { + /* + * Make sure to apply timeout from watchdog core, taking + * the prescaler of this driver here into account (the +@@ -154,17 +174,25 @@ static int mt7621_wdt_probe(struct platf + * we first disable the watchdog, set the new prescaler + * and timeout, and then re-enable the watchdog. + */ +- mt7621_wdt_stop(&mt7621_wdt_dev); +- mt7621_wdt_start(&mt7621_wdt_dev); +- set_bit(WDOG_HW_RUNNING, &mt7621_wdt_dev.status); ++ mt7621_wdt_stop(mt7621_wdt); ++ mt7621_wdt_start(mt7621_wdt); ++ set_bit(WDOG_HW_RUNNING, &mt7621_wdt->status); + } + +- return devm_watchdog_register_device(dev, &mt7621_wdt_dev); ++ err = devm_watchdog_register_device(dev, &drvdata->wdt); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, drvdata); ++ ++ return 0; + } + + static void mt7621_wdt_shutdown(struct platform_device *pdev) + { +- mt7621_wdt_stop(&mt7621_wdt_dev); ++ struct mt7621_wdt_data *drvdata = platform_get_drvdata(pdev); ++ ++ mt7621_wdt_stop(&drvdata->wdt); + } + + static const struct of_device_id mt7621_wdt_match[] = { diff --git a/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch b/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch new file mode 100644 index 0000000000..8e6265404b --- /dev/null +++ b/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch @@ -0,0 +1,104 @@ +From ff8ec4ac39ad413b580d611dbf68e1d8a82eba56 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Tue, 14 Feb 2023 11:39:36 +0100 +Subject: [PATCH 2/2] watchdog: mt7621-wdt: avoid ralink architecture dependent code + +MT7621 SoC has a system controller node. Watchdog need to access to reset +status register. Ralink architecture and related driver are old and from +the beggining they are using some architecture dependent operations for +accessing this shared registers through 'asm/mach-ralink/ralink_regs.h' +header file. However this is not ideal from a driver perspective which can +just access to the system controller registers in an arch independent way +using regmap syscon APIs. Update Kconfig accordingly to select new added +dependencies and allow driver to be compile tested. + +Signed-off-by: Sergio Paracuellos +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20230214103936.1061078-6-sergio.paracuellos@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/Kconfig | 4 +++- + drivers/watchdog/mt7621_wdt.c | 22 +++++++++++++++++----- + 2 files changed, 20 insertions(+), 6 deletions(-) + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1799,7 +1799,9 @@ config RALINK_WDT + config MT7621_WDT + tristate "Mediatek SoC watchdog" + select WATCHDOG_CORE +- depends on SOC_MT7620 || SOC_MT7621 ++ select REGMAP_MMIO ++ select MFD_SYSCON ++ depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST + help + Hardware driver for the Mediatek/Ralink MT7621/8 SoC Watchdog Timer. + +--- a/drivers/watchdog/mt7621_wdt.c ++++ b/drivers/watchdog/mt7621_wdt.c +@@ -15,8 +15,8 @@ + #include + #include + #include +- +-#include ++#include ++#include + + #define SYSC_RSTSTAT 0x38 + #define WDT_RST_CAUSE BIT(1) +@@ -34,6 +34,7 @@ + struct mt7621_wdt_data { + void __iomem *base; + struct reset_control *rst; ++ struct regmap *sysc; + struct watchdog_device wdt; + }; + +@@ -104,9 +105,12 @@ static int mt7621_wdt_stop(struct watchd + return 0; + } + +-static int mt7621_wdt_bootcause(void) ++static int mt7621_wdt_bootcause(struct mt7621_wdt_data *d) + { +- if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) ++ u32 val; ++ ++ regmap_read(d->sysc, SYSC_RSTSTAT, &val); ++ if (val & WDT_RST_CAUSE) + return WDIOF_CARDRESET; + + return 0; +@@ -134,6 +138,7 @@ static const struct watchdog_ops mt7621_ + + static int mt7621_wdt_probe(struct platform_device *pdev) + { ++ struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct watchdog_device *mt7621_wdt; + struct mt7621_wdt_data *drvdata; +@@ -143,6 +148,13 @@ static int mt7621_wdt_probe(struct platf + if (!drvdata) + return -ENOMEM; + ++ drvdata->sysc = syscon_regmap_lookup_by_phandle(np, "mediatek,sysctl"); ++ if (IS_ERR(drvdata->sysc)) { ++ drvdata->sysc = syscon_regmap_lookup_by_compatible("mediatek,mt7621-sysc"); ++ if (IS_ERR(drvdata->sysc)) ++ return PTR_ERR(drvdata->sysc); ++ } ++ + drvdata->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); +@@ -158,7 +170,7 @@ static int mt7621_wdt_probe(struct platf + mt7621_wdt->max_timeout = 0xfffful / 1000; + mt7621_wdt->parent = dev; + +- mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); ++ mt7621_wdt->bootstatus = mt7621_wdt_bootcause(drvdata); + + watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); + watchdog_set_nowayout(mt7621_wdt, nowayout); -- 2.30.2