[PATCH v2 1/1] watchdog: mtk_wdt: Remove mtk_wdt_stop() in probe() to prevent the system freeze and it doesn't reboot by watchdog problem
From: "freddy.hsin" Before user space daemon start to access the watchdog device, there is a time interval that watchdog is disabled in the original flow. If the system freezing at this interval, it cannot be rebooted by watchdog hardware automatically. In order to solve this problem, the watchdog hardware should be kept working, and start hrtimer in framework to ping it by setting max_hw_heartbeat_ms and HW_RUNNING used in watchdog_need_worker to determine whether the worker should be started or not. Besides the redundant setting of max_timeout is also removed. Signed-off-by: freddy.hsin --- drivers/watchdog/mtk_wdt.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index d6a6393..0c869b7 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -195,6 +195,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev, return 0; } +static void mtk_wdt_init(struct watchdog_device *wdt_dev) +{ + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); + void __iomem *wdt_base; + + wdt_base = mtk_wdt->wdt_base; + + if (readl(wdt_base + WDT_MODE) & WDT_MODE_EN) { + set_bit(WDOG_HW_RUNNING, &wdt_dev->status); + mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout); + } +} + static int mtk_wdt_stop(struct watchdog_device *wdt_dev) { struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); @@ -264,7 +277,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) mtk_wdt->wdt_dev.info = &mtk_wdt_info; mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; - mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT; + mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; mtk_wdt->wdt_dev.parent = dev; @@ -274,7 +287,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); - mtk_wdt_stop(&mtk_wdt->wdt_dev); + mtk_wdt_init(&mtk_wdt->wdt_dev); watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); -- 1.7.9.5
driver: watchdog: Remove mtk_wdt_stop() in probe() to prevent the system freeze and it doesn't reboot by watchdog problem
Before user space daemon start to access the watchdog device, there is a time interval that watchdog is disabled in the original flow. If the system freezing at this interval, it cannot be rebooted by watchdog hardware automatically. In order to solve this problem, the watchdog hardware should be kept working, and start hrtimer in framework to ping it by setting max_hw_heartbeat_ms and HW_RUNNING used in watchdog_need_worker to determine whether the worker should be started or not
[PATCH v1 1/1] driver: watchdog: Remove mtk_wdt_stop() in probe() to prevent the system freeze and it doesn't reboot by watchdog problem
From: "freddy.hsin" Before user space daemon start to access the watchdog device, there is a time interval that watchdog is disabled in the original flow. If the system freezing at this interval, it cannot be rebooted by watchdog hardware automatically. In order to solve this problem, the watchdog hardware should be kept working, and start hrtimer in framework to ping it by setting max_hw_heartbeat_ms and HW_RUNNING used in watchdog_need_worker to determine whether the worker should be started or not Change-Id: I6a041b0922888a90011d7538ee804d80bc8d15ea Signed-off-by: freddy.hsin --- drivers/watchdog/mtk_wdt.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index d6a6393..62f08cd 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -195,6 +195,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev, return 0; } +static void mtk_wdt_init(struct watchdog_device *wdt_dev) +{ + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); + void __iomem *wdt_base; + + wdt_base = mtk_wdt->wdt_base; + + if (readl(wdt_base + WDT_MODE) & WDT_MODE_EN) { + set_bit(WDOG_HW_RUNNING, &wdt_dev->status); + mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout); + } +} + static int mtk_wdt_stop(struct watchdog_device *wdt_dev) { struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); @@ -266,16 +279,17 @@ static int mtk_wdt_probe(struct platform_device *pdev) mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; + mtk_wdt->wdt_dev.max_hw_heartbeat_ms = (WDT_MAX_TIMEOUT - 1) * 1000; mtk_wdt->wdt_dev.parent = dev; + watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); + + mtk_wdt_init(&mtk_wdt->wdt_dev); + watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev); watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); - watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); - - mtk_wdt_stop(&mtk_wdt->wdt_dev); - watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); if (unlikely(err)) -- 1.7.9.5
[PATCH v1 1/1] timer: mt6873: remove COMPILE_TEST condition for MTK timer
MTK timer driver can work on MTK platform normally, so remove the redundant condition for MTK_TIMER Signed-off-by: Freddy Hsin --- drivers/clocksource/Kconfig |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 9141838..1ec5d94 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -472,7 +472,7 @@ config SYS_SUPPORTS_SH_CMT bool config MTK_TIMER - bool "Mediatek timer driver" if COMPILE_TEST + bool "Mediatek timer driver" depends on HAS_IOMEM select TIMER_OF select CLKSRC_MMIO -- 1.7.9.5
[PATCH 0/1] Remove redundant condition for MTK_TIMER
Remove the redundant condition of MTK_TIMER because the driver can work on MTK platform normally, so COMPILE_TEST is no longer needed for development purpose Freddy Hsin (1): timer: mt6873: remove COMPILE_TEST condition for MTK timer drivers/clocksource/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH 0/1] Refine mtk wdt driver init flow
Add mtk_wdt_init() functin in probe flow to determine enable/disable the hw watchdog by its original setting Freddy Hsin (1): driver: watchdog: Add mtk_wdt_init for mediatek watchdog hw init drivers/watchdog/mtk_wdt.c | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-)
[PATCH v1 1/1] driver: watchdog: Add mtk_wdt_init for mediatek watchdog hw init
1. add a hw initialization function 2. enable/disable the watchdog depends on the original hw setting 3. set WDOD_HW_RUNNING in start function in order to start kicker after driver probe and clear the bit in stop function Change-Id: I25aa797f3b88288f26984455e499e599e27f09fa Signed-off-by: Freddy Hsin --- drivers/watchdog/mtk_wdt.c | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index d6a6393..59b5061 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -57,6 +57,9 @@ static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout; +static int mtk_wdt_start(struct watchdog_device *wdt_dev); +static int mtk_wdt_stop(struct watchdog_device *wdt_dev); + struct mtk_wdt_dev { struct watchdog_device wdt_dev; void __iomem *wdt_base; @@ -148,6 +151,19 @@ static int toprgu_register_reset_controller(struct platform_device *pdev, return ret; } +static int mtk_wdt_init(struct watchdog_device *wdt_dev) +{ + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); + void __iomem *wdt_base; + + wdt_base = mtk_wdt->wdt_base; + + if (readl(wdt_base + WDT_MODE) & WDT_MODE_EN) + mtk_wdt_start(wdt_dev); + else + mtk_wdt_stop(wdt_dev); +} + static int mtk_wdt_restart(struct watchdog_device *wdt_dev, unsigned long action, void *data) { @@ -206,6 +222,8 @@ static int mtk_wdt_stop(struct watchdog_device *wdt_dev) reg |= WDT_MODE_KEY; iowrite32(reg, wdt_base + WDT_MODE); + clear_bit(WDOG_HW_RUNNING, &wdt_dev->status); + return 0; } @@ -225,6 +243,8 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); + set_bit(WDOG_HW_RUNNING, &wdt_dev->status); + return 0; } @@ -274,7 +294,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); - mtk_wdt_stop(&mtk_wdt->wdt_dev); + mtk_wdt_init(&mtk_wdt->wdt_dev); watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); -- 1.7.9.5
[PATCH v1 1/2] kernel: time: export sched_clock_register function
export sched_clock_register function, because the Mediatek timer loadable module depends on this function Signed-off-by: Freddy Hsin --- kernel/time/sched_clock.c |1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index fa3f800..e1d5afe 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -239,6 +239,7 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt) pr_debug("Registered %pS as sched_clock source\n", read); } +EXPORT_SYMBOL(sched_clock_register); void __init generic_sched_clock_init(void) { -- 1.7.9.5
[PATCH v1] Porting Mediatek timer driver to kernel module
Porting Mediatek timer driver to kernel module for GKI (Generic Kernel Image). Clocksource mmio functions are exported for Mediatek timer init function. This patch depends on the timer-of patch submitted by Baolin Wang https://lkml.org/lkml/2020/3/24/72 Freddy Hsin (2): kernel: time: remove init section label of sched_clock_register timer: mt6873: porting timer driver to loadable module drivers/clocksource/Kconfig |2 +- drivers/clocksource/mmio.c |4 +++- drivers/clocksource/timer-mediatek.c | 39 ++ kernel/time/sched_clock.c|1 +
[PATCH v1 2/2] timer: mt6873: porting Mediatek timer driver to loadable module
porting Mediatek timer driver to loadable module Signed-off-by: Freddy Hsin --- drivers/clocksource/Kconfig |2 +- drivers/clocksource/mmio.c |4 +++- drivers/clocksource/timer-mediatek.c | 39 ++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 9141838..538351a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -472,7 +472,7 @@ config SYS_SUPPORTS_SH_CMT bool config MTK_TIMER - bool "Mediatek timer driver" if COMPILE_TEST + tristate "Mediatek timer driver" depends on HAS_IOMEM select TIMER_OF select CLKSRC_MMIO diff --git a/drivers/clocksource/mmio.c b/drivers/clocksource/mmio.c index 9de7515..5504569 100644 --- a/drivers/clocksource/mmio.c +++ b/drivers/clocksource/mmio.c @@ -21,6 +21,7 @@ u64 clocksource_mmio_readl_up(struct clocksource *c) { return (u64)readl_relaxed(to_mmio_clksrc(c)->reg); } +EXPORT_SYMBOL(clocksource_mmio_readl_up); u64 clocksource_mmio_readl_down(struct clocksource *c) { @@ -46,7 +47,7 @@ u64 clocksource_mmio_readw_down(struct clocksource *c) * @bits: Number of valid bits * @read: One of clocksource_mmio_read*() above */ -int __init clocksource_mmio_init(void __iomem *base, const char *name, +int clocksource_mmio_init(void __iomem *base, const char *name, unsigned long hz, int rating, unsigned bits, u64 (*read)(struct clocksource *)) { @@ -68,3 +69,4 @@ int __init clocksource_mmio_init(void __iomem *base, const char *name, return clocksource_register_hz(&cs->clksrc, hz); } +EXPORT_SYMBOL(clocksource_mmio_init); diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c index 9318edc..5c89b6b 100644 --- a/drivers/clocksource/timer-mediatek.c +++ b/drivers/clocksource/timer-mediatek.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include #include #include "timer-of.h" @@ -309,5 +312,41 @@ static int __init mtk_gpt_init(struct device_node *node) return 0; } + +#ifdef MODULE +static int mtk_timer_probe(struct platform_device *pdev) +{ + int (*timer_init)(struct device_node *node); + struct device_node *np = pdev->dev.of_node; + + timer_init = of_device_get_match_data(&pdev->dev); + return timer_init(np); +} + +static const struct of_device_id mtk_timer_match_table[] = { + { + .compatible = "mediatek,mt6577-timer", + .data = mtk_gpt_init, + }, + { + .compatible = "mediatek,mt6765-timer", + .data = mtk_syst_init, + }, + {} +}; + +static struct platform_driver mtk_timer_driver = { + .probe = mtk_timer_probe, + .driver = { + .name = "mtk-timer", + .of_match_table = mtk_timer_match_table, + }, +}; +MODULE_DESCRIPTION("MEDIATEK Module timer driver"); +MODULE_LICENSE("GPL v2"); + +module_platform_driver(mtk_timer_driver); +#else TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init); TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init); +#endif -- 1.7.9.5