diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-26 13:49:48 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-26 13:49:48 -0400 |
commit | 18ffa418aead13c56515ac74cd26105102128aca (patch) | |
tree | 2096ea8db3b2594bd25ad39a70edc691219f669b /drivers/rtc | |
parent | ab76f3d771590d5c89faa3219559c5d3fc0ce0c2 (diff) | |
parent | 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff) |
Merge commit 'v2.6.29' into x86/setup-lzma
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 13 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-au1xxx.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-dm355evm.c | 175 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1390.c | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf50633.c | 344 | ||||
-rw-r--r-- | drivers/rtc/rtc-pxa.c | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-twl4030.c | 49 |
8 files changed, 551 insertions, 39 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4ad831de41ad..81450fbd8b12 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT | |||
241 | If you say Y here you will get support for the | 241 | If you say Y here you will get support for the |
242 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. | 242 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
243 | 243 | ||
244 | config RTC_DRV_DM355EVM | ||
245 | tristate "TI DaVinci DM355 EVM RTC" | ||
246 | depends on MFD_DM355EVM_MSP | ||
247 | help | ||
248 | Supports the RTC firmware in the MSP430 on the DM355 EVM. | ||
249 | |||
244 | config RTC_DRV_TWL92330 | 250 | config RTC_DRV_TWL92330 |
245 | boolean "TI TWL92330/Menelaus" | 251 | boolean "TI TWL92330/Menelaus" |
246 | depends on MENELAUS | 252 | depends on MENELAUS |
@@ -502,6 +508,13 @@ config RTC_DRV_WM8350 | |||
502 | This driver can also be built as a module. If so, the module | 508 | This driver can also be built as a module. If so, the module |
503 | will be called "rtc-wm8350". | 509 | will be called "rtc-wm8350". |
504 | 510 | ||
511 | config RTC_DRV_PCF50633 | ||
512 | depends on MFD_PCF50633 | ||
513 | tristate "NXP PCF50633 RTC" | ||
514 | help | ||
515 | If you say yes here you get support for the RTC subsystem of the | ||
516 | NXP PCF50633 used in embedded systems. | ||
517 | |||
505 | comment "on-CPU RTC drivers" | 518 | comment "on-CPU RTC drivers" |
506 | 519 | ||
507 | config RTC_DRV_OMAP | 520 | config RTC_DRV_OMAP |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9a4340d48f26..0e697aa51caa 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | |||
23 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o | 23 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o |
24 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 24 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
25 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 25 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
26 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | ||
26 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 27 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
27 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | 28 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o |
28 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 29 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
@@ -74,3 +75,4 @@ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | |||
74 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 75 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
75 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 76 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
76 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 77 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
78 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | ||
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index 8906a688e6a6..979ed0406ce9 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c | |||
@@ -81,7 +81,7 @@ static int __devinit au1xtoy_rtc_probe(struct platform_device *pdev) | |||
81 | if (au_readl(SYS_TOYTRIM) != 32767) { | 81 | if (au_readl(SYS_TOYTRIM) != 32767) { |
82 | /* wait until hardware gives access to TRIM register */ | 82 | /* wait until hardware gives access to TRIM register */ |
83 | t = 0x00100000; | 83 | t = 0x00100000; |
84 | while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && t--) | 84 | while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t) |
85 | msleep(1); | 85 | msleep(1); |
86 | 86 | ||
87 | if (!t) { | 87 | if (!t) { |
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c new file mode 100644 index 000000000000..58d4e18530da --- /dev/null +++ b/drivers/rtc/rtc-dm355evm.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware | ||
3 | * | ||
4 | * Copyright (c) 2008 by David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <linux/i2c/dm355evm_msp.h> | ||
17 | |||
18 | |||
19 | /* | ||
20 | * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed | ||
21 | * a 1 Hz counter. When a backup battery is supplied, that makes a | ||
22 | * reasonable RTC for applications where alarms and non-NTP drift | ||
23 | * compensation aren't important. | ||
24 | * | ||
25 | * The only real glitch is the inability to read or write all four | ||
26 | * counter bytes atomically: the count may increment in the middle | ||
27 | * of an operation, causing trouble when the LSB rolls over. | ||
28 | * | ||
29 | * This driver was tested with firmware revision A4. | ||
30 | */ | ||
31 | union evm_time { | ||
32 | u8 bytes[4]; | ||
33 | u32 value; | ||
34 | }; | ||
35 | |||
36 | static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
37 | { | ||
38 | union evm_time time; | ||
39 | int status; | ||
40 | int tries = 0; | ||
41 | |||
42 | do { | ||
43 | /* | ||
44 | * Read LSB(0) to MSB(3) bytes. Defend against the counter | ||
45 | * rolling over by re-reading until the value is stable, | ||
46 | * and assuming the four reads take at most a few seconds. | ||
47 | */ | ||
48 | status = dm355evm_msp_read(DM355EVM_MSP_RTC_0); | ||
49 | if (status < 0) | ||
50 | return status; | ||
51 | if (tries && time.bytes[0] == status) | ||
52 | break; | ||
53 | time.bytes[0] = status; | ||
54 | |||
55 | status = dm355evm_msp_read(DM355EVM_MSP_RTC_1); | ||
56 | if (status < 0) | ||
57 | return status; | ||
58 | if (tries && time.bytes[1] == status) | ||
59 | break; | ||
60 | time.bytes[1] = status; | ||
61 | |||
62 | status = dm355evm_msp_read(DM355EVM_MSP_RTC_2); | ||
63 | if (status < 0) | ||
64 | return status; | ||
65 | if (tries && time.bytes[2] == status) | ||
66 | break; | ||
67 | time.bytes[2] = status; | ||
68 | |||
69 | status = dm355evm_msp_read(DM355EVM_MSP_RTC_3); | ||
70 | if (status < 0) | ||
71 | return status; | ||
72 | if (tries && time.bytes[3] == status) | ||
73 | break; | ||
74 | time.bytes[3] = status; | ||
75 | |||
76 | } while (++tries < 5); | ||
77 | |||
78 | dev_dbg(dev, "read timestamp %08x\n", time.value); | ||
79 | |||
80 | rtc_time_to_tm(le32_to_cpu(time.value), tm); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
85 | { | ||
86 | union evm_time time; | ||
87 | unsigned long value; | ||
88 | int status; | ||
89 | |||
90 | rtc_tm_to_time(tm, &value); | ||
91 | time.value = cpu_to_le32(value); | ||
92 | |||
93 | dev_dbg(dev, "write timestamp %08x\n", time.value); | ||
94 | |||
95 | /* | ||
96 | * REVISIT handle non-atomic writes ... maybe just retry until | ||
97 | * byte[1] sticks (no rollover)? | ||
98 | */ | ||
99 | status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0); | ||
100 | if (status < 0) | ||
101 | return status; | ||
102 | |||
103 | status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1); | ||
104 | if (status < 0) | ||
105 | return status; | ||
106 | |||
107 | status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2); | ||
108 | if (status < 0) | ||
109 | return status; | ||
110 | |||
111 | status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3); | ||
112 | if (status < 0) | ||
113 | return status; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static struct rtc_class_ops dm355evm_rtc_ops = { | ||
119 | .read_time = dm355evm_rtc_read_time, | ||
120 | .set_time = dm355evm_rtc_set_time, | ||
121 | }; | ||
122 | |||
123 | /*----------------------------------------------------------------------*/ | ||
124 | |||
125 | static int __devinit dm355evm_rtc_probe(struct platform_device *pdev) | ||
126 | { | ||
127 | struct rtc_device *rtc; | ||
128 | |||
129 | rtc = rtc_device_register(pdev->name, | ||
130 | &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE); | ||
131 | if (IS_ERR(rtc)) { | ||
132 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
133 | PTR_ERR(rtc)); | ||
134 | return PTR_ERR(rtc); | ||
135 | } | ||
136 | platform_set_drvdata(pdev, rtc); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int __devexit dm355evm_rtc_remove(struct platform_device *pdev) | ||
142 | { | ||
143 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
144 | |||
145 | rtc_device_unregister(rtc); | ||
146 | platform_set_drvdata(pdev, NULL); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * I2C is used to talk to the MSP430, but this platform device is | ||
152 | * exposed by an MFD driver that manages I2C communications. | ||
153 | */ | ||
154 | static struct platform_driver rtc_dm355evm_driver = { | ||
155 | .probe = dm355evm_rtc_probe, | ||
156 | .remove = __devexit_p(dm355evm_rtc_remove), | ||
157 | .driver = { | ||
158 | .owner = THIS_MODULE, | ||
159 | .name = "rtc-dm355evm", | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | static int __init dm355evm_rtc_init(void) | ||
164 | { | ||
165 | return platform_driver_register(&rtc_dm355evm_driver); | ||
166 | } | ||
167 | module_init(dm355evm_rtc_init); | ||
168 | |||
169 | static void __exit dm355evm_rtc_exit(void) | ||
170 | { | ||
171 | platform_driver_unregister(&rtc_dm355evm_driver); | ||
172 | } | ||
173 | module_exit(dm355evm_rtc_exit); | ||
174 | |||
175 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index e54b5c619bdf..e01b955db077 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c | |||
@@ -122,7 +122,6 @@ static const struct rtc_class_ops ds1390_rtc_ops = { | |||
122 | 122 | ||
123 | static int __devinit ds1390_probe(struct spi_device *spi) | 123 | static int __devinit ds1390_probe(struct spi_device *spi) |
124 | { | 124 | { |
125 | struct rtc_device *rtc; | ||
126 | unsigned char tmp; | 125 | unsigned char tmp; |
127 | struct ds1390 *chip; | 126 | struct ds1390 *chip; |
128 | int res; | 127 | int res; |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c new file mode 100644 index 000000000000..f4dd87e29075 --- /dev/null +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* NXP PCF50633 RTC Driver | ||
2 | * | ||
3 | * (C) 2006-2008 by Openmoko, Inc. | ||
4 | * Author: Balaji Rao <balajirrao@openmoko.org> | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Broken down from monstrous PCF50633 driver mainly by | ||
8 | * Harald Welte, Andy Green and Werner Almesberger | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/err.h> | ||
25 | |||
26 | #include <linux/mfd/pcf50633/core.h> | ||
27 | |||
28 | #define PCF50633_REG_RTCSC 0x59 /* Second */ | ||
29 | #define PCF50633_REG_RTCMN 0x5a /* Minute */ | ||
30 | #define PCF50633_REG_RTCHR 0x5b /* Hour */ | ||
31 | #define PCF50633_REG_RTCWD 0x5c /* Weekday */ | ||
32 | #define PCF50633_REG_RTCDT 0x5d /* Day */ | ||
33 | #define PCF50633_REG_RTCMT 0x5e /* Month */ | ||
34 | #define PCF50633_REG_RTCYR 0x5f /* Year */ | ||
35 | #define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */ | ||
36 | #define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */ | ||
37 | #define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */ | ||
38 | #define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */ | ||
39 | #define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */ | ||
40 | #define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */ | ||
41 | #define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */ | ||
42 | |||
43 | enum pcf50633_time_indexes { | ||
44 | PCF50633_TI_SEC, | ||
45 | PCF50633_TI_MIN, | ||
46 | PCF50633_TI_HOUR, | ||
47 | PCF50633_TI_WKDAY, | ||
48 | PCF50633_TI_DAY, | ||
49 | PCF50633_TI_MONTH, | ||
50 | PCF50633_TI_YEAR, | ||
51 | PCF50633_TI_EXTENT /* always last */ | ||
52 | }; | ||
53 | |||
54 | struct pcf50633_time { | ||
55 | u_int8_t time[PCF50633_TI_EXTENT]; | ||
56 | }; | ||
57 | |||
58 | struct pcf50633_rtc { | ||
59 | int alarm_enabled; | ||
60 | int second_enabled; | ||
61 | |||
62 | struct pcf50633 *pcf; | ||
63 | struct rtc_device *rtc_dev; | ||
64 | }; | ||
65 | |||
66 | static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf) | ||
67 | { | ||
68 | rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]); | ||
69 | rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]); | ||
70 | rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]); | ||
71 | rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]); | ||
72 | rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]); | ||
73 | rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]); | ||
74 | rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100; | ||
75 | } | ||
76 | |||
77 | static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc) | ||
78 | { | ||
79 | pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec); | ||
80 | pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min); | ||
81 | pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour); | ||
82 | pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday); | ||
83 | pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday); | ||
84 | pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon); | ||
85 | pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100); | ||
86 | } | ||
87 | |||
88 | static int | ||
89 | pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
90 | { | ||
91 | struct pcf50633_rtc *rtc = dev_get_drvdata(dev); | ||
92 | int err; | ||
93 | |||
94 | if (enabled) | ||
95 | err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
96 | else | ||
97 | err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
98 | |||
99 | if (err < 0) | ||
100 | return err; | ||
101 | |||
102 | rtc->alarm_enabled = enabled; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int | ||
108 | pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled) | ||
109 | { | ||
110 | struct pcf50633_rtc *rtc = dev_get_drvdata(dev); | ||
111 | int err; | ||
112 | |||
113 | if (enabled) | ||
114 | err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
115 | else | ||
116 | err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
117 | |||
118 | if (err < 0) | ||
119 | return err; | ||
120 | |||
121 | rtc->second_enabled = enabled; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
127 | { | ||
128 | struct pcf50633_rtc *rtc; | ||
129 | struct pcf50633_time pcf_tm; | ||
130 | int ret; | ||
131 | |||
132 | rtc = dev_get_drvdata(dev); | ||
133 | |||
134 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC, | ||
135 | PCF50633_TI_EXTENT, | ||
136 | &pcf_tm.time[0]); | ||
137 | if (ret != PCF50633_TI_EXTENT) { | ||
138 | dev_err(dev, "Failed to read time\n"); | ||
139 | return -EIO; | ||
140 | } | ||
141 | |||
142 | dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", | ||
143 | pcf_tm.time[PCF50633_TI_DAY], | ||
144 | pcf_tm.time[PCF50633_TI_MONTH], | ||
145 | pcf_tm.time[PCF50633_TI_YEAR], | ||
146 | pcf_tm.time[PCF50633_TI_HOUR], | ||
147 | pcf_tm.time[PCF50633_TI_MIN], | ||
148 | pcf_tm.time[PCF50633_TI_SEC]); | ||
149 | |||
150 | pcf2rtc_time(tm, &pcf_tm); | ||
151 | |||
152 | dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n", | ||
153 | tm->tm_mday, tm->tm_mon, tm->tm_year, | ||
154 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
155 | |||
156 | return rtc_valid_tm(tm); | ||
157 | } | ||
158 | |||
159 | static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
160 | { | ||
161 | struct pcf50633_rtc *rtc; | ||
162 | struct pcf50633_time pcf_tm; | ||
163 | int second_masked, alarm_masked, ret = 0; | ||
164 | |||
165 | rtc = dev_get_drvdata(dev); | ||
166 | |||
167 | dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n", | ||
168 | tm->tm_mday, tm->tm_mon, tm->tm_year, | ||
169 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
170 | |||
171 | rtc2pcf_time(&pcf_tm, tm); | ||
172 | |||
173 | dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", | ||
174 | pcf_tm.time[PCF50633_TI_DAY], | ||
175 | pcf_tm.time[PCF50633_TI_MONTH], | ||
176 | pcf_tm.time[PCF50633_TI_YEAR], | ||
177 | pcf_tm.time[PCF50633_TI_HOUR], | ||
178 | pcf_tm.time[PCF50633_TI_MIN], | ||
179 | pcf_tm.time[PCF50633_TI_SEC]); | ||
180 | |||
181 | |||
182 | second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND); | ||
183 | alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); | ||
184 | |||
185 | if (!second_masked) | ||
186 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
187 | if (!alarm_masked) | ||
188 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
189 | |||
190 | /* Returns 0 on success */ | ||
191 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC, | ||
192 | PCF50633_TI_EXTENT, | ||
193 | &pcf_tm.time[0]); | ||
194 | |||
195 | if (!second_masked) | ||
196 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
197 | if (!alarm_masked) | ||
198 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
204 | { | ||
205 | struct pcf50633_rtc *rtc; | ||
206 | struct pcf50633_time pcf_tm; | ||
207 | int ret = 0; | ||
208 | |||
209 | rtc = dev_get_drvdata(dev); | ||
210 | |||
211 | alrm->enabled = rtc->alarm_enabled; | ||
212 | |||
213 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, | ||
214 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | ||
215 | if (ret != PCF50633_TI_EXTENT) { | ||
216 | dev_err(dev, "Failed to read time\n"); | ||
217 | return -EIO; | ||
218 | } | ||
219 | |||
220 | pcf2rtc_time(&alrm->time, &pcf_tm); | ||
221 | |||
222 | return rtc_valid_tm(&alrm->time); | ||
223 | } | ||
224 | |||
225 | static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
226 | { | ||
227 | struct pcf50633_rtc *rtc; | ||
228 | struct pcf50633_time pcf_tm; | ||
229 | int alarm_masked, ret = 0; | ||
230 | |||
231 | rtc = dev_get_drvdata(dev); | ||
232 | |||
233 | rtc2pcf_time(&pcf_tm, &alrm->time); | ||
234 | |||
235 | /* do like mktime does and ignore tm_wday */ | ||
236 | pcf_tm.time[PCF50633_TI_WKDAY] = 7; | ||
237 | |||
238 | alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); | ||
239 | |||
240 | /* disable alarm interrupt */ | ||
241 | if (!alarm_masked) | ||
242 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
243 | |||
244 | /* Returns 0 on success */ | ||
245 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, | ||
246 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | ||
247 | |||
248 | if (!alarm_masked) | ||
249 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | ||
250 | |||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | static struct rtc_class_ops pcf50633_rtc_ops = { | ||
255 | .read_time = pcf50633_rtc_read_time, | ||
256 | .set_time = pcf50633_rtc_set_time, | ||
257 | .read_alarm = pcf50633_rtc_read_alarm, | ||
258 | .set_alarm = pcf50633_rtc_set_alarm, | ||
259 | .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable, | ||
260 | .update_irq_enable = pcf50633_rtc_update_irq_enable, | ||
261 | }; | ||
262 | |||
263 | static void pcf50633_rtc_irq(int irq, void *data) | ||
264 | { | ||
265 | struct pcf50633_rtc *rtc = data; | ||
266 | |||
267 | switch (irq) { | ||
268 | case PCF50633_IRQ_ALARM: | ||
269 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); | ||
270 | break; | ||
271 | case PCF50633_IRQ_SECOND: | ||
272 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | ||
273 | break; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | ||
278 | { | ||
279 | struct pcf50633_subdev_pdata *pdata; | ||
280 | struct pcf50633_rtc *rtc; | ||
281 | |||
282 | |||
283 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
284 | if (!rtc) | ||
285 | return -ENOMEM; | ||
286 | |||
287 | pdata = pdev->dev.platform_data; | ||
288 | rtc->pcf = pdata->pcf; | ||
289 | platform_set_drvdata(pdev, rtc); | ||
290 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, | ||
291 | &pcf50633_rtc_ops, THIS_MODULE); | ||
292 | |||
293 | if (IS_ERR(rtc->rtc_dev)) { | ||
294 | kfree(rtc); | ||
295 | return PTR_ERR(rtc->rtc_dev); | ||
296 | } | ||
297 | |||
298 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, | ||
299 | pcf50633_rtc_irq, rtc); | ||
300 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND, | ||
301 | pcf50633_rtc_irq, rtc); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int __devexit pcf50633_rtc_remove(struct platform_device *pdev) | ||
307 | { | ||
308 | struct pcf50633_rtc *rtc; | ||
309 | |||
310 | rtc = platform_get_drvdata(pdev); | ||
311 | |||
312 | pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); | ||
313 | pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND); | ||
314 | |||
315 | rtc_device_unregister(rtc->rtc_dev); | ||
316 | kfree(rtc); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static struct platform_driver pcf50633_rtc_driver = { | ||
322 | .driver = { | ||
323 | .name = "pcf50633-rtc", | ||
324 | }, | ||
325 | .probe = pcf50633_rtc_probe, | ||
326 | .remove = __devexit_p(pcf50633_rtc_remove), | ||
327 | }; | ||
328 | |||
329 | static int __init pcf50633_rtc_init(void) | ||
330 | { | ||
331 | return platform_driver_register(&pcf50633_rtc_driver); | ||
332 | } | ||
333 | module_init(pcf50633_rtc_init); | ||
334 | |||
335 | static void __exit pcf50633_rtc_exit(void) | ||
336 | { | ||
337 | platform_driver_unregister(&pcf50633_rtc_driver); | ||
338 | } | ||
339 | module_exit(pcf50633_rtc_exit); | ||
340 | |||
341 | MODULE_DESCRIPTION("PCF50633 RTC driver"); | ||
342 | MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); | ||
343 | MODULE_LICENSE("GPL"); | ||
344 | |||
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index cc7eb8767b82..bb8cc05605ac 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | 29 | ||
30 | #include <mach/hardware.h> | ||
31 | |||
30 | #define TIMER_FREQ CLOCK_TICK_RATE | 32 | #define TIMER_FREQ CLOCK_TICK_RATE |
31 | #define RTC_DEF_DIVIDER (32768 - 1) | 33 | #define RTC_DEF_DIVIDER (32768 - 1) |
32 | #define RTC_DEF_TRIM 0 | 34 | #define RTC_DEF_TRIM 0 |
@@ -483,7 +485,7 @@ static void __exit pxa_rtc_exit(void) | |||
483 | module_init(pxa_rtc_init); | 485 | module_init(pxa_rtc_init); |
484 | module_exit(pxa_rtc_exit); | 486 | module_exit(pxa_rtc_exit); |
485 | 487 | ||
486 | MODULE_AUTHOR("Robert Jarzmik"); | 488 | MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); |
487 | MODULE_DESCRIPTION("PXA27x/PXA3xx Realtime Clock Driver (RTC)"); | 489 | MODULE_DESCRIPTION("PXA27x/PXA3xx Realtime Clock Driver (RTC)"); |
488 | MODULE_LICENSE("GPL"); | 490 | MODULE_LICENSE("GPL"); |
489 | MODULE_ALIAS("platform:pxa-rtc"); | 491 | MODULE_ALIAS("platform:pxa-rtc"); |
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index 8ce5f74ee45b..ad35f76c46b7 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c | |||
@@ -120,7 +120,7 @@ static int twl4030_rtc_write_u8(u8 data, u8 reg) | |||
120 | static unsigned char rtc_irq_bits; | 120 | static unsigned char rtc_irq_bits; |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * Enable timer and/or alarm interrupts. | 123 | * Enable 1/second update and/or alarm interrupts. |
124 | */ | 124 | */ |
125 | static int set_rtc_irq_bit(unsigned char bit) | 125 | static int set_rtc_irq_bit(unsigned char bit) |
126 | { | 126 | { |
@@ -128,6 +128,7 @@ static int set_rtc_irq_bit(unsigned char bit) | |||
128 | int ret; | 128 | int ret; |
129 | 129 | ||
130 | val = rtc_irq_bits | bit; | 130 | val = rtc_irq_bits | bit; |
131 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; | ||
131 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 132 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
132 | if (ret == 0) | 133 | if (ret == 0) |
133 | rtc_irq_bits = val; | 134 | rtc_irq_bits = val; |
@@ -136,7 +137,7 @@ static int set_rtc_irq_bit(unsigned char bit) | |||
136 | } | 137 | } |
137 | 138 | ||
138 | /* | 139 | /* |
139 | * Disable timer and/or alarm interrupts. | 140 | * Disable update and/or alarm interrupts. |
140 | */ | 141 | */ |
141 | static int mask_rtc_irq_bit(unsigned char bit) | 142 | static int mask_rtc_irq_bit(unsigned char bit) |
142 | { | 143 | { |
@@ -151,7 +152,7 @@ static int mask_rtc_irq_bit(unsigned char bit) | |||
151 | return ret; | 152 | return ret; |
152 | } | 153 | } |
153 | 154 | ||
154 | static inline int twl4030_rtc_alarm_irq_set_state(int enabled) | 155 | static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) |
155 | { | 156 | { |
156 | int ret; | 157 | int ret; |
157 | 158 | ||
@@ -163,7 +164,7 @@ static inline int twl4030_rtc_alarm_irq_set_state(int enabled) | |||
163 | return ret; | 164 | return ret; |
164 | } | 165 | } |
165 | 166 | ||
166 | static inline int twl4030_rtc_irq_set_state(int enabled) | 167 | static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) |
167 | { | 168 | { |
168 | int ret; | 169 | int ret; |
169 | 170 | ||
@@ -292,7 +293,7 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
292 | unsigned char alarm_data[ALL_TIME_REGS + 1]; | 293 | unsigned char alarm_data[ALL_TIME_REGS + 1]; |
293 | int ret; | 294 | int ret; |
294 | 295 | ||
295 | ret = twl4030_rtc_alarm_irq_set_state(0); | 296 | ret = twl4030_rtc_alarm_irq_enable(dev, 0); |
296 | if (ret) | 297 | if (ret) |
297 | goto out; | 298 | goto out; |
298 | 299 | ||
@@ -312,35 +313,11 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
312 | } | 313 | } |
313 | 314 | ||
314 | if (alm->enabled) | 315 | if (alm->enabled) |
315 | ret = twl4030_rtc_alarm_irq_set_state(1); | 316 | ret = twl4030_rtc_alarm_irq_enable(dev, 1); |
316 | out: | 317 | out: |
317 | return ret; | 318 | return ret; |
318 | } | 319 | } |
319 | 320 | ||
320 | #ifdef CONFIG_RTC_INTF_DEV | ||
321 | |||
322 | static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
323 | unsigned long arg) | ||
324 | { | ||
325 | switch (cmd) { | ||
326 | case RTC_AIE_OFF: | ||
327 | return twl4030_rtc_alarm_irq_set_state(0); | ||
328 | case RTC_AIE_ON: | ||
329 | return twl4030_rtc_alarm_irq_set_state(1); | ||
330 | case RTC_UIE_OFF: | ||
331 | return twl4030_rtc_irq_set_state(0); | ||
332 | case RTC_UIE_ON: | ||
333 | return twl4030_rtc_irq_set_state(1); | ||
334 | |||
335 | default: | ||
336 | return -ENOIOCTLCMD; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | #else | ||
341 | #define twl4030_rtc_ioctl NULL | ||
342 | #endif | ||
343 | |||
344 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | 321 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) |
345 | { | 322 | { |
346 | unsigned long events = 0; | 323 | unsigned long events = 0; |
@@ -400,11 +377,12 @@ out: | |||
400 | } | 377 | } |
401 | 378 | ||
402 | static struct rtc_class_ops twl4030_rtc_ops = { | 379 | static struct rtc_class_ops twl4030_rtc_ops = { |
403 | .ioctl = twl4030_rtc_ioctl, | ||
404 | .read_time = twl4030_rtc_read_time, | 380 | .read_time = twl4030_rtc_read_time, |
405 | .set_time = twl4030_rtc_set_time, | 381 | .set_time = twl4030_rtc_set_time, |
406 | .read_alarm = twl4030_rtc_read_alarm, | 382 | .read_alarm = twl4030_rtc_read_alarm, |
407 | .set_alarm = twl4030_rtc_set_alarm, | 383 | .set_alarm = twl4030_rtc_set_alarm, |
384 | .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, | ||
385 | .update_irq_enable = twl4030_rtc_update_irq_enable, | ||
408 | }; | 386 | }; |
409 | 387 | ||
410 | /*----------------------------------------------------------------------*/ | 388 | /*----------------------------------------------------------------------*/ |
@@ -422,7 +400,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
422 | rtc = rtc_device_register(pdev->name, | 400 | rtc = rtc_device_register(pdev->name, |
423 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); | 401 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); |
424 | if (IS_ERR(rtc)) { | 402 | if (IS_ERR(rtc)) { |
425 | ret = -EINVAL; | 403 | ret = PTR_ERR(rtc); |
426 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 404 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
427 | PTR_ERR(rtc)); | 405 | PTR_ERR(rtc)); |
428 | goto out0; | 406 | goto out0; |
@@ -432,7 +410,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
432 | platform_set_drvdata(pdev, rtc); | 410 | platform_set_drvdata(pdev, rtc); |
433 | 411 | ||
434 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 412 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
435 | |||
436 | if (ret < 0) | 413 | if (ret < 0) |
437 | goto out1; | 414 | goto out1; |
438 | 415 | ||
@@ -475,7 +452,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
475 | 452 | ||
476 | return ret; | 453 | return ret; |
477 | 454 | ||
478 | |||
479 | out2: | 455 | out2: |
480 | free_irq(irq, rtc); | 456 | free_irq(irq, rtc); |
481 | out1: | 457 | out1: |
@@ -506,8 +482,9 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
506 | 482 | ||
507 | static void twl4030_rtc_shutdown(struct platform_device *pdev) | 483 | static void twl4030_rtc_shutdown(struct platform_device *pdev) |
508 | { | 484 | { |
509 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | | 485 | /* mask timer interrupts, but leave alarm interrupts on to enable |
510 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | 486 | power-on when alarm is triggered */ |
487 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | ||
511 | } | 488 | } |
512 | 489 | ||
513 | #ifdef CONFIG_PM | 490 | #ifdef CONFIG_PM |