* [rtc-linux] [PATCH 1/2] rtc: stmp3xxx: unify register access macros @ 2015-10-02 20:18 ` Harald Geyer 0 siblings, 0 replies; 8+ messages in thread From: Harald Geyer @ 2015-10-02 20:18 UTC (permalink / raw) To: Alessandro Zummo, Alexandre Belloni, Wim Van Sebroeck Cc: rtc-linux, linux-watchdog, kernel, Harald Geyer Use STMP_OFFSET_REG_(SET|CLR) instead of defining _SET and _CLR for STMP3XXX_RTC_CTRL and STMP3XXX_RTC_PERSISTENT0 - no functional changes. Signed-off-by: Harald Geyer <harald@ccbib.org> --- drivers/rtc/rtc-stmp3xxx.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index eb09edd..ca54d03 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -32,8 +32,6 @@ #include <linux/stmp3xxx_rtc_wdt.h> #define STMP3XXX_RTC_CTRL 0x0 -#define STMP3XXX_RTC_CTRL_SET 0x4 -#define STMP3XXX_RTC_CTRL_CLR 0x8 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 @@ -52,8 +50,6 @@ #define STMP3XXX_RTC_WATCHDOG 0x50 #define STMP3XXX_RTC_PERSISTENT0 0x60 -#define STMP3XXX_RTC_PERSISTENT0_SET 0x64 -#define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1) #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2) @@ -179,7 +175,7 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) { writel(STMP3XXX_RTC_CTRL_ALARM_IRQ, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF); return IRQ_HANDLED; } @@ -194,15 +190,17 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) if (enabled) { writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_SET); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); } else { writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); } return 0; } @@ -245,7 +243,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev) return 0; writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); return 0; } @@ -334,16 +332,17 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; } - writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &stmp3xxx_rtc_ops, THIS_MODULE); @@ -376,7 +375,7 @@ static int stmp3xxx_rtc_resume(struct device *dev) writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR); return 0; } #endif -- 1.7.10.4 -- -- You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. --- You received this message because you are subscribed to the Google Groups "rtc-linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout. ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/2] rtc: stmp3xxx: unify register access macros @ 2015-10-02 20:18 ` Harald Geyer 0 siblings, 0 replies; 8+ messages in thread From: Harald Geyer @ 2015-10-02 20:18 UTC (permalink / raw) To: Alessandro Zummo, Alexandre Belloni, Wim Van Sebroeck Cc: rtc-linux, linux-watchdog, kernel, Harald Geyer Use STMP_OFFSET_REG_(SET|CLR) instead of defining _SET and _CLR for STMP3XXX_RTC_CTRL and STMP3XXX_RTC_PERSISTENT0 - no functional changes. Signed-off-by: Harald Geyer <harald@ccbib.org> --- drivers/rtc/rtc-stmp3xxx.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index eb09edd..ca54d03 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -32,8 +32,6 @@ #include <linux/stmp3xxx_rtc_wdt.h> #define STMP3XXX_RTC_CTRL 0x0 -#define STMP3XXX_RTC_CTRL_SET 0x4 -#define STMP3XXX_RTC_CTRL_CLR 0x8 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 @@ -52,8 +50,6 @@ #define STMP3XXX_RTC_WATCHDOG 0x50 #define STMP3XXX_RTC_PERSISTENT0 0x60 -#define STMP3XXX_RTC_PERSISTENT0_SET 0x64 -#define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1) #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2) @@ -179,7 +175,7 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) { writel(STMP3XXX_RTC_CTRL_ALARM_IRQ, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF); return IRQ_HANDLED; } @@ -194,15 +190,17 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) if (enabled) { writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_SET); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); } else { writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); } return 0; } @@ -245,7 +243,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev) return 0; writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); return 0; } @@ -334,16 +332,17 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; } - writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + STMP3XXX_RTC_CTRL_CLR); + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &stmp3xxx_rtc_ops, THIS_MODULE); @@ -376,7 +375,7 @@ static int stmp3xxx_rtc_resume(struct device *dev) writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, - rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR); return 0; } #endif -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [rtc-linux] [PATCH 2/2] watchdog: stmp3xxx: Implement GETBOOTSTATUS 2015-10-02 20:18 ` Harald Geyer @ 2015-10-02 20:18 ` Harald Geyer -1 siblings, 0 replies; 8+ messages in thread From: Harald Geyer @ 2015-10-02 20:18 UTC (permalink / raw) To: Alessandro Zummo, Alexandre Belloni, Wim Van Sebroeck Cc: rtc-linux, linux-watchdog, kernel, Harald Geyer When the watchdog is enabled, we set a persitent bit. After booting we query the bit and see if the system was reset by the watchdog. This is somewhat similar to what the legacy driver from freescale does. However we use STMP3XXX_RTC_PERSISTENT2 instead of STMP3XXX_RTC_PERSISTENT1. I tried that first, but it seems I can't clear the bit there once it is set. I didn't find any documentation what this register does - only vague hints that it is meant to control the boot ROM. Part of the code from the legacy driver touching this register is still included. Maybe this is stale, but this patch doesn't touch any of it because I don't know what it really does or is meant to do. Signed-off-by: Harald Geyer <harald@ccbib.org> --- Changes since initially posting this patch on 08/04/2015: * fix a spelling error in the commit message * rebase to a recent version drivers/rtc/rtc-stmp3xxx.c | 23 +++++++++++++++++++++++ drivers/watchdog/stmp3xxx_rtc_wdt.c | 34 +++++++++++++++++++++++++++++++++- include/linux/stmp3xxx_rtc_wdt.h | 2 ++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index ca54d03..5d68090 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -30,6 +30,7 @@ #include <linux/of.h> #include <linux/stmp_device.h> #include <linux/stmp3xxx_rtc_wdt.h> +#include <linux/watchdog.h> #define STMP3XXX_RTC_CTRL 0x0 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 @@ -62,6 +63,9 @@ /* missing bitmask in headers */ #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000 +#define STMP3XXX_RTC_PERSISTENT2 0x80 +#define STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE 0x00000001 + struct stmp3xxx_rtc_data { struct rtc_device *rtc; void __iomem *io; @@ -83,6 +87,14 @@ struct stmp3xxx_rtc_data { * registers is atomic. */ +static void stmp3xxx_wdt_clear_bootstatus(struct device *dev) +{ + struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); + + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR + rtc_data->io); +} + static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) { struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); @@ -93,16 +105,22 @@ static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET); + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_SET); } else { writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR); + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR); } } static struct stmp3xxx_wdt_pdata wdt_pdata = { .wdt_set_timeout = stmp3xxx_wdt_set_timeout, + .wdt_clear_bootstatus = stmp3xxx_wdt_clear_bootstatus, + .bootstatus = 0, }; static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) @@ -110,6 +128,8 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) struct platform_device *wdt_pdev = platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); + stmp3xxx_wdt_clear_bootstatus(&rtc_pdev->dev); + if (wdt_pdev) { wdt_pdev->dev.parent = &rtc_pdev->dev; wdt_pdev->dev.platform_data = &wdt_pdata; @@ -357,6 +377,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) return err; } + if (readl(STMP3XXX_RTC_PERSISTENT2 + rtc_data->io) & + STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE) + wdt_pdata.bootstatus |= WDIOF_CARDRESET; stmp3xxx_wdt_register(pdev); return 0; } diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index 3ee6128..7609f78 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -14,6 +14,8 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/stmp3xxx_rtc_wdt.h> +#include <linux/notifier.h> +#include <linux/reboot.h> #define WDOG_TICK_RATE 1000 /* 1 kHz clock */ #define STMP3XXX_DEFAULT_TIMEOUT 19 @@ -50,7 +52,8 @@ static int wdt_set_timeout(struct watchdog_device *wdd, unsigned new_timeout) } static const struct watchdog_info stmp3xxx_wdt_ident = { - .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_CARDRESET, .identity = "STMP3XXX RTC Watchdog", }; @@ -69,14 +72,39 @@ static struct watchdog_device stmp3xxx_wdd = { .status = WATCHDOG_NOWAYOUT_INIT_STATUS, }; +static int wdt_notify_sys(struct notifier_block *nb, unsigned long code, + void *unused) +{ + struct device *dev = watchdog_get_drvdata(&stmp3xxx_wdd); + struct stmp3xxx_wdt_pdata *pdata = dev_get_platdata(dev); + + switch (code) { + case SYS_DOWN: /* keep enabled, system might crash while going down */ + pdata->wdt_clear_bootstatus(dev->parent); + break; + case SYS_HALT: /* allow the system to actually halt */ + case SYS_POWER_OFF: + wdt_stop(&stmp3xxx_wdd); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + static int stmp3xxx_wdt_probe(struct platform_device *pdev) { + struct stmp3xxx_wdt_pdata *pdata = dev_get_platdata(&pdev->dev); int ret; watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); stmp3xxx_wdd.parent = &pdev->dev; + stmp3xxx_wdd.bootstatus = pdata->bootstatus; ret = watchdog_register_device(&stmp3xxx_wdd); if (ret < 0) { @@ -84,6 +112,9 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev) return ret; } + if (register_reboot_notifier(&wdt_notifier)) + dev_warn(&pdev->dev, "cannot register reboot notifier\n"); + dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n", stmp3xxx_wdd.timeout); return 0; @@ -91,6 +122,7 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev) static int stmp3xxx_wdt_remove(struct platform_device *pdev) { + unregister_reboot_notifier(&wdt_notifier); watchdog_unregister_device(&stmp3xxx_wdd); return 0; } diff --git a/include/linux/stmp3xxx_rtc_wdt.h b/include/linux/stmp3xxx_rtc_wdt.h index 1dd12c9..62dd9e6 100644 --- a/include/linux/stmp3xxx_rtc_wdt.h +++ b/include/linux/stmp3xxx_rtc_wdt.h @@ -10,6 +10,8 @@ struct stmp3xxx_wdt_pdata { void (*wdt_set_timeout)(struct device *dev, u32 timeout); + void (*wdt_clear_bootstatus)(struct device *dev); + unsigned int bootstatus; }; #endif /* __LINUX_STMP3XXX_RTC_WDT_H */ -- 1.7.10.4 -- -- You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. --- You received this message because you are subscribed to the Google Groups "rtc-linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout. ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] watchdog: stmp3xxx: Implement GETBOOTSTATUS @ 2015-10-02 20:18 ` Harald Geyer 0 siblings, 0 replies; 8+ messages in thread From: Harald Geyer @ 2015-10-02 20:18 UTC (permalink / raw) To: Alessandro Zummo, Alexandre Belloni, Wim Van Sebroeck Cc: rtc-linux, linux-watchdog, kernel, Harald Geyer When the watchdog is enabled, we set a persitent bit. After booting we query the bit and see if the system was reset by the watchdog. This is somewhat similar to what the legacy driver from freescale does. However we use STMP3XXX_RTC_PERSISTENT2 instead of STMP3XXX_RTC_PERSISTENT1. I tried that first, but it seems I can't clear the bit there once it is set. I didn't find any documentation what this register does - only vague hints that it is meant to control the boot ROM. Part of the code from the legacy driver touching this register is still included. Maybe this is stale, but this patch doesn't touch any of it because I don't know what it really does or is meant to do. Signed-off-by: Harald Geyer <harald@ccbib.org> --- Changes since initially posting this patch on 08/04/2015: * fix a spelling error in the commit message * rebase to a recent version drivers/rtc/rtc-stmp3xxx.c | 23 +++++++++++++++++++++++ drivers/watchdog/stmp3xxx_rtc_wdt.c | 34 +++++++++++++++++++++++++++++++++- include/linux/stmp3xxx_rtc_wdt.h | 2 ++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index ca54d03..5d68090 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -30,6 +30,7 @@ #include <linux/of.h> #include <linux/stmp_device.h> #include <linux/stmp3xxx_rtc_wdt.h> +#include <linux/watchdog.h> #define STMP3XXX_RTC_CTRL 0x0 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 @@ -62,6 +63,9 @@ /* missing bitmask in headers */ #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000 +#define STMP3XXX_RTC_PERSISTENT2 0x80 +#define STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE 0x00000001 + struct stmp3xxx_rtc_data { struct rtc_device *rtc; void __iomem *io; @@ -83,6 +87,14 @@ struct stmp3xxx_rtc_data { * registers is atomic. */ +static void stmp3xxx_wdt_clear_bootstatus(struct device *dev) +{ + struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); + + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR + rtc_data->io); +} + static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) { struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); @@ -93,16 +105,22 @@ static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET); + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_SET); } else { writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR); + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, + rtc_data->io + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR); } } static struct stmp3xxx_wdt_pdata wdt_pdata = { .wdt_set_timeout = stmp3xxx_wdt_set_timeout, + .wdt_clear_bootstatus = stmp3xxx_wdt_clear_bootstatus, + .bootstatus = 0, }; static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) @@ -110,6 +128,8 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) struct platform_device *wdt_pdev = platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); + stmp3xxx_wdt_clear_bootstatus(&rtc_pdev->dev); + if (wdt_pdev) { wdt_pdev->dev.parent = &rtc_pdev->dev; wdt_pdev->dev.platform_data = &wdt_pdata; @@ -357,6 +377,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) return err; } + if (readl(STMP3XXX_RTC_PERSISTENT2 + rtc_data->io) & + STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE) + wdt_pdata.bootstatus |= WDIOF_CARDRESET; stmp3xxx_wdt_register(pdev); return 0; } diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index 3ee6128..7609f78 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -14,6 +14,8 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/stmp3xxx_rtc_wdt.h> +#include <linux/notifier.h> +#include <linux/reboot.h> #define WDOG_TICK_RATE 1000 /* 1 kHz clock */ #define STMP3XXX_DEFAULT_TIMEOUT 19 @@ -50,7 +52,8 @@ static int wdt_set_timeout(struct watchdog_device *wdd, unsigned new_timeout) } static const struct watchdog_info stmp3xxx_wdt_ident = { - .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_CARDRESET, .identity = "STMP3XXX RTC Watchdog", }; @@ -69,14 +72,39 @@ static struct watchdog_device stmp3xxx_wdd = { .status = WATCHDOG_NOWAYOUT_INIT_STATUS, }; +static int wdt_notify_sys(struct notifier_block *nb, unsigned long code, + void *unused) +{ + struct device *dev = watchdog_get_drvdata(&stmp3xxx_wdd); + struct stmp3xxx_wdt_pdata *pdata = dev_get_platdata(dev); + + switch (code) { + case SYS_DOWN: /* keep enabled, system might crash while going down */ + pdata->wdt_clear_bootstatus(dev->parent); + break; + case SYS_HALT: /* allow the system to actually halt */ + case SYS_POWER_OFF: + wdt_stop(&stmp3xxx_wdd); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + static int stmp3xxx_wdt_probe(struct platform_device *pdev) { + struct stmp3xxx_wdt_pdata *pdata = dev_get_platdata(&pdev->dev); int ret; watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); stmp3xxx_wdd.parent = &pdev->dev; + stmp3xxx_wdd.bootstatus = pdata->bootstatus; ret = watchdog_register_device(&stmp3xxx_wdd); if (ret < 0) { @@ -84,6 +112,9 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev) return ret; } + if (register_reboot_notifier(&wdt_notifier)) + dev_warn(&pdev->dev, "cannot register reboot notifier\n"); + dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n", stmp3xxx_wdd.timeout); return 0; @@ -91,6 +122,7 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev) static int stmp3xxx_wdt_remove(struct platform_device *pdev) { + unregister_reboot_notifier(&wdt_notifier); watchdog_unregister_device(&stmp3xxx_wdd); return 0; } diff --git a/include/linux/stmp3xxx_rtc_wdt.h b/include/linux/stmp3xxx_rtc_wdt.h index 1dd12c9..62dd9e6 100644 --- a/include/linux/stmp3xxx_rtc_wdt.h +++ b/include/linux/stmp3xxx_rtc_wdt.h @@ -10,6 +10,8 @@ struct stmp3xxx_wdt_pdata { void (*wdt_set_timeout)(struct device *dev, u32 timeout); + void (*wdt_clear_bootstatus)(struct device *dev); + unsigned int bootstatus; }; #endif /* __LINUX_STMP3XXX_RTC_WDT_H */ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [rtc-linux] Re: [PATCH 2/2] watchdog: stmp3xxx: Implement GETBOOTSTATUS 2015-10-02 20:18 ` Harald Geyer @ 2015-10-03 16:47 ` Alexandre Belloni -1 siblings, 0 replies; 8+ messages in thread From: Alexandre Belloni @ 2015-10-03 16:47 UTC (permalink / raw) To: Harald Geyer Cc: Alessandro Zummo, Wim Van Sebroeck, rtc-linux, linux-watchdog, kernel Hi, On 02/10/2015 at 20:18:02 +0000, Harald Geyer wrote : > +static void stmp3xxx_wdt_clear_bootstatus(struct device *dev) > +{ > + struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); > + > + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, > + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR + rtc_data->io); nitpick: I would put rtc_data->io first here for consistency. Else, this seems fine to me, I can take that patch with the watchdog maintainers ack. -- Alexandre Belloni, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -- -- You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. --- You received this message because you are subscribed to the Google Groups "rtc-linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] watchdog: stmp3xxx: Implement GETBOOTSTATUS @ 2015-10-03 16:47 ` Alexandre Belloni 0 siblings, 0 replies; 8+ messages in thread From: Alexandre Belloni @ 2015-10-03 16:47 UTC (permalink / raw) To: Harald Geyer Cc: Alessandro Zummo, Wim Van Sebroeck, rtc-linux, linux-watchdog, kernel Hi, On 02/10/2015 at 20:18:02 +0000, Harald Geyer wrote : > +static void stmp3xxx_wdt_clear_bootstatus(struct device *dev) > +{ > + struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); > + > + writel(STMP3XXX_RTC_PERSISTENT2_WDT_ACTIVE, > + STMP3XXX_RTC_PERSISTENT2 + STMP_OFFSET_REG_CLR + rtc_data->io); nitpick: I would put rtc_data->io first here for consistency. Else, this seems fine to me, I can take that patch with the watchdog maintainers ack. -- Alexandre Belloni, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com ^ permalink raw reply [flat|nested] 8+ messages in thread
* [rtc-linux] Re: [PATCH 1/2] rtc: stmp3xxx: unify register access macros 2015-10-02 20:18 ` Harald Geyer @ 2015-10-03 15:57 ` Alexandre Belloni -1 siblings, 0 replies; 8+ messages in thread From: Alexandre Belloni @ 2015-10-03 15:57 UTC (permalink / raw) To: Harald Geyer Cc: Alessandro Zummo, Wim Van Sebroeck, rtc-linux, linux-watchdog, kernel On 02/10/2015 at 20:18:01 +0000, Harald Geyer wrote : > Use STMP_OFFSET_REG_(SET|CLR) instead of defining _SET and _CLR for > STMP3XXX_RTC_CTRL and STMP3XXX_RTC_PERSISTENT0 - no functional changes. > > Signed-off-by: Harald Geyer <harald@ccbib.org> > --- > drivers/rtc/rtc-stmp3xxx.c | 27 +++++++++++++-------------- > 1 file changed, 13 insertions(+), 14 deletions(-) > Applied, thanks. -- Alexandre Belloni, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -- -- You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. --- You received this message because you are subscribed to the Google Groups "rtc-linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] rtc: stmp3xxx: unify register access macros @ 2015-10-03 15:57 ` Alexandre Belloni 0 siblings, 0 replies; 8+ messages in thread From: Alexandre Belloni @ 2015-10-03 15:57 UTC (permalink / raw) To: Harald Geyer Cc: Alessandro Zummo, Wim Van Sebroeck, rtc-linux, linux-watchdog, kernel On 02/10/2015 at 20:18:01 +0000, Harald Geyer wrote : > Use STMP_OFFSET_REG_(SET|CLR) instead of defining _SET and _CLR for > STMP3XXX_RTC_CTRL and STMP3XXX_RTC_PERSISTENT0 - no functional changes. > > Signed-off-by: Harald Geyer <harald@ccbib.org> > --- > drivers/rtc/rtc-stmp3xxx.c | 27 +++++++++++++-------------- > 1 file changed, 13 insertions(+), 14 deletions(-) > Applied, thanks. -- Alexandre Belloni, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-10-03 16:47 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-10-02 20:18 [rtc-linux] [PATCH 1/2] rtc: stmp3xxx: unify register access macros Harald Geyer 2015-10-02 20:18 ` Harald Geyer 2015-10-02 20:18 ` [rtc-linux] [PATCH 2/2] watchdog: stmp3xxx: Implement GETBOOTSTATUS Harald Geyer 2015-10-02 20:18 ` Harald Geyer 2015-10-03 16:47 ` [rtc-linux] " Alexandre Belloni 2015-10-03 16:47 ` Alexandre Belloni 2015-10-03 15:57 ` [rtc-linux] Re: [PATCH 1/2] rtc: stmp3xxx: unify register access macros Alexandre Belloni 2015-10-03 15:57 ` Alexandre Belloni
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.