diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-09-21 06:51:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-21 06:51:42 -0400 |
commit | ae82bfd61ca7e57cc2d914add9ab0873e260f2f5 (patch) | |
tree | a7f862ad8b0ae4f2e8953e6aa613eb702b484ecf /drivers/rtc | |
parent | cd74c86bdf705f824d494a2bbda393d1d562b40a (diff) | |
parent | ebc79c4f8da0f92efa968e0328f32334a2ce80cf (diff) |
Merge branch 'linus' into perfcounters/rename
Merge reason: pull in all the latest code before doing the rename.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 19 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-ab3100.c | 281 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1302.c | 69 | ||||
-rw-r--r-- | drivers/rtc/rtc-sh.c | 97 | ||||
-rw-r--r-- | drivers/rtc/rtc-wm831x.c | 523 |
6 files changed, 873 insertions, 118 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 81adbdbd5042..73771b09fbd3 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -518,6 +518,16 @@ config RTC_DRV_V3020 | |||
518 | This driver can also be built as a module. If so, the module | 518 | This driver can also be built as a module. If so, the module |
519 | will be called rtc-v3020. | 519 | will be called rtc-v3020. |
520 | 520 | ||
521 | config RTC_DRV_WM831X | ||
522 | tristate "Wolfson Microelectronics WM831x RTC" | ||
523 | depends on MFD_WM831X | ||
524 | help | ||
525 | If you say yes here you will get support for the RTC subsystem | ||
526 | of the Wolfson Microelectronics WM831X series PMICs. | ||
527 | |||
528 | This driver can also be built as a module. If so, the module | ||
529 | will be called "rtc-wm831x". | ||
530 | |||
521 | config RTC_DRV_WM8350 | 531 | config RTC_DRV_WM8350 |
522 | tristate "Wolfson Microelectronics WM8350 RTC" | 532 | tristate "Wolfson Microelectronics WM8350 RTC" |
523 | depends on MFD_WM8350 | 533 | depends on MFD_WM8350 |
@@ -535,6 +545,15 @@ config RTC_DRV_PCF50633 | |||
535 | If you say yes here you get support for the RTC subsystem of the | 545 | If you say yes here you get support for the RTC subsystem of the |
536 | NXP PCF50633 used in embedded systems. | 546 | NXP PCF50633 used in embedded systems. |
537 | 547 | ||
548 | config RTC_DRV_AB3100 | ||
549 | tristate "ST-Ericsson AB3100 RTC" | ||
550 | depends on AB3100_CORE | ||
551 | default y if AB3100_CORE | ||
552 | help | ||
553 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | ||
554 | support. This chip contains a battery- and capacitor-backed RTC. | ||
555 | |||
556 | |||
538 | comment "on-CPU RTC drivers" | 557 | comment "on-CPU RTC drivers" |
539 | 558 | ||
540 | config RTC_DRV_OMAP | 559 | config RTC_DRV_OMAP |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 3c0f2b2ac927..5e152ffe5058 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -17,6 +17,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
17 | 17 | ||
18 | # Keep the list ordered. | 18 | # Keep the list ordered. |
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | ||
20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 21 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 22 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
22 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
@@ -74,6 +75,7 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | |||
74 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 75 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
75 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 76 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
76 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 77 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
78 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o | ||
77 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 79 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
78 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 80 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
79 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 81 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c new file mode 100644 index 000000000000..4704aac2b5af --- /dev/null +++ b/drivers/rtc/rtc-ab3100.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * RTC clock driver for the AB3100 Analog Baseband Chip | ||
5 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
6 | */ | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/mfd/ab3100.h> | ||
13 | |||
14 | /* Clock rate in Hz */ | ||
15 | #define AB3100_RTC_CLOCK_RATE 32768 | ||
16 | |||
17 | /* | ||
18 | * The AB3100 RTC registers. These are the same for | ||
19 | * AB3000 and AB3100. | ||
20 | * Control register: | ||
21 | * Bit 0: RTC Monitor cleared=0, active=1, if you set it | ||
22 | * to 1 it remains active until RTC power is lost. | ||
23 | * Bit 1: 32 kHz Oscillator, 0 = on, 1 = bypass | ||
24 | * Bit 2: Alarm on, 0 = off, 1 = on | ||
25 | * Bit 3: 32 kHz buffer disabling, 0 = enabled, 1 = disabled | ||
26 | */ | ||
27 | #define AB3100_RTC 0x53 | ||
28 | /* default setting, buffer disabled, alarm on */ | ||
29 | #define RTC_SETTING 0x30 | ||
30 | /* Alarm when AL0-AL3 == TI0-TI3 */ | ||
31 | #define AB3100_AL0 0x56 | ||
32 | #define AB3100_AL1 0x57 | ||
33 | #define AB3100_AL2 0x58 | ||
34 | #define AB3100_AL3 0x59 | ||
35 | /* This 48-bit register that counts up at 32768 Hz */ | ||
36 | #define AB3100_TI0 0x5a | ||
37 | #define AB3100_TI1 0x5b | ||
38 | #define AB3100_TI2 0x5c | ||
39 | #define AB3100_TI3 0x5d | ||
40 | #define AB3100_TI4 0x5e | ||
41 | #define AB3100_TI5 0x5f | ||
42 | |||
43 | /* | ||
44 | * RTC clock functions and device struct declaration | ||
45 | */ | ||
46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
47 | { | ||
48 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
49 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, | ||
50 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; | ||
51 | unsigned char buf[6]; | ||
52 | u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; | ||
53 | int err = 0; | ||
54 | int i; | ||
55 | |||
56 | buf[0] = (fat_time) & 0xFF; | ||
57 | buf[1] = (fat_time >> 8) & 0xFF; | ||
58 | buf[2] = (fat_time >> 16) & 0xFF; | ||
59 | buf[3] = (fat_time >> 24) & 0xFF; | ||
60 | buf[4] = (fat_time >> 32) & 0xFF; | ||
61 | buf[5] = (fat_time >> 40) & 0xFF; | ||
62 | |||
63 | for (i = 0; i < 6; i++) { | ||
64 | err = ab3100_set_register_interruptible(ab3100_data, | ||
65 | regs[i], buf[i]); | ||
66 | if (err) | ||
67 | return err; | ||
68 | } | ||
69 | |||
70 | /* Set the flag to mark that the clock is now set */ | ||
71 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | ||
72 | AB3100_RTC, | ||
73 | 0xFE, 0x01); | ||
74 | |||
75 | } | ||
76 | |||
77 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
78 | { | ||
79 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
80 | unsigned long time; | ||
81 | u8 rtcval; | ||
82 | int err; | ||
83 | |||
84 | err = ab3100_get_register_interruptible(ab3100_data, | ||
85 | AB3100_RTC, &rtcval); | ||
86 | if (err) | ||
87 | return err; | ||
88 | |||
89 | if (!(rtcval & 0x01)) { | ||
90 | dev_info(dev, "clock not set (lost power)"); | ||
91 | return -EINVAL; | ||
92 | } else { | ||
93 | u64 fat_time; | ||
94 | u8 buf[6]; | ||
95 | |||
96 | /* Read out time registers */ | ||
97 | err = ab3100_get_register_page_interruptible(ab3100_data, | ||
98 | AB3100_TI0, | ||
99 | buf, 6); | ||
100 | if (err != 0) | ||
101 | return err; | ||
102 | |||
103 | fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) | | ||
104 | ((u64) buf[3] << 24) | ((u64) buf[2] << 16) | | ||
105 | ((u64) buf[1] << 8) | (u64) buf[0]; | ||
106 | time = (unsigned long) (fat_time / | ||
107 | (u64) (AB3100_RTC_CLOCK_RATE * 2)); | ||
108 | } | ||
109 | |||
110 | rtc_time_to_tm(time, tm); | ||
111 | |||
112 | return rtc_valid_tm(tm); | ||
113 | } | ||
114 | |||
115 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
116 | { | ||
117 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
118 | unsigned long time; | ||
119 | u64 fat_time; | ||
120 | u8 buf[6]; | ||
121 | u8 rtcval; | ||
122 | int err; | ||
123 | |||
124 | /* Figure out if alarm is enabled or not */ | ||
125 | err = ab3100_get_register_interruptible(ab3100_data, | ||
126 | AB3100_RTC, &rtcval); | ||
127 | if (err) | ||
128 | return err; | ||
129 | if (rtcval & 0x04) | ||
130 | alarm->enabled = 1; | ||
131 | else | ||
132 | alarm->enabled = 0; | ||
133 | /* No idea how this could be represented */ | ||
134 | alarm->pending = 0; | ||
135 | /* Read out alarm registers, only 4 bytes */ | ||
136 | err = ab3100_get_register_page_interruptible(ab3100_data, | ||
137 | AB3100_AL0, buf, 4); | ||
138 | if (err) | ||
139 | return err; | ||
140 | fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) | | ||
141 | ((u64) buf[1] << 24) | ((u64) buf[0] << 16); | ||
142 | time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2)); | ||
143 | |||
144 | rtc_time_to_tm(time, &alarm->time); | ||
145 | |||
146 | return rtc_valid_tm(&alarm->time); | ||
147 | } | ||
148 | |||
149 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
150 | { | ||
151 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
152 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; | ||
153 | unsigned char buf[4]; | ||
154 | unsigned long secs; | ||
155 | u64 fat_time; | ||
156 | int err; | ||
157 | int i; | ||
158 | |||
159 | rtc_tm_to_time(&alarm->time, &secs); | ||
160 | fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; | ||
161 | buf[0] = (fat_time >> 16) & 0xFF; | ||
162 | buf[1] = (fat_time >> 24) & 0xFF; | ||
163 | buf[2] = (fat_time >> 32) & 0xFF; | ||
164 | buf[3] = (fat_time >> 40) & 0xFF; | ||
165 | |||
166 | /* Set the alarm */ | ||
167 | for (i = 0; i < 4; i++) { | ||
168 | err = ab3100_set_register_interruptible(ab3100_data, | ||
169 | regs[i], buf[i]); | ||
170 | if (err) | ||
171 | return err; | ||
172 | } | ||
173 | /* Then enable the alarm */ | ||
174 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | ||
175 | AB3100_RTC, ~(1 << 2), | ||
176 | alarm->enabled << 2); | ||
177 | } | ||
178 | |||
179 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
180 | { | ||
181 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
182 | |||
183 | /* | ||
184 | * It's not possible to enable/disable the alarm IRQ for this RTC. | ||
185 | * It does not actually trigger any IRQ: instead its only function is | ||
186 | * to power up the system, if it wasn't on. This will manifest as | ||
187 | * a "power up cause" in the AB3100 power driver (battery charging etc) | ||
188 | * and need to be handled there instead. | ||
189 | */ | ||
190 | if (enabled) | ||
191 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | ||
192 | AB3100_RTC, ~(1 << 2), | ||
193 | 1 << 2); | ||
194 | else | ||
195 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | ||
196 | AB3100_RTC, ~(1 << 2), | ||
197 | 0); | ||
198 | } | ||
199 | |||
200 | static const struct rtc_class_ops ab3100_rtc_ops = { | ||
201 | .read_time = ab3100_rtc_read_time, | ||
202 | .set_mmss = ab3100_rtc_set_mmss, | ||
203 | .read_alarm = ab3100_rtc_read_alarm, | ||
204 | .set_alarm = ab3100_rtc_set_alarm, | ||
205 | .alarm_irq_enable = ab3100_rtc_irq_enable, | ||
206 | }; | ||
207 | |||
208 | static int __init ab3100_rtc_probe(struct platform_device *pdev) | ||
209 | { | ||
210 | int err; | ||
211 | u8 regval; | ||
212 | struct rtc_device *rtc; | ||
213 | struct ab3100 *ab3100_data = platform_get_drvdata(pdev); | ||
214 | |||
215 | /* The first RTC register needs special treatment */ | ||
216 | err = ab3100_get_register_interruptible(ab3100_data, | ||
217 | AB3100_RTC, ®val); | ||
218 | if (err) { | ||
219 | dev_err(&pdev->dev, "unable to read RTC register\n"); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | |||
223 | if ((regval & 0xFE) != RTC_SETTING) { | ||
224 | dev_warn(&pdev->dev, "not default value in RTC reg 0x%x\n", | ||
225 | regval); | ||
226 | } | ||
227 | |||
228 | if ((regval & 1) == 0) { | ||
229 | /* | ||
230 | * Set bit to detect power loss. | ||
231 | * This bit remains until RTC power is lost. | ||
232 | */ | ||
233 | regval = 1 | RTC_SETTING; | ||
234 | err = ab3100_set_register_interruptible(ab3100_data, | ||
235 | AB3100_RTC, regval); | ||
236 | /* Ignore any error on this write */ | ||
237 | } | ||
238 | |||
239 | rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops, | ||
240 | THIS_MODULE); | ||
241 | if (IS_ERR(rtc)) { | ||
242 | err = PTR_ERR(rtc); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int __exit ab3100_rtc_remove(struct platform_device *pdev) | ||
250 | { | ||
251 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
252 | |||
253 | rtc_device_unregister(rtc); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static struct platform_driver ab3100_rtc_driver = { | ||
258 | .driver = { | ||
259 | .name = "ab3100-rtc", | ||
260 | .owner = THIS_MODULE, | ||
261 | }, | ||
262 | .remove = __exit_p(ab3100_rtc_remove), | ||
263 | }; | ||
264 | |||
265 | static int __init ab3100_rtc_init(void) | ||
266 | { | ||
267 | return platform_driver_probe(&ab3100_rtc_driver, | ||
268 | ab3100_rtc_probe); | ||
269 | } | ||
270 | |||
271 | static void __exit ab3100_rtc_exit(void) | ||
272 | { | ||
273 | platform_driver_unregister(&ab3100_rtc_driver); | ||
274 | } | ||
275 | |||
276 | module_init(ab3100_rtc_init); | ||
277 | module_exit(ab3100_rtc_exit); | ||
278 | |||
279 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
280 | MODULE_DESCRIPTION("AB3100 RTC Driver"); | ||
281 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 184556620778..d490628b64da 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -1,26 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * Dallas DS1302 RTC Support | 2 | * Dallas DS1302 RTC Support |
3 | * | 3 | * |
4 | * Copyright (C) 2002 David McCullough | 4 | * Copyright (C) 2002 David McCullough |
5 | * Copyright (C) 2003 - 2007 Paul Mundt | 5 | * Copyright (C) 2003 - 2007 Paul Mundt |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License version 2. See the file "COPYING" in the main directory of | 8 | * License version 2. See the file "COPYING" in the main directory of |
9 | * this archive for more details. | 9 | * this archive for more details. |
10 | */ | 10 | */ |
11 | |||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
15 | #include <linux/time.h> | ||
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/io.h> | 17 | #include <linux/io.h> |
19 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
20 | #include <asm/rtc.h> | 19 | #include <asm/rtc.h> |
21 | 20 | ||
22 | #define DRV_NAME "rtc-ds1302" | 21 | #define DRV_NAME "rtc-ds1302" |
23 | #define DRV_VERSION "0.1.0" | 22 | #define DRV_VERSION "0.1.1" |
24 | 23 | ||
25 | #define RTC_CMD_READ 0x81 /* Read command */ | 24 | #define RTC_CMD_READ 0x81 /* Read command */ |
26 | #define RTC_CMD_WRITE 0x80 /* Write command */ | 25 | #define RTC_CMD_WRITE 0x80 /* Write command */ |
@@ -47,11 +46,6 @@ | |||
47 | #error "Add support for your platform" | 46 | #error "Add support for your platform" |
48 | #endif | 47 | #endif |
49 | 48 | ||
50 | struct ds1302_rtc { | ||
51 | struct rtc_device *rtc_dev; | ||
52 | spinlock_t lock; | ||
53 | }; | ||
54 | |||
55 | static void ds1302_sendbits(unsigned int val) | 49 | static void ds1302_sendbits(unsigned int val) |
56 | { | 50 | { |
57 | int i; | 51 | int i; |
@@ -103,10 +97,6 @@ static void ds1302_writebyte(unsigned int addr, unsigned int val) | |||
103 | 97 | ||
104 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | 98 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) |
105 | { | 99 | { |
106 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
107 | |||
108 | spin_lock_irq(&rtc->lock); | ||
109 | |||
110 | tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); | 100 | tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); |
111 | tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); | 101 | tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); |
112 | tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); | 102 | tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); |
@@ -118,26 +108,17 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
118 | if (tm->tm_year < 70) | 108 | if (tm->tm_year < 70) |
119 | tm->tm_year += 100; | 109 | tm->tm_year += 100; |
120 | 110 | ||
121 | spin_unlock_irq(&rtc->lock); | ||
122 | |||
123 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 111 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " |
124 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 112 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
125 | __func__, | 113 | __func__, |
126 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 114 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
127 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); | 115 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); |
128 | 116 | ||
129 | if (rtc_valid_tm(tm) < 0) | 117 | return rtc_valid_tm(tm); |
130 | dev_err(dev, "invalid date\n"); | ||
131 | |||
132 | return 0; | ||
133 | } | 118 | } |
134 | 119 | ||
135 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | 120 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) |
136 | { | 121 | { |
137 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
138 | |||
139 | spin_lock_irq(&rtc->lock); | ||
140 | |||
141 | /* Stop RTC */ | 122 | /* Stop RTC */ |
142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | 123 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); |
143 | 124 | ||
@@ -152,8 +133,6 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
152 | /* Start RTC */ | 133 | /* Start RTC */ |
153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | 134 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); |
154 | 135 | ||
155 | spin_unlock_irq(&rtc->lock); | ||
156 | |||
157 | return 0; | 136 | return 0; |
158 | } | 137 | } |
159 | 138 | ||
@@ -170,9 +149,7 @@ static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
170 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | 149 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) |
171 | return -EFAULT; | 150 | return -EFAULT; |
172 | 151 | ||
173 | spin_lock_irq(&rtc->lock); | ||
174 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); | 152 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); |
175 | spin_unlock_irq(&rtc->lock); | ||
176 | return 0; | 153 | return 0; |
177 | } | 154 | } |
178 | #endif | 155 | #endif |
@@ -187,10 +164,9 @@ static struct rtc_class_ops ds1302_rtc_ops = { | |||
187 | .ioctl = ds1302_rtc_ioctl, | 164 | .ioctl = ds1302_rtc_ioctl, |
188 | }; | 165 | }; |
189 | 166 | ||
190 | static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | 167 | static int __init ds1302_rtc_probe(struct platform_device *pdev) |
191 | { | 168 | { |
192 | struct ds1302_rtc *rtc; | 169 | struct rtc_device *rtc; |
193 | int ret; | ||
194 | 170 | ||
195 | /* Reset */ | 171 | /* Reset */ |
196 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 172 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); |
@@ -200,37 +176,23 @@ static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | |||
200 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | 176 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) |
201 | return -ENODEV; | 177 | return -ENODEV; |
202 | 178 | ||
203 | rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL); | 179 | rtc = rtc_device_register("ds1302", &pdev->dev, |
204 | if (unlikely(!rtc)) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | spin_lock_init(&rtc->lock); | ||
208 | rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev, | ||
209 | &ds1302_rtc_ops, THIS_MODULE); | 180 | &ds1302_rtc_ops, THIS_MODULE); |
210 | if (IS_ERR(rtc->rtc_dev)) { | 181 | if (IS_ERR(rtc)) |
211 | ret = PTR_ERR(rtc->rtc_dev); | 182 | return PTR_ERR(rtc); |
212 | goto out; | ||
213 | } | ||
214 | 183 | ||
215 | platform_set_drvdata(pdev, rtc); | 184 | platform_set_drvdata(pdev, rtc); |
216 | 185 | ||
217 | return 0; | 186 | return 0; |
218 | out: | ||
219 | kfree(rtc); | ||
220 | return ret; | ||
221 | } | 187 | } |
222 | 188 | ||
223 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) | 189 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) |
224 | { | 190 | { |
225 | struct ds1302_rtc *rtc = platform_get_drvdata(pdev); | 191 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
226 | |||
227 | if (likely(rtc->rtc_dev)) | ||
228 | rtc_device_unregister(rtc->rtc_dev); | ||
229 | 192 | ||
193 | rtc_device_unregister(rtc); | ||
230 | platform_set_drvdata(pdev, NULL); | 194 | platform_set_drvdata(pdev, NULL); |
231 | 195 | ||
232 | kfree(rtc); | ||
233 | |||
234 | return 0; | 196 | return 0; |
235 | } | 197 | } |
236 | 198 | ||
@@ -239,13 +201,12 @@ static struct platform_driver ds1302_platform_driver = { | |||
239 | .name = DRV_NAME, | 201 | .name = DRV_NAME, |
240 | .owner = THIS_MODULE, | 202 | .owner = THIS_MODULE, |
241 | }, | 203 | }, |
242 | .probe = ds1302_rtc_probe, | 204 | .remove = __exit_p(ds1302_rtc_remove), |
243 | .remove = __devexit_p(ds1302_rtc_remove), | ||
244 | }; | 205 | }; |
245 | 206 | ||
246 | static int __init ds1302_rtc_init(void) | 207 | static int __init ds1302_rtc_init(void) |
247 | { | 208 | { |
248 | return platform_driver_register(&ds1302_platform_driver); | 209 | return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe); |
249 | } | 210 | } |
250 | 211 | ||
251 | static void __exit ds1302_rtc_exit(void) | 212 | static void __exit ds1302_rtc_exit(void) |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index d7310adb7152..e6ed5404bca0 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <asm/rtc.h> | 29 | #include <asm/rtc.h> |
30 | 30 | ||
31 | #define DRV_NAME "sh-rtc" | 31 | #define DRV_NAME "sh-rtc" |
32 | #define DRV_VERSION "0.2.2" | 32 | #define DRV_VERSION "0.2.3" |
33 | 33 | ||
34 | #define RTC_REG(r) ((r) * rtc_reg_size) | 34 | #define RTC_REG(r) ((r) * rtc_reg_size) |
35 | 35 | ||
@@ -215,7 +215,7 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id) | |||
215 | return IRQ_RETVAL(ret); | 215 | return IRQ_RETVAL(ret); |
216 | } | 216 | } |
217 | 217 | ||
218 | static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | 218 | static int sh_rtc_irq_set_state(struct device *dev, int enable) |
219 | { | 219 | { |
220 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 220 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
221 | unsigned int tmp; | 221 | unsigned int tmp; |
@@ -225,17 +225,22 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | |||
225 | tmp = readb(rtc->regbase + RCR2); | 225 | tmp = readb(rtc->regbase + RCR2); |
226 | 226 | ||
227 | if (enable) { | 227 | if (enable) { |
228 | rtc->periodic_freq |= PF_KOU; | ||
228 | tmp &= ~RCR2_PEF; /* Clear PES bit */ | 229 | tmp &= ~RCR2_PEF; /* Clear PES bit */ |
229 | tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */ | 230 | tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */ |
230 | } else | 231 | } else { |
232 | rtc->periodic_freq &= ~PF_KOU; | ||
231 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); | 233 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); |
234 | } | ||
232 | 235 | ||
233 | writeb(tmp, rtc->regbase + RCR2); | 236 | writeb(tmp, rtc->regbase + RCR2); |
234 | 237 | ||
235 | spin_unlock_irq(&rtc->lock); | 238 | spin_unlock_irq(&rtc->lock); |
239 | |||
240 | return 0; | ||
236 | } | 241 | } |
237 | 242 | ||
238 | static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq) | 243 | static int sh_rtc_irq_set_freq(struct device *dev, int freq) |
239 | { | 244 | { |
240 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 245 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
241 | int tmp, ret = 0; | 246 | int tmp, ret = 0; |
@@ -278,10 +283,8 @@ static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq) | |||
278 | ret = -ENOTSUPP; | 283 | ret = -ENOTSUPP; |
279 | } | 284 | } |
280 | 285 | ||
281 | if (ret == 0) { | 286 | if (ret == 0) |
282 | rtc->periodic_freq |= tmp; | 287 | rtc->periodic_freq |= tmp; |
283 | rtc->rtc_dev->irq_freq = freq; | ||
284 | } | ||
285 | 288 | ||
286 | spin_unlock_irq(&rtc->lock); | 289 | spin_unlock_irq(&rtc->lock); |
287 | return ret; | 290 | return ret; |
@@ -346,10 +349,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
346 | unsigned int ret = 0; | 349 | unsigned int ret = 0; |
347 | 350 | ||
348 | switch (cmd) { | 351 | switch (cmd) { |
349 | case RTC_PIE_OFF: | ||
350 | case RTC_PIE_ON: | ||
351 | sh_rtc_setpie(dev, cmd == RTC_PIE_ON); | ||
352 | break; | ||
353 | case RTC_AIE_OFF: | 352 | case RTC_AIE_OFF: |
354 | case RTC_AIE_ON: | 353 | case RTC_AIE_ON: |
355 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); | 354 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); |
@@ -362,13 +361,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
362 | rtc->periodic_freq |= PF_OXS; | 361 | rtc->periodic_freq |= PF_OXS; |
363 | sh_rtc_setcie(dev, 1); | 362 | sh_rtc_setcie(dev, 1); |
364 | break; | 363 | break; |
365 | case RTC_IRQP_READ: | ||
366 | ret = put_user(rtc->rtc_dev->irq_freq, | ||
367 | (unsigned long __user *)arg); | ||
368 | break; | ||
369 | case RTC_IRQP_SET: | ||
370 | ret = sh_rtc_setfreq(dev, arg); | ||
371 | break; | ||
372 | default: | 364 | default: |
373 | ret = -ENOIOCTLCMD; | 365 | ret = -ENOIOCTLCMD; |
374 | } | 366 | } |
@@ -602,28 +594,6 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
602 | return 0; | 594 | return 0; |
603 | } | 595 | } |
604 | 596 | ||
605 | static int sh_rtc_irq_set_state(struct device *dev, int enabled) | ||
606 | { | ||
607 | struct platform_device *pdev = to_platform_device(dev); | ||
608 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
609 | |||
610 | if (enabled) { | ||
611 | rtc->periodic_freq |= PF_KOU; | ||
612 | return sh_rtc_ioctl(dev, RTC_PIE_ON, 0); | ||
613 | } else { | ||
614 | rtc->periodic_freq &= ~PF_KOU; | ||
615 | return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static int sh_rtc_irq_set_freq(struct device *dev, int freq) | ||
620 | { | ||
621 | if (!is_power_of_2(freq)) | ||
622 | return -EINVAL; | ||
623 | |||
624 | return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq); | ||
625 | } | ||
626 | |||
627 | static struct rtc_class_ops sh_rtc_ops = { | 597 | static struct rtc_class_ops sh_rtc_ops = { |
628 | .ioctl = sh_rtc_ioctl, | 598 | .ioctl = sh_rtc_ioctl, |
629 | .read_time = sh_rtc_read_time, | 599 | .read_time = sh_rtc_read_time, |
@@ -635,7 +605,7 @@ static struct rtc_class_ops sh_rtc_ops = { | |||
635 | .proc = sh_rtc_proc, | 605 | .proc = sh_rtc_proc, |
636 | }; | 606 | }; |
637 | 607 | ||
638 | static int __devinit sh_rtc_probe(struct platform_device *pdev) | 608 | static int __init sh_rtc_probe(struct platform_device *pdev) |
639 | { | 609 | { |
640 | struct sh_rtc *rtc; | 610 | struct sh_rtc *rtc; |
641 | struct resource *res; | 611 | struct resource *res; |
@@ -702,13 +672,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
702 | 672 | ||
703 | clk_enable(rtc->clk); | 673 | clk_enable(rtc->clk); |
704 | 674 | ||
705 | rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, | ||
706 | &sh_rtc_ops, THIS_MODULE); | ||
707 | if (IS_ERR(rtc->rtc_dev)) { | ||
708 | ret = PTR_ERR(rtc->rtc_dev); | ||
709 | goto err_unmap; | ||
710 | } | ||
711 | |||
712 | rtc->capabilities = RTC_DEF_CAPABILITIES; | 675 | rtc->capabilities = RTC_DEF_CAPABILITIES; |
713 | if (pdev->dev.platform_data) { | 676 | if (pdev->dev.platform_data) { |
714 | struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data; | 677 | struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data; |
@@ -720,10 +683,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
720 | rtc->capabilities |= pinfo->capabilities; | 683 | rtc->capabilities |= pinfo->capabilities; |
721 | } | 684 | } |
722 | 685 | ||
723 | rtc->rtc_dev->max_user_freq = 256; | ||
724 | |||
725 | platform_set_drvdata(pdev, rtc); | ||
726 | |||
727 | if (rtc->carry_irq <= 0) { | 686 | if (rtc->carry_irq <= 0) { |
728 | /* register shared periodic/carry/alarm irq */ | 687 | /* register shared periodic/carry/alarm irq */ |
729 | ret = request_irq(rtc->periodic_irq, sh_rtc_shared, | 688 | ret = request_irq(rtc->periodic_irq, sh_rtc_shared, |
@@ -767,13 +726,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
767 | } | 726 | } |
768 | } | 727 | } |
769 | 728 | ||
729 | platform_set_drvdata(pdev, rtc); | ||
730 | |||
770 | /* everything disabled by default */ | 731 | /* everything disabled by default */ |
771 | rtc->periodic_freq = 0; | 732 | sh_rtc_irq_set_freq(&pdev->dev, 0); |
772 | rtc->rtc_dev->irq_freq = 0; | 733 | sh_rtc_irq_set_state(&pdev->dev, 0); |
773 | sh_rtc_setpie(&pdev->dev, 0); | ||
774 | sh_rtc_setaie(&pdev->dev, 0); | 734 | sh_rtc_setaie(&pdev->dev, 0); |
775 | sh_rtc_setcie(&pdev->dev, 0); | 735 | sh_rtc_setcie(&pdev->dev, 0); |
776 | 736 | ||
737 | rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, | ||
738 | &sh_rtc_ops, THIS_MODULE); | ||
739 | if (IS_ERR(rtc->rtc_dev)) { | ||
740 | ret = PTR_ERR(rtc->rtc_dev); | ||
741 | free_irq(rtc->periodic_irq, rtc); | ||
742 | free_irq(rtc->carry_irq, rtc); | ||
743 | free_irq(rtc->alarm_irq, rtc); | ||
744 | goto err_unmap; | ||
745 | } | ||
746 | |||
747 | rtc->rtc_dev->max_user_freq = 256; | ||
748 | |||
777 | /* reset rtc to epoch 0 if time is invalid */ | 749 | /* reset rtc to epoch 0 if time is invalid */ |
778 | if (rtc_read_time(rtc->rtc_dev, &r) < 0) { | 750 | if (rtc_read_time(rtc->rtc_dev, &r) < 0) { |
779 | rtc_time_to_tm(0, &r); | 751 | rtc_time_to_tm(0, &r); |
@@ -795,14 +767,13 @@ err_badres: | |||
795 | return ret; | 767 | return ret; |
796 | } | 768 | } |
797 | 769 | ||
798 | static int __devexit sh_rtc_remove(struct platform_device *pdev) | 770 | static int __exit sh_rtc_remove(struct platform_device *pdev) |
799 | { | 771 | { |
800 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 772 | struct sh_rtc *rtc = platform_get_drvdata(pdev); |
801 | 773 | ||
802 | if (likely(rtc->rtc_dev)) | 774 | rtc_device_unregister(rtc->rtc_dev); |
803 | rtc_device_unregister(rtc->rtc_dev); | 775 | sh_rtc_irq_set_state(&pdev->dev, 0); |
804 | 776 | ||
805 | sh_rtc_setpie(&pdev->dev, 0); | ||
806 | sh_rtc_setaie(&pdev->dev, 0); | 777 | sh_rtc_setaie(&pdev->dev, 0); |
807 | sh_rtc_setcie(&pdev->dev, 0); | 778 | sh_rtc_setcie(&pdev->dev, 0); |
808 | 779 | ||
@@ -813,9 +784,8 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) | |||
813 | free_irq(rtc->alarm_irq, rtc); | 784 | free_irq(rtc->alarm_irq, rtc); |
814 | } | 785 | } |
815 | 786 | ||
816 | release_resource(rtc->res); | ||
817 | |||
818 | iounmap(rtc->regbase); | 787 | iounmap(rtc->regbase); |
788 | release_resource(rtc->res); | ||
819 | 789 | ||
820 | clk_disable(rtc->clk); | 790 | clk_disable(rtc->clk); |
821 | clk_put(rtc->clk); | 791 | clk_put(rtc->clk); |
@@ -867,13 +837,12 @@ static struct platform_driver sh_rtc_platform_driver = { | |||
867 | .owner = THIS_MODULE, | 837 | .owner = THIS_MODULE, |
868 | .pm = &sh_rtc_dev_pm_ops, | 838 | .pm = &sh_rtc_dev_pm_ops, |
869 | }, | 839 | }, |
870 | .probe = sh_rtc_probe, | 840 | .remove = __exit_p(sh_rtc_remove), |
871 | .remove = __devexit_p(sh_rtc_remove), | ||
872 | }; | 841 | }; |
873 | 842 | ||
874 | static int __init sh_rtc_init(void) | 843 | static int __init sh_rtc_init(void) |
875 | { | 844 | { |
876 | return platform_driver_register(&sh_rtc_platform_driver); | 845 | return platform_driver_probe(&sh_rtc_platform_driver, sh_rtc_probe); |
877 | } | 846 | } |
878 | 847 | ||
879 | static void __exit sh_rtc_exit(void) | 848 | static void __exit sh_rtc_exit(void) |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c new file mode 100644 index 000000000000..79795cdf6ed8 --- /dev/null +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -0,0 +1,523 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Wolfson Microelectronics WM831x | ||
3 | * | ||
4 | * Copyright (C) 2009 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/time.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/bcd.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/ioctl.h> | ||
22 | #include <linux/completion.h> | ||
23 | #include <linux/mfd/wm831x/core.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | |||
28 | /* | ||
29 | * R16416 (0x4020) - RTC Write Counter | ||
30 | */ | ||
31 | #define WM831X_RTC_WR_CNT_MASK 0xFFFF /* RTC_WR_CNT - [15:0] */ | ||
32 | #define WM831X_RTC_WR_CNT_SHIFT 0 /* RTC_WR_CNT - [15:0] */ | ||
33 | #define WM831X_RTC_WR_CNT_WIDTH 16 /* RTC_WR_CNT - [15:0] */ | ||
34 | |||
35 | /* | ||
36 | * R16417 (0x4021) - RTC Time 1 | ||
37 | */ | ||
38 | #define WM831X_RTC_TIME_MASK 0xFFFF /* RTC_TIME - [15:0] */ | ||
39 | #define WM831X_RTC_TIME_SHIFT 0 /* RTC_TIME - [15:0] */ | ||
40 | #define WM831X_RTC_TIME_WIDTH 16 /* RTC_TIME - [15:0] */ | ||
41 | |||
42 | /* | ||
43 | * R16418 (0x4022) - RTC Time 2 | ||
44 | */ | ||
45 | #define WM831X_RTC_TIME_MASK 0xFFFF /* RTC_TIME - [15:0] */ | ||
46 | #define WM831X_RTC_TIME_SHIFT 0 /* RTC_TIME - [15:0] */ | ||
47 | #define WM831X_RTC_TIME_WIDTH 16 /* RTC_TIME - [15:0] */ | ||
48 | |||
49 | /* | ||
50 | * R16419 (0x4023) - RTC Alarm 1 | ||
51 | */ | ||
52 | #define WM831X_RTC_ALM_MASK 0xFFFF /* RTC_ALM - [15:0] */ | ||
53 | #define WM831X_RTC_ALM_SHIFT 0 /* RTC_ALM - [15:0] */ | ||
54 | #define WM831X_RTC_ALM_WIDTH 16 /* RTC_ALM - [15:0] */ | ||
55 | |||
56 | /* | ||
57 | * R16420 (0x4024) - RTC Alarm 2 | ||
58 | */ | ||
59 | #define WM831X_RTC_ALM_MASK 0xFFFF /* RTC_ALM - [15:0] */ | ||
60 | #define WM831X_RTC_ALM_SHIFT 0 /* RTC_ALM - [15:0] */ | ||
61 | #define WM831X_RTC_ALM_WIDTH 16 /* RTC_ALM - [15:0] */ | ||
62 | |||
63 | /* | ||
64 | * R16421 (0x4025) - RTC Control | ||
65 | */ | ||
66 | #define WM831X_RTC_VALID 0x8000 /* RTC_VALID */ | ||
67 | #define WM831X_RTC_VALID_MASK 0x8000 /* RTC_VALID */ | ||
68 | #define WM831X_RTC_VALID_SHIFT 15 /* RTC_VALID */ | ||
69 | #define WM831X_RTC_VALID_WIDTH 1 /* RTC_VALID */ | ||
70 | #define WM831X_RTC_SYNC_BUSY 0x4000 /* RTC_SYNC_BUSY */ | ||
71 | #define WM831X_RTC_SYNC_BUSY_MASK 0x4000 /* RTC_SYNC_BUSY */ | ||
72 | #define WM831X_RTC_SYNC_BUSY_SHIFT 14 /* RTC_SYNC_BUSY */ | ||
73 | #define WM831X_RTC_SYNC_BUSY_WIDTH 1 /* RTC_SYNC_BUSY */ | ||
74 | #define WM831X_RTC_ALM_ENA 0x0400 /* RTC_ALM_ENA */ | ||
75 | #define WM831X_RTC_ALM_ENA_MASK 0x0400 /* RTC_ALM_ENA */ | ||
76 | #define WM831X_RTC_ALM_ENA_SHIFT 10 /* RTC_ALM_ENA */ | ||
77 | #define WM831X_RTC_ALM_ENA_WIDTH 1 /* RTC_ALM_ENA */ | ||
78 | #define WM831X_RTC_PINT_FREQ_MASK 0x0070 /* RTC_PINT_FREQ - [6:4] */ | ||
79 | #define WM831X_RTC_PINT_FREQ_SHIFT 4 /* RTC_PINT_FREQ - [6:4] */ | ||
80 | #define WM831X_RTC_PINT_FREQ_WIDTH 3 /* RTC_PINT_FREQ - [6:4] */ | ||
81 | |||
82 | /* | ||
83 | * R16422 (0x4026) - RTC Trim | ||
84 | */ | ||
85 | #define WM831X_RTC_TRIM_MASK 0x03FF /* RTC_TRIM - [9:0] */ | ||
86 | #define WM831X_RTC_TRIM_SHIFT 0 /* RTC_TRIM - [9:0] */ | ||
87 | #define WM831X_RTC_TRIM_WIDTH 10 /* RTC_TRIM - [9:0] */ | ||
88 | |||
89 | #define WM831X_SET_TIME_RETRIES 5 | ||
90 | #define WM831X_GET_TIME_RETRIES 5 | ||
91 | |||
92 | struct wm831x_rtc { | ||
93 | struct wm831x *wm831x; | ||
94 | struct rtc_device *rtc; | ||
95 | unsigned int alarm_enabled:1; | ||
96 | }; | ||
97 | |||
98 | /* | ||
99 | * Read current time and date in RTC | ||
100 | */ | ||
101 | static int wm831x_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
102 | { | ||
103 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
104 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
105 | u16 time1[2], time2[2]; | ||
106 | int ret; | ||
107 | int count = 0; | ||
108 | |||
109 | /* Has the RTC been programmed? */ | ||
110 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
111 | if (ret < 0) { | ||
112 | dev_err(dev, "Failed to read RTC control: %d\n", ret); | ||
113 | return ret; | ||
114 | } | ||
115 | if (!(ret & WM831X_RTC_VALID)) { | ||
116 | dev_dbg(dev, "RTC not yet configured\n"); | ||
117 | return -EINVAL; | ||
118 | } | ||
119 | |||
120 | /* Read twice to make sure we don't read a corrupt, partially | ||
121 | * incremented, value. | ||
122 | */ | ||
123 | do { | ||
124 | ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1, | ||
125 | 2, time1); | ||
126 | if (ret != 0) | ||
127 | continue; | ||
128 | |||
129 | ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1, | ||
130 | 2, time2); | ||
131 | if (ret != 0) | ||
132 | continue; | ||
133 | |||
134 | if (memcmp(time1, time2, sizeof(time1)) == 0) { | ||
135 | u32 time = (time1[0] << 16) | time1[1]; | ||
136 | |||
137 | rtc_time_to_tm(time, tm); | ||
138 | return rtc_valid_tm(tm); | ||
139 | } | ||
140 | |||
141 | } while (++count < WM831X_GET_TIME_RETRIES); | ||
142 | |||
143 | dev_err(dev, "Timed out reading current time\n"); | ||
144 | |||
145 | return -EIO; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Set current time and date in RTC | ||
150 | */ | ||
151 | static int wm831x_rtc_set_mmss(struct device *dev, unsigned long time) | ||
152 | { | ||
153 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
154 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
155 | struct rtc_time new_tm; | ||
156 | unsigned long new_time; | ||
157 | int ret; | ||
158 | int count = 0; | ||
159 | |||
160 | ret = wm831x_reg_write(wm831x, WM831X_RTC_TIME_1, | ||
161 | (time >> 16) & 0xffff); | ||
162 | if (ret < 0) { | ||
163 | dev_err(dev, "Failed to write TIME_1: %d\n", ret); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | ret = wm831x_reg_write(wm831x, WM831X_RTC_TIME_2, time & 0xffff); | ||
168 | if (ret < 0) { | ||
169 | dev_err(dev, "Failed to write TIME_2: %d\n", ret); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | /* Wait for the update to complete - should happen first time | ||
174 | * round but be conservative. | ||
175 | */ | ||
176 | do { | ||
177 | msleep(1); | ||
178 | |||
179 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
180 | if (ret < 0) | ||
181 | ret = WM831X_RTC_SYNC_BUSY; | ||
182 | } while (!(ret & WM831X_RTC_SYNC_BUSY) && | ||
183 | ++count < WM831X_SET_TIME_RETRIES); | ||
184 | |||
185 | if (ret & WM831X_RTC_SYNC_BUSY) { | ||
186 | dev_err(dev, "Timed out writing RTC update\n"); | ||
187 | return -EIO; | ||
188 | } | ||
189 | |||
190 | /* Check that the update was accepted; security features may | ||
191 | * have caused the update to be ignored. | ||
192 | */ | ||
193 | ret = wm831x_rtc_readtime(dev, &new_tm); | ||
194 | if (ret < 0) | ||
195 | return ret; | ||
196 | |||
197 | ret = rtc_tm_to_time(&new_tm, &new_time); | ||
198 | if (ret < 0) { | ||
199 | dev_err(dev, "Failed to convert time: %d\n", ret); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | /* Allow a second of change in case of tick */ | ||
204 | if (new_time - time > 1) { | ||
205 | dev_err(dev, "RTC update not permitted by hardware\n"); | ||
206 | return -EPERM; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Read alarm time and date in RTC | ||
214 | */ | ||
215 | static int wm831x_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
216 | { | ||
217 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
218 | int ret; | ||
219 | u16 data[2]; | ||
220 | u32 time; | ||
221 | |||
222 | ret = wm831x_bulk_read(wm831x_rtc->wm831x, WM831X_RTC_ALARM_1, | ||
223 | 2, data); | ||
224 | if (ret != 0) { | ||
225 | dev_err(dev, "Failed to read alarm time: %d\n", ret); | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | time = (data[0] << 16) | data[1]; | ||
230 | |||
231 | rtc_time_to_tm(time, &alrm->time); | ||
232 | |||
233 | ret = wm831x_reg_read(wm831x_rtc->wm831x, WM831X_RTC_CONTROL); | ||
234 | if (ret < 0) { | ||
235 | dev_err(dev, "Failed to read RTC control: %d\n", ret); | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | if (ret & WM831X_RTC_ALM_ENA) | ||
240 | alrm->enabled = 1; | ||
241 | else | ||
242 | alrm->enabled = 0; | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int wm831x_rtc_stop_alarm(struct wm831x_rtc *wm831x_rtc) | ||
248 | { | ||
249 | wm831x_rtc->alarm_enabled = 0; | ||
250 | |||
251 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
252 | WM831X_RTC_ALM_ENA, 0); | ||
253 | } | ||
254 | |||
255 | static int wm831x_rtc_start_alarm(struct wm831x_rtc *wm831x_rtc) | ||
256 | { | ||
257 | wm831x_rtc->alarm_enabled = 1; | ||
258 | |||
259 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
260 | WM831X_RTC_ALM_ENA, WM831X_RTC_ALM_ENA); | ||
261 | } | ||
262 | |||
263 | static int wm831x_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
264 | { | ||
265 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
266 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
267 | int ret; | ||
268 | unsigned long time; | ||
269 | |||
270 | ret = rtc_tm_to_time(&alrm->time, &time); | ||
271 | if (ret < 0) { | ||
272 | dev_err(dev, "Failed to convert time: %d\n", ret); | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | ret = wm831x_rtc_stop_alarm(wm831x_rtc); | ||
277 | if (ret < 0) { | ||
278 | dev_err(dev, "Failed to stop alarm: %d\n", ret); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_1, | ||
283 | (time >> 16) & 0xffff); | ||
284 | if (ret < 0) { | ||
285 | dev_err(dev, "Failed to write ALARM_1: %d\n", ret); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_2, time & 0xffff); | ||
290 | if (ret < 0) { | ||
291 | dev_err(dev, "Failed to write ALARM_2: %d\n", ret); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | if (alrm->enabled) { | ||
296 | ret = wm831x_rtc_start_alarm(wm831x_rtc); | ||
297 | if (ret < 0) { | ||
298 | dev_err(dev, "Failed to start alarm: %d\n", ret); | ||
299 | return ret; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int wm831x_rtc_alarm_irq_enable(struct device *dev, | ||
307 | unsigned int enabled) | ||
308 | { | ||
309 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
310 | |||
311 | if (enabled) | ||
312 | return wm831x_rtc_start_alarm(wm831x_rtc); | ||
313 | else | ||
314 | return wm831x_rtc_stop_alarm(wm831x_rtc); | ||
315 | } | ||
316 | |||
317 | static int wm831x_rtc_update_irq_enable(struct device *dev, | ||
318 | unsigned int enabled) | ||
319 | { | ||
320 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
321 | int val; | ||
322 | |||
323 | if (enabled) | ||
324 | val = 1 << WM831X_RTC_PINT_FREQ_SHIFT; | ||
325 | else | ||
326 | val = 0; | ||
327 | |||
328 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
329 | WM831X_RTC_PINT_FREQ_MASK, val); | ||
330 | } | ||
331 | |||
332 | static irqreturn_t wm831x_alm_irq(int irq, void *data) | ||
333 | { | ||
334 | struct wm831x_rtc *wm831x_rtc = data; | ||
335 | |||
336 | rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
337 | |||
338 | return IRQ_HANDLED; | ||
339 | } | ||
340 | |||
341 | static irqreturn_t wm831x_per_irq(int irq, void *data) | ||
342 | { | ||
343 | struct wm831x_rtc *wm831x_rtc = data; | ||
344 | |||
345 | rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
346 | |||
347 | return IRQ_HANDLED; | ||
348 | } | ||
349 | |||
350 | static const struct rtc_class_ops wm831x_rtc_ops = { | ||
351 | .read_time = wm831x_rtc_readtime, | ||
352 | .set_mmss = wm831x_rtc_set_mmss, | ||
353 | .read_alarm = wm831x_rtc_readalarm, | ||
354 | .set_alarm = wm831x_rtc_setalarm, | ||
355 | .alarm_irq_enable = wm831x_rtc_alarm_irq_enable, | ||
356 | .update_irq_enable = wm831x_rtc_update_irq_enable, | ||
357 | }; | ||
358 | |||
359 | #ifdef CONFIG_PM | ||
360 | /* Turn off the alarm if it should not be a wake source. */ | ||
361 | static int wm831x_rtc_suspend(struct device *dev) | ||
362 | { | ||
363 | struct platform_device *pdev = to_platform_device(dev); | ||
364 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
365 | int ret, enable; | ||
366 | |||
367 | if (wm831x_rtc->alarm_enabled && device_may_wakeup(&pdev->dev)) | ||
368 | enable = WM831X_RTC_ALM_ENA; | ||
369 | else | ||
370 | enable = 0; | ||
371 | |||
372 | ret = wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
373 | WM831X_RTC_ALM_ENA, enable); | ||
374 | if (ret != 0) | ||
375 | dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | /* Enable the alarm if it should be enabled (in case it was disabled to | ||
381 | * prevent use as a wake source). | ||
382 | */ | ||
383 | static int wm831x_rtc_resume(struct device *dev) | ||
384 | { | ||
385 | struct platform_device *pdev = to_platform_device(dev); | ||
386 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
387 | int ret; | ||
388 | |||
389 | if (wm831x_rtc->alarm_enabled) { | ||
390 | ret = wm831x_rtc_start_alarm(wm831x_rtc); | ||
391 | if (ret != 0) | ||
392 | dev_err(&pdev->dev, | ||
393 | "Failed to restart RTC alarm: %d\n", ret); | ||
394 | } | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* Unconditionally disable the alarm */ | ||
400 | static int wm831x_rtc_freeze(struct device *dev) | ||
401 | { | ||
402 | struct platform_device *pdev = to_platform_device(dev); | ||
403 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
404 | int ret; | ||
405 | |||
406 | ret = wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
407 | WM831X_RTC_ALM_ENA, 0); | ||
408 | if (ret != 0) | ||
409 | dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | #else | ||
414 | #define wm831x_rtc_suspend NULL | ||
415 | #define wm831x_rtc_resume NULL | ||
416 | #define wm831x_rtc_freeze NULL | ||
417 | #endif | ||
418 | |||
419 | static int wm831x_rtc_probe(struct platform_device *pdev) | ||
420 | { | ||
421 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | ||
422 | struct wm831x_rtc *wm831x_rtc; | ||
423 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
424 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
425 | int ret = 0; | ||
426 | |||
427 | wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL); | ||
428 | if (wm831x_rtc == NULL) | ||
429 | return -ENOMEM; | ||
430 | |||
431 | platform_set_drvdata(pdev, wm831x_rtc); | ||
432 | wm831x_rtc->wm831x = wm831x; | ||
433 | |||
434 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
435 | if (ret < 0) { | ||
436 | dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret); | ||
437 | goto err; | ||
438 | } | ||
439 | if (ret & WM831X_RTC_ALM_ENA) | ||
440 | wm831x_rtc->alarm_enabled = 1; | ||
441 | |||
442 | device_init_wakeup(&pdev->dev, 1); | ||
443 | |||
444 | wm831x_rtc->rtc = rtc_device_register("wm831x", &pdev->dev, | ||
445 | &wm831x_rtc_ops, THIS_MODULE); | ||
446 | if (IS_ERR(wm831x_rtc->rtc)) { | ||
447 | ret = PTR_ERR(wm831x_rtc->rtc); | ||
448 | goto err; | ||
449 | } | ||
450 | |||
451 | ret = wm831x_request_irq(wm831x, per_irq, wm831x_per_irq, | ||
452 | IRQF_TRIGGER_RISING, "wm831x_rtc_per", | ||
453 | wm831x_rtc); | ||
454 | if (ret != 0) { | ||
455 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", | ||
456 | per_irq, ret); | ||
457 | } | ||
458 | |||
459 | ret = wm831x_request_irq(wm831x, alm_irq, wm831x_alm_irq, | ||
460 | IRQF_TRIGGER_RISING, "wm831x_rtc_alm", | ||
461 | wm831x_rtc); | ||
462 | if (ret != 0) { | ||
463 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | ||
464 | alm_irq, ret); | ||
465 | } | ||
466 | |||
467 | return 0; | ||
468 | |||
469 | err: | ||
470 | kfree(wm831x_rtc); | ||
471 | return ret; | ||
472 | } | ||
473 | |||
474 | static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | ||
475 | { | ||
476 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); | ||
477 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
478 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
479 | |||
480 | wm831x_free_irq(wm831x_rtc->wm831x, alm_irq, wm831x_rtc); | ||
481 | wm831x_free_irq(wm831x_rtc->wm831x, per_irq, wm831x_rtc); | ||
482 | rtc_device_unregister(wm831x_rtc->rtc); | ||
483 | kfree(wm831x_rtc); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static struct dev_pm_ops wm831x_rtc_pm_ops = { | ||
489 | .suspend = wm831x_rtc_suspend, | ||
490 | .resume = wm831x_rtc_resume, | ||
491 | |||
492 | .freeze = wm831x_rtc_freeze, | ||
493 | .thaw = wm831x_rtc_resume, | ||
494 | .restore = wm831x_rtc_resume, | ||
495 | |||
496 | .poweroff = wm831x_rtc_suspend, | ||
497 | }; | ||
498 | |||
499 | static struct platform_driver wm831x_rtc_driver = { | ||
500 | .probe = wm831x_rtc_probe, | ||
501 | .remove = __devexit_p(wm831x_rtc_remove), | ||
502 | .driver = { | ||
503 | .name = "wm831x-rtc", | ||
504 | .pm = &wm831x_rtc_pm_ops, | ||
505 | }, | ||
506 | }; | ||
507 | |||
508 | static int __init wm831x_rtc_init(void) | ||
509 | { | ||
510 | return platform_driver_register(&wm831x_rtc_driver); | ||
511 | } | ||
512 | module_init(wm831x_rtc_init); | ||
513 | |||
514 | static void __exit wm831x_rtc_exit(void) | ||
515 | { | ||
516 | platform_driver_unregister(&wm831x_rtc_driver); | ||
517 | } | ||
518 | module_exit(wm831x_rtc_exit); | ||
519 | |||
520 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
521 | MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs"); | ||
522 | MODULE_LICENSE("GPL"); | ||
523 | MODULE_ALIAS("platform:wm831x-rtc"); | ||