diff options
author | Wolfram Sang <w.sang@pengutronix.de> | 2011-09-27 16:21:37 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2013-03-01 06:40:36 -0500 |
commit | 1a71fb84fda651105e1e194c2d3a3a13a38210a9 (patch) | |
tree | 812379bf5a5f6ffaddd129fd7858e3d2adb66dab | |
parent | 3d3a6d18abc66ba38e554fd5cb5991dfa805cd23 (diff) |
rtc: stmp3xxx: add wdt-accessor function
This RTC also includes a watchdog timer. Provide an accessor function
for setting the watchdog timeout value which will be picked up by a
watchdog driver. Also register the platform_device for the watchdog here
to get the boot-time dependencies right.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 64 | ||||
-rw-r--r-- | include/linux/stmp3xxx_rtc_wdt.h | 15 |
2 files changed, 79 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index b2a8ed99b2bf..98f0d3c30738 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
29 | #include <linux/of.h> | 29 | #include <linux/of.h> |
30 | #include <linux/stmp_device.h> | ||
31 | #include <linux/stmp3xxx_rtc_wdt.h> | ||
30 | 32 | ||
31 | #include <mach/common.h> | 33 | #include <mach/common.h> |
32 | 34 | ||
@@ -36,6 +38,7 @@ | |||
36 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 | 38 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 |
37 | #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 | 39 | #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 |
38 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 | 40 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 |
41 | #define STMP3XXX_RTC_CTRL_WATCHDOGEN 0x00000010 | ||
39 | 42 | ||
40 | #define STMP3XXX_RTC_STAT 0x10 | 43 | #define STMP3XXX_RTC_STAT 0x10 |
41 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 | 44 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 |
@@ -45,6 +48,8 @@ | |||
45 | 48 | ||
46 | #define STMP3XXX_RTC_ALARM 0x40 | 49 | #define STMP3XXX_RTC_ALARM 0x40 |
47 | 50 | ||
51 | #define STMP3XXX_RTC_WATCHDOG 0x50 | ||
52 | |||
48 | #define STMP3XXX_RTC_PERSISTENT0 0x60 | 53 | #define STMP3XXX_RTC_PERSISTENT0 0x60 |
49 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 | 54 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 |
50 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 | 55 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 |
@@ -52,12 +57,70 @@ | |||
52 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 | 57 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 |
53 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 | 58 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 |
54 | 59 | ||
60 | #define STMP3XXX_RTC_PERSISTENT1 0x70 | ||
61 | /* missing bitmask in headers */ | ||
62 | #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000 | ||
63 | |||
55 | struct stmp3xxx_rtc_data { | 64 | struct stmp3xxx_rtc_data { |
56 | struct rtc_device *rtc; | 65 | struct rtc_device *rtc; |
57 | void __iomem *io; | 66 | void __iomem *io; |
58 | int irq_alarm; | 67 | int irq_alarm; |
59 | }; | 68 | }; |
60 | 69 | ||
70 | #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG) | ||
71 | /** | ||
72 | * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC | ||
73 | * @dev: the parent device of the watchdog (= the RTC) | ||
74 | * @timeout: the desired value for the timeout register of the watchdog. | ||
75 | * 0 disables the watchdog | ||
76 | * | ||
77 | * The watchdog needs one register and two bits which are in the RTC domain. | ||
78 | * To handle the resource conflict, the RTC driver will create another | ||
79 | * platform_device for the watchdog driver as a child of the RTC device. | ||
80 | * The watchdog driver is passed the below accessor function via platform_data | ||
81 | * to configure the watchdog. Locking is not needed because accessing SET/CLR | ||
82 | * registers is atomic. | ||
83 | */ | ||
84 | |||
85 | static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) | ||
86 | { | ||
87 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
88 | |||
89 | if (timeout) { | ||
90 | writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG); | ||
91 | writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, | ||
92 | rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); | ||
93 | writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, | ||
94 | rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET); | ||
95 | } else { | ||
96 | writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, | ||
97 | rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); | ||
98 | writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, | ||
99 | rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static struct stmp3xxx_wdt_pdata wdt_pdata = { | ||
104 | .wdt_set_timeout = stmp3xxx_wdt_set_timeout, | ||
105 | }; | ||
106 | |||
107 | static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) | ||
108 | { | ||
109 | struct platform_device *wdt_pdev = | ||
110 | platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); | ||
111 | |||
112 | if (wdt_pdev) { | ||
113 | wdt_pdev->dev.parent = &rtc_pdev->dev; | ||
114 | wdt_pdev->dev.platform_data = &wdt_pdata; | ||
115 | platform_device_add(wdt_pdev); | ||
116 | } | ||
117 | } | ||
118 | #else | ||
119 | static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) | ||
120 | { | ||
121 | } | ||
122 | #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */ | ||
123 | |||
61 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | 124 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) |
62 | { | 125 | { |
63 | /* | 126 | /* |
@@ -233,6 +296,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
233 | goto out_irq_alarm; | 296 | goto out_irq_alarm; |
234 | } | 297 | } |
235 | 298 | ||
299 | stmp3xxx_wdt_register(pdev); | ||
236 | return 0; | 300 | return 0; |
237 | 301 | ||
238 | out_irq_alarm: | 302 | out_irq_alarm: |
diff --git a/include/linux/stmp3xxx_rtc_wdt.h b/include/linux/stmp3xxx_rtc_wdt.h new file mode 100644 index 000000000000..1dd12c96231b --- /dev/null +++ b/include/linux/stmp3xxx_rtc_wdt.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * stmp3xxx_rtc_wdt.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | #ifndef __LINUX_STMP3XXX_RTC_WDT_H | ||
9 | #define __LINUX_STMP3XXX_RTC_WDT_H | ||
10 | |||
11 | struct stmp3xxx_wdt_pdata { | ||
12 | void (*wdt_set_timeout)(struct device *dev, u32 timeout); | ||
13 | }; | ||
14 | |||
15 | #endif /* __LINUX_STMP3XXX_RTC_WDT_H */ | ||