summaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-03-03 10:23:29 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-03-03 10:23:29 -0800
commit68b86a25225d03f134f306caffc46df80906c3f8 (patch)
treed5f6556e07e3fb376199c2ba70153c17d47b7607 /drivers/rtc
parent527c680f7c36ff17d49efc99632232dba3549c51 (diff)
parent41e9f3f71bc7a5d41a2b925cfdc0dc22a77f7d8c (diff)
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: "This contains: - fixes and improvements - devicetree bindings - conversion to watchdog generic framework of the following drivers: - booke_wdt - bcm47xx_wdt.c - at91sam9_wdt - Removal of old STMP3xxx driver - Addition of following new drivers: - new driver for STMP3xxx and i.MX23/28 - Retu watchdog driver" * git://www.linux-watchdog.org/linux-watchdog: (30 commits) watchdog: sp805_wdt depends on ARM watchdog: davinci_wdt: update to devm_* API watchdog: davinci_wdt: use devm managed clk get watchdog: at91rm9200: add DT support watchdog: add timeout-sec property binding watchdog: at91sam9_wdt: Convert to use the watchdog framework watchdog: omap_wdt: Add option nowayout watchdog: core: dt: add support for the timeout-sec dt property watchdog: bcm47xx_wdt.c: add hard timer watchdog: bcm47xx_wdt.c: rename wdt_time to timeout watchdog: bcm47xx_wdt.c: rename ops methods watchdog: bcm47xx_wdt.c: use platform device watchdog: bcm47xx_wdt.c: convert to watchdog core api watchdog: Convert BookE watchdog driver to watchdog infrastructure watchdog: s3c2410_wdt: Use devm_* functions watchdog: remove old STMP3xxx driver watchdog: add new driver for STMP3xxx and i.MX23/28 rtc: stmp3xxx: add wdt-accessor function watchdog: introduce retu_wdt driver watchdog: intel_scu_watchdog: fix Kconfig dependency ...
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index b2a8ed99b2b..98f0d3c3073 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -27,6 +27,8 @@
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/of.h>
+#include <linux/stmp_device.h>
+#include <linux/stmp3xxx_rtc_wdt.h>
#include <mach/common.h>
@@ -36,6 +38,7 @@
#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001
#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002
#define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004
+#define STMP3XXX_RTC_CTRL_WATCHDOGEN 0x00000010
#define STMP3XXX_RTC_STAT 0x10
#define STMP3XXX_RTC_STAT_STALE_SHIFT 16
@@ -45,6 +48,8 @@
#define STMP3XXX_RTC_ALARM 0x40
+#define STMP3XXX_RTC_WATCHDOG 0x50
+
#define STMP3XXX_RTC_PERSISTENT0 0x60
#define STMP3XXX_RTC_PERSISTENT0_SET 0x64
#define STMP3XXX_RTC_PERSISTENT0_CLR 0x68
@@ -52,12 +57,70 @@
#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004
#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080
+#define STMP3XXX_RTC_PERSISTENT1 0x70
+/* missing bitmask in headers */
+#define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000
+
struct stmp3xxx_rtc_data {
struct rtc_device *rtc;
void __iomem *io;
int irq_alarm;
};
+#if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
+/**
+ * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC
+ * @dev: the parent device of the watchdog (= the RTC)
+ * @timeout: the desired value for the timeout register of the watchdog.
+ * 0 disables the watchdog
+ *
+ * The watchdog needs one register and two bits which are in the RTC domain.
+ * To handle the resource conflict, the RTC driver will create another
+ * platform_device for the watchdog driver as a child of the RTC device.
+ * The watchdog driver is passed the below accessor function via platform_data
+ * to configure the watchdog. Locking is not needed because accessing SET/CLR
+ * registers is atomic.
+ */
+
+static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout)
+{
+ struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
+
+ if (timeout) {
+ writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG);
+ writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
+ 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);
+ } 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);
+ }
+}
+
+static struct stmp3xxx_wdt_pdata wdt_pdata = {
+ .wdt_set_timeout = stmp3xxx_wdt_set_timeout,
+};
+
+static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
+{
+ struct platform_device *wdt_pdev =
+ platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id);
+
+ if (wdt_pdev) {
+ wdt_pdev->dev.parent = &rtc_pdev->dev;
+ wdt_pdev->dev.platform_data = &wdt_pdata;
+ platform_device_add(wdt_pdev);
+ }
+}
+#else
+static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
+{
+}
+#endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
+
static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
{
/*
@@ -233,6 +296,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
goto out_irq_alarm;
}
+ stmp3xxx_wdt_register(pdev);
return 0;
out_irq_alarm: