diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2010-05-16 18:40:56 -0400 |
---|---|---|
committer | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2010-05-16 18:40:56 -0400 |
commit | b65b34895437915f411882dd40d704eb0863ffb0 (patch) | |
tree | 3e9302ab09c9a9068fd8fd80708ef3a35b55e665 /drivers/rtc | |
parent | 88cc83772a3c7756b9f2b4ba835545ad90a08409 (diff) | |
parent | b57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff) |
Merge mainline (v2.6.34-rc7)
Diffstat (limited to 'drivers/rtc')
49 files changed, 1390 insertions, 162 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8167e9e6827a..6a1303759432 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -175,6 +175,16 @@ config RTC_DRV_MAX6900 | |||
175 | This driver can also be built as a module. If so, the module | 175 | This driver can also be built as a module. If so, the module |
176 | will be called rtc-max6900. | 176 | will be called rtc-max6900. |
177 | 177 | ||
178 | config RTC_DRV_MAX8925 | ||
179 | tristate "Maxim MAX8925" | ||
180 | depends on MFD_MAX8925 | ||
181 | help | ||
182 | If you say yes here you will get support for the | ||
183 | RTC of Maxim MAX8925 PMIC. | ||
184 | |||
185 | This driver can also be built as a module. If so, the module | ||
186 | will be called rtc-max8925. | ||
187 | |||
178 | config RTC_DRV_RS5C372 | 188 | config RTC_DRV_RS5C372 |
179 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 189 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
180 | help | 190 | help |
@@ -868,4 +878,14 @@ config RTC_DRV_MC13783 | |||
868 | help | 878 | help |
869 | This enables support for the Freescale MC13783 PMIC RTC | 879 | This enables support for the Freescale MC13783 PMIC RTC |
870 | 880 | ||
881 | config RTC_DRV_MPC5121 | ||
882 | tristate "Freescale MPC5121 built-in RTC" | ||
883 | depends on PPC_MPC512x && RTC_CLASS | ||
884 | help | ||
885 | If you say yes here you will get support for the | ||
886 | built-in RTC MPC5121. | ||
887 | |||
888 | This driver can also be built as a module. If so, the module | ||
889 | will be called rtc-mpc5121. | ||
890 | |||
871 | endif # RTC_CLASS | 891 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e5160fddc446..44ef194a9573 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -52,9 +52,11 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | |||
52 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 52 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
53 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 53 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
54 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 54 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
55 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | ||
55 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 56 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
56 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | 57 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o |
57 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 58 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
59 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | ||
58 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 60 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
59 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | 61 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o |
60 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 62 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index be5a6b73e601..565562ba6ac9 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/kdev_t.h> | 16 | #include <linux/kdev_t.h> |
17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
18 | #include <linux/slab.h> | ||
18 | 19 | ||
19 | #include "rtc-core.h" | 20 | #include "rtc-core.h" |
20 | 21 | ||
@@ -226,6 +227,7 @@ static void __exit rtc_exit(void) | |||
226 | { | 227 | { |
227 | rtc_dev_exit(); | 228 | rtc_dev_exit(); |
228 | class_destroy(rtc_class); | 229 | class_destroy(rtc_class); |
230 | idr_destroy(&rtc_idr); | ||
229 | } | 231 | } |
230 | 232 | ||
231 | subsys_initcall(rtc_init); | 233 | subsys_initcall(rtc_init); |
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 33c0e98243ee..bc90b091f195 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c | |||
@@ -22,48 +22,57 @@ | |||
22 | * the best guess is to add 0.5s. | 22 | * the best guess is to add 0.5s. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | int rtc_hctosys_ret = -ENODEV; | ||
26 | |||
25 | static int __init rtc_hctosys(void) | 27 | static int __init rtc_hctosys(void) |
26 | { | 28 | { |
27 | int err; | 29 | int err = -ENODEV; |
28 | struct rtc_time tm; | 30 | struct rtc_time tm; |
31 | struct timespec tv = { | ||
32 | .tv_nsec = NSEC_PER_SEC >> 1, | ||
33 | }; | ||
29 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | 34 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); |
30 | 35 | ||
31 | if (rtc == NULL) { | 36 | if (rtc == NULL) { |
32 | printk("%s: unable to open rtc device (%s)\n", | 37 | pr_err("%s: unable to open rtc device (%s)\n", |
33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); | 38 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); |
34 | return -ENODEV; | 39 | goto err_open; |
35 | } | 40 | } |
36 | 41 | ||
37 | err = rtc_read_time(rtc, &tm); | 42 | err = rtc_read_time(rtc, &tm); |
38 | if (err == 0) { | 43 | if (err) { |
39 | err = rtc_valid_tm(&tm); | 44 | dev_err(rtc->dev.parent, |
40 | if (err == 0) { | 45 | "hctosys: unable to read the hardware clock\n"); |
41 | struct timespec tv; | 46 | goto err_read; |
42 | 47 | ||
43 | tv.tv_nsec = NSEC_PER_SEC >> 1; | 48 | } |
44 | 49 | ||
45 | rtc_tm_to_time(&tm, &tv.tv_sec); | 50 | err = rtc_valid_tm(&tm); |
51 | if (err) { | ||
52 | dev_err(rtc->dev.parent, | ||
53 | "hctosys: invalid date/time\n"); | ||
54 | goto err_invalid; | ||
55 | } | ||
46 | 56 | ||
47 | do_settimeofday(&tv); | 57 | rtc_tm_to_time(&tm, &tv.tv_sec); |
48 | 58 | ||
49 | dev_info(rtc->dev.parent, | 59 | do_settimeofday(&tv); |
50 | "setting system clock to " | ||
51 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
53 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
54 | (unsigned int) tv.tv_sec); | ||
55 | } | ||
56 | else | ||
57 | dev_err(rtc->dev.parent, | ||
58 | "hctosys: invalid date/time\n"); | ||
59 | } | ||
60 | else | ||
61 | dev_err(rtc->dev.parent, | ||
62 | "hctosys: unable to read the hardware clock\n"); | ||
63 | 60 | ||
61 | dev_info(rtc->dev.parent, | ||
62 | "setting system clock to " | ||
63 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
64 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
65 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
66 | (unsigned int) tv.tv_sec); | ||
67 | |||
68 | err_invalid: | ||
69 | err_read: | ||
64 | rtc_class_close(rtc); | 70 | rtc_class_close(rtc); |
65 | 71 | ||
66 | return 0; | 72 | err_open: |
73 | rtc_hctosys_ret = err; | ||
74 | |||
75 | return err; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | late_initcall(rtc_hctosys); | 78 | late_initcall(rtc_hctosys); |
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 8825695777df..b2752b6e7a2f 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
16 | 17 | ||
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 86c61f143515..f677e0710ca1 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/ioctl.h> | 20 | #include <linux/ioctl.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #include <mach/board.h> | 23 | #include <mach/board.h> |
23 | #include <mach/at91_rtt.h> | 24 | #include <mach/at91_rtt.h> |
@@ -161,7 +162,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
161 | if (offset == 0) | 162 | if (offset == 0) |
162 | return -EILSEQ; | 163 | return -EILSEQ; |
163 | 164 | ||
164 | memset(alrm, 0, sizeof(alrm)); | 165 | memset(alrm, 0, sizeof(*alrm)); |
165 | if (alarm != ALARM_DISABLED && offset != 0) { | 166 | if (alarm != ALARM_DISABLED && offset != 0) { |
166 | rtc_time_to_tm(offset + alarm, tm); | 167 | rtc_time_to_tm(offset + alarm, tm); |
167 | 168 | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index b11485b9f21c..72b2bcc2c224 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/platform_device.h> | 51 | #include <linux/platform_device.h> |
52 | #include <linux/rtc.h> | 52 | #include <linux/rtc.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | ||
54 | 55 | ||
55 | #include <asm/blackfin.h> | 56 | #include <asm/blackfin.h> |
56 | 57 | ||
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index 280fe48ada0b..128270ce355d 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/rtc.h> | 11 | #include <linux/rtc.h> |
12 | #include <linux/bcd.h> | 12 | #include <linux/bcd.h> |
13 | #include <linux/slab.h> | ||
13 | 14 | ||
14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | 15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | 16 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); |
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 03ea530981d1..316f484999b5 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/pm.h> | 14 | #include <linux/pm.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/slab.h> | ||
17 | 18 | ||
18 | /* | 19 | /* |
19 | * Registers in the COH 901 331 | 20 | * Registers in the COH 901 331 |
@@ -271,12 +272,13 @@ static int coh901331_resume(struct platform_device *pdev) | |||
271 | { | 272 | { |
272 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | 273 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); |
273 | 274 | ||
274 | if (device_may_wakeup(&pdev->dev)) | 275 | if (device_may_wakeup(&pdev->dev)) { |
275 | disable_irq_wake(rtap->irq); | 276 | disable_irq_wake(rtap->irq); |
276 | else | 277 | } else { |
277 | clk_enable(rtap->clk); | 278 | clk_enable(rtap->clk); |
278 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); | 279 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); |
279 | clk_disable(rtap->clk); | 280 | clk_disable(rtap->clk); |
281 | } | ||
280 | return 0; | 282 | return 0; |
281 | } | 283 | } |
282 | #else | 284 | #else |
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 4aedc705518c..45cd8c9f5a39 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/rtc.h> | 9 | #include <linux/rtc.h> |
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/slab.h> | ||
12 | 13 | ||
13 | #define DRV_VERSION "0.2" | 14 | #define DRV_VERSION "0.2" |
14 | 15 | ||
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 4fcb16bbff4a..bf430f9091ed 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/ds1286.h> | 19 | #include <linux/ds1286.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #define DRV_VERSION "1.0" | 23 | #define DRV_VERSION "1.0" |
23 | 24 | ||
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 9630e7d3314e..7836c9cec557 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/bcd.h> | 13 | #include <linux/bcd.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
15 | #include <linux/workqueue.h> | 16 | #include <linux/workqueue.h> |
16 | 17 | ||
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 5317bbcbc7a0..61945734ad00 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/bcd.h> | 25 | #include <linux/bcd.h> |
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/slab.h> | ||
27 | 28 | ||
28 | #define DS1374_REG_TOD0 0x00 /* Time of Day */ | 29 | #define DS1374_REG_TOD0 0x00 /* Time of Day */ |
29 | #define DS1374_REG_TOD1 0x01 | 30 | #define DS1374_REG_TOD1 0x01 |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index cdb705057091..26a86d235051 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/slab.h> | ||
22 | 23 | ||
23 | #define DS1390_REG_100THS 0x00 | 24 | #define DS1390_REG_100THS 0x00 |
24 | #define DS1390_REG_SECONDS 0x01 | 25 | #define DS1390_REG_SECONDS 0x01 |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 4166b84cb514..06b8566c4532 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/bcd.h> | 17 | #include <linux/bcd.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/gfp.h> | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index ed1ef7c9cc06..244f9994bcbb 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/gfp.h> | ||
14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
15 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index a1273360a44e..2b4b0bc42d6f 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/gfp.h> | ||
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/jiffies.h> | 20 | #include <linux/jiffies.h> |
20 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
@@ -184,6 +185,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
184 | pdata->size_nvram = pdata->size - RTC_SIZE; | 185 | pdata->size_nvram = pdata->size - RTC_SIZE; |
185 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | 186 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; |
186 | 187 | ||
188 | sysfs_bin_attr_init(&pdata->nvram_attr); | ||
187 | pdata->nvram_attr.attr.name = "nvram"; | 189 | pdata->nvram_attr.attr.name = "nvram"; |
188 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | 190 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; |
189 | pdata->nvram_attr.read = ds1742_nvram_read; | 191 | pdata->nvram_attr.read = ds1742_nvram_read; |
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 9da02d108b73..11ae64dcbf3c 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/gfp.h> | ||
16 | 17 | ||
17 | #define EP93XX_RTC_DATA 0x000 | 18 | #define EP93XX_RTC_DATA 0x000 |
18 | #define EP93XX_RTC_MATCH 0x004 | 19 | #define EP93XX_RTC_MATCH 0x004 |
@@ -115,6 +116,15 @@ static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev, | |||
115 | } | 116 | } |
116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); | 117 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); |
117 | 118 | ||
119 | static struct attribute *ep93xx_rtc_attrs[] = { | ||
120 | &dev_attr_comp_preload.attr, | ||
121 | &dev_attr_comp_delete.attr, | ||
122 | NULL | ||
123 | }; | ||
124 | |||
125 | static const struct attribute_group ep93xx_rtc_sysfs_files = { | ||
126 | .attrs = ep93xx_rtc_attrs, | ||
127 | }; | ||
118 | 128 | ||
119 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) | 129 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) |
120 | { | 130 | { |
@@ -123,27 +133,22 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
123 | struct rtc_device *rtc; | 133 | struct rtc_device *rtc; |
124 | int err; | 134 | int err; |
125 | 135 | ||
126 | ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL); | 136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); |
127 | if (ep93xx_rtc == NULL) | 137 | if (!ep93xx_rtc) |
128 | return -ENOMEM; | 138 | return -ENOMEM; |
129 | 139 | ||
130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
131 | if (res == NULL) { | 141 | if (!res) |
132 | err = -ENXIO; | 142 | return -ENXIO; |
133 | goto fail_free; | ||
134 | } | ||
135 | 143 | ||
136 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 144 | if (!devm_request_mem_region(&pdev->dev, res->start, |
137 | if (res == NULL) { | 145 | resource_size(res), pdev->name)) |
138 | err = -EBUSY; | 146 | return -EBUSY; |
139 | goto fail_free; | ||
140 | } | ||
141 | 147 | ||
142 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | 148 | ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start, |
143 | if (ep93xx_rtc->mmio_base == NULL) { | 149 | resource_size(res)); |
144 | err = -ENXIO; | 150 | if (!ep93xx_rtc->mmio_base) |
145 | goto fail; | 151 | return -ENXIO; |
146 | } | ||
147 | 152 | ||
148 | pdev->dev.platform_data = ep93xx_rtc; | 153 | pdev->dev.platform_data = ep93xx_rtc; |
149 | 154 | ||
@@ -151,53 +156,34 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
151 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 156 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
152 | if (IS_ERR(rtc)) { | 157 | if (IS_ERR(rtc)) { |
153 | err = PTR_ERR(rtc); | 158 | err = PTR_ERR(rtc); |
154 | goto fail; | 159 | goto exit; |
155 | } | 160 | } |
156 | 161 | ||
157 | platform_set_drvdata(pdev, rtc); | 162 | platform_set_drvdata(pdev, rtc); |
158 | 163 | ||
159 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); | 164 | err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
160 | if (err) | 165 | if (err) |
161 | goto fail; | 166 | goto fail; |
162 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
163 | if (err) { | ||
164 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
165 | goto fail; | ||
166 | } | ||
167 | 167 | ||
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | fail: | 170 | fail: |
171 | if (ep93xx_rtc->mmio_base) { | 171 | platform_set_drvdata(pdev, NULL); |
172 | iounmap(ep93xx_rtc->mmio_base); | 172 | rtc_device_unregister(rtc); |
173 | pdev->dev.platform_data = NULL; | 173 | exit: |
174 | } | 174 | pdev->dev.platform_data = NULL; |
175 | release_mem_region(res->start, resource_size(res)); | ||
176 | fail_free: | ||
177 | kfree(ep93xx_rtc); | ||
178 | return err; | 175 | return err; |
179 | } | 176 | } |
180 | 177 | ||
181 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 178 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
182 | { | 179 | { |
183 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 180 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
184 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
185 | struct resource *res; | ||
186 | |||
187 | /* cleanup sysfs */ | ||
188 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
189 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
190 | 181 | ||
182 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | ||
183 | platform_set_drvdata(pdev, NULL); | ||
191 | rtc_device_unregister(rtc); | 184 | rtc_device_unregister(rtc); |
192 | |||
193 | iounmap(ep93xx_rtc->mmio_base); | ||
194 | pdev->dev.platform_data = NULL; | 185 | pdev->dev.platform_data = NULL; |
195 | 186 | ||
196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
197 | release_mem_region(res->start, resource_size(res)); | ||
198 | |||
199 | platform_set_drvdata(pdev, NULL); | ||
200 | |||
201 | return 0; | 187 | return 0; |
202 | } | 188 | } |
203 | 189 | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 812c66755083..ff6fce61ea41 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define FM3130_RTC_CONTROL (0x0) | 18 | #define FM3130_RTC_CONTROL (0x0) |
18 | #define FM3130_CAL_CONTROL (0x1) | 19 | #define FM3130_CAL_CONTROL (0x1) |
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 8cb5b8959e5b..7410875e5838 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index ede43b846859..365ff3ac2348 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/rtc/m48t59.h> | 20 | #include <linux/rtc/m48t59.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/slab.h> | ||
22 | 23 | ||
23 | #ifndef NO_IRQ | 24 | #ifndef NO_IRQ |
24 | #define NO_IRQ (-1) | 25 | #define NO_IRQ (-1) |
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c new file mode 100644 index 000000000000..174036dda786 --- /dev/null +++ b/drivers/rtc/rtc-max8925.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8925 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mfd/max8925.h> | ||
18 | |||
19 | enum { | ||
20 | RTC_SEC = 0, | ||
21 | RTC_MIN, | ||
22 | RTC_HOUR, | ||
23 | RTC_WEEKDAY, | ||
24 | RTC_DATE, | ||
25 | RTC_MONTH, | ||
26 | RTC_YEAR1, | ||
27 | RTC_YEAR2, | ||
28 | }; | ||
29 | |||
30 | #define MAX8925_RTC_SEC 0x00 | ||
31 | #define MAX8925_RTC_MIN 0x01 | ||
32 | #define MAX8925_RTC_HOUR 0x02 | ||
33 | #define MAX8925_RTC_WEEKDAY 0x03 | ||
34 | #define MAX8925_RTC_DATE 0x04 | ||
35 | #define MAX8925_RTC_MONTH 0x05 | ||
36 | #define MAX8925_RTC_YEAR1 0x06 | ||
37 | #define MAX8925_RTC_YEAR2 0x07 | ||
38 | #define MAX8925_ALARM0_SEC 0x08 | ||
39 | #define MAX8925_ALARM0_MIN 0x09 | ||
40 | #define MAX8925_ALARM0_HOUR 0x0a | ||
41 | #define MAX8925_ALARM0_WEEKDAY 0x0b | ||
42 | #define MAX8925_ALARM0_DATE 0x0c | ||
43 | #define MAX8925_ALARM0_MON 0x0d | ||
44 | #define MAX8925_ALARM0_YEAR1 0x0e | ||
45 | #define MAX8925_ALARM0_YEAR2 0x0f | ||
46 | #define MAX8925_ALARM1_SEC 0x10 | ||
47 | #define MAX8925_ALARM1_MIN 0x11 | ||
48 | #define MAX8925_ALARM1_HOUR 0x12 | ||
49 | #define MAX8925_ALARM1_WEEKDAY 0x13 | ||
50 | #define MAX8925_ALARM1_DATE 0x14 | ||
51 | #define MAX8925_ALARM1_MON 0x15 | ||
52 | #define MAX8925_ALARM1_YEAR1 0x16 | ||
53 | #define MAX8925_ALARM1_YEAR2 0x17 | ||
54 | #define MAX8925_RTC_CNTL 0x1b | ||
55 | #define MAX8925_RTC_STATUS 0x20 | ||
56 | |||
57 | #define TIME_NUM 8 | ||
58 | #define ALARM_1SEC (1 << 7) | ||
59 | #define HOUR_12 (1 << 7) | ||
60 | #define HOUR_AM_PM (1 << 5) | ||
61 | #define ALARM0_IRQ (1 << 3) | ||
62 | #define ALARM1_IRQ (1 << 2) | ||
63 | #define ALARM0_STATUS (1 << 2) | ||
64 | #define ALARM1_STATUS (1 << 1) | ||
65 | |||
66 | |||
67 | struct max8925_rtc_info { | ||
68 | struct rtc_device *rtc_dev; | ||
69 | struct max8925_chip *chip; | ||
70 | struct i2c_client *rtc; | ||
71 | struct device *dev; | ||
72 | }; | ||
73 | |||
74 | static irqreturn_t rtc_update_handler(int irq, void *data) | ||
75 | { | ||
76 | struct max8925_rtc_info *info = (struct max8925_rtc_info *)data; | ||
77 | |||
78 | /* disable ALARM0 except for 1SEC alarm */ | ||
79 | max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0); | ||
80 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
81 | return IRQ_HANDLED; | ||
82 | } | ||
83 | |||
84 | static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len) | ||
85 | { | ||
86 | if (len < TIME_NUM) | ||
87 | return -EINVAL; | ||
88 | tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000 | ||
89 | + (buf[RTC_YEAR2] & 0xf) * 100 | ||
90 | + (buf[RTC_YEAR1] >> 4) * 10 | ||
91 | + (buf[RTC_YEAR1] & 0xf); | ||
92 | tm->tm_year -= 1900; | ||
93 | tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10 | ||
94 | + (buf[RTC_MONTH] & 0x0f); | ||
95 | tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10 | ||
96 | + (buf[RTC_DATE] & 0x0f); | ||
97 | tm->tm_wday = buf[RTC_WEEKDAY] & 0x07; | ||
98 | if (buf[RTC_HOUR] & HOUR_12) { | ||
99 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10 | ||
100 | + (buf[RTC_HOUR] & 0x0f); | ||
101 | if (buf[RTC_HOUR] & HOUR_AM_PM) | ||
102 | tm->tm_hour += 12; | ||
103 | } else | ||
104 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10 | ||
105 | + (buf[RTC_HOUR] & 0x0f); | ||
106 | tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10 | ||
107 | + (buf[RTC_MIN] & 0x0f); | ||
108 | tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10 | ||
109 | + (buf[RTC_SEC] & 0x0f); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int data_calc(unsigned char *buf, struct rtc_time *tm, int len) | ||
114 | { | ||
115 | unsigned char high, low; | ||
116 | |||
117 | if (len < TIME_NUM) | ||
118 | return -EINVAL; | ||
119 | |||
120 | high = (tm->tm_year + 1900) / 1000; | ||
121 | low = (tm->tm_year + 1900) / 100; | ||
122 | low = low - high * 10; | ||
123 | buf[RTC_YEAR2] = (high << 4) + low; | ||
124 | high = (tm->tm_year + 1900) / 10; | ||
125 | low = tm->tm_year + 1900; | ||
126 | low = low - high * 10; | ||
127 | high = high - (high / 10) * 10; | ||
128 | buf[RTC_YEAR1] = (high << 4) + low; | ||
129 | high = tm->tm_mon / 10; | ||
130 | low = tm->tm_mon; | ||
131 | low = low - high * 10; | ||
132 | buf[RTC_MONTH] = (high << 4) + low; | ||
133 | high = tm->tm_mday / 10; | ||
134 | low = tm->tm_mday; | ||
135 | low = low - high * 10; | ||
136 | buf[RTC_DATE] = (high << 4) + low; | ||
137 | buf[RTC_WEEKDAY] = tm->tm_wday; | ||
138 | high = tm->tm_hour / 10; | ||
139 | low = tm->tm_hour; | ||
140 | low = low - high * 10; | ||
141 | buf[RTC_HOUR] = (high << 4) + low; | ||
142 | high = tm->tm_min / 10; | ||
143 | low = tm->tm_min; | ||
144 | low = low - high * 10; | ||
145 | buf[RTC_MIN] = (high << 4) + low; | ||
146 | high = tm->tm_sec / 10; | ||
147 | low = tm->tm_sec; | ||
148 | low = low - high * 10; | ||
149 | buf[RTC_SEC] = (high << 4) + low; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
154 | { | ||
155 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
156 | unsigned char buf[TIME_NUM]; | ||
157 | int ret; | ||
158 | |||
159 | ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); | ||
160 | if (ret < 0) | ||
161 | goto out; | ||
162 | ret = tm_calc(tm, buf, TIME_NUM); | ||
163 | out: | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
168 | { | ||
169 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
170 | unsigned char buf[TIME_NUM]; | ||
171 | int ret; | ||
172 | |||
173 | ret = data_calc(buf, tm, TIME_NUM); | ||
174 | if (ret < 0) | ||
175 | goto out; | ||
176 | ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); | ||
177 | out: | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
182 | { | ||
183 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
184 | unsigned char buf[TIME_NUM]; | ||
185 | int ret; | ||
186 | |||
187 | ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); | ||
188 | if (ret < 0) | ||
189 | goto out; | ||
190 | ret = tm_calc(&alrm->time, buf, TIME_NUM); | ||
191 | if (ret < 0) | ||
192 | goto out; | ||
193 | ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK); | ||
194 | if (ret < 0) | ||
195 | goto out; | ||
196 | if ((ret & ALARM0_IRQ) == 0) | ||
197 | alrm->enabled = 1; | ||
198 | else | ||
199 | alrm->enabled = 0; | ||
200 | ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS); | ||
201 | if (ret < 0) | ||
202 | goto out; | ||
203 | if (ret & ALARM0_STATUS) | ||
204 | alrm->pending = 1; | ||
205 | else | ||
206 | alrm->pending = 0; | ||
207 | out: | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
212 | { | ||
213 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
214 | unsigned char buf[TIME_NUM]; | ||
215 | int ret; | ||
216 | |||
217 | ret = data_calc(buf, &alrm->time, TIME_NUM); | ||
218 | if (ret < 0) | ||
219 | goto out; | ||
220 | ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | /* only enable alarm on year/month/day/hour/min/sec */ | ||
224 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); | ||
225 | if (ret < 0) | ||
226 | goto out; | ||
227 | out: | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static const struct rtc_class_ops max8925_rtc_ops = { | ||
232 | .read_time = max8925_rtc_read_time, | ||
233 | .set_time = max8925_rtc_set_time, | ||
234 | .read_alarm = max8925_rtc_read_alarm, | ||
235 | .set_alarm = max8925_rtc_set_alarm, | ||
236 | }; | ||
237 | |||
238 | static int __devinit max8925_rtc_probe(struct platform_device *pdev) | ||
239 | { | ||
240 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
241 | struct max8925_rtc_info *info; | ||
242 | int irq, ret; | ||
243 | |||
244 | info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL); | ||
245 | if (!info) | ||
246 | return -ENOMEM; | ||
247 | info->chip = chip; | ||
248 | info->rtc = chip->rtc; | ||
249 | info->dev = &pdev->dev; | ||
250 | irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0; | ||
251 | |||
252 | ret = request_threaded_irq(irq, NULL, rtc_update_handler, | ||
253 | IRQF_ONESHOT, "rtc-alarm0", info); | ||
254 | if (ret < 0) { | ||
255 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
256 | irq, ret); | ||
257 | goto out_irq; | ||
258 | } | ||
259 | |||
260 | info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev, | ||
261 | &max8925_rtc_ops, THIS_MODULE); | ||
262 | ret = PTR_ERR(info->rtc_dev); | ||
263 | if (IS_ERR(info->rtc_dev)) { | ||
264 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
265 | goto out_rtc; | ||
266 | } | ||
267 | |||
268 | dev_set_drvdata(&pdev->dev, info); | ||
269 | platform_set_drvdata(pdev, info); | ||
270 | |||
271 | return 0; | ||
272 | out_rtc: | ||
273 | free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); | ||
274 | out_irq: | ||
275 | kfree(info); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static int __devexit max8925_rtc_remove(struct platform_device *pdev) | ||
280 | { | ||
281 | struct max8925_rtc_info *info = platform_get_drvdata(pdev); | ||
282 | |||
283 | if (info) { | ||
284 | free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); | ||
285 | rtc_device_unregister(info->rtc_dev); | ||
286 | kfree(info); | ||
287 | } | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static struct platform_driver max8925_rtc_driver = { | ||
292 | .driver = { | ||
293 | .name = "max8925-rtc", | ||
294 | .owner = THIS_MODULE, | ||
295 | }, | ||
296 | .probe = max8925_rtc_probe, | ||
297 | .remove = __devexit_p(max8925_rtc_remove), | ||
298 | }; | ||
299 | |||
300 | static int __init max8925_rtc_init(void) | ||
301 | { | ||
302 | return platform_driver_register(&max8925_rtc_driver); | ||
303 | } | ||
304 | module_init(max8925_rtc_init); | ||
305 | |||
306 | static void __exit max8925_rtc_exit(void) | ||
307 | { | ||
308 | platform_driver_unregister(&max8925_rtc_driver); | ||
309 | } | ||
310 | module_exit(max8925_rtc_exit); | ||
311 | |||
312 | MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); | ||
313 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
314 | MODULE_LICENSE("GPL"); | ||
315 | |||
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c index 850f983c039c..675bfb515367 100644 --- a/drivers/rtc/rtc-mc13783.c +++ b/drivers/rtc/rtc-mc13783.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
17 | 18 | ||
18 | #define DRIVER_NAME "mc13783-rtc" | 19 | #define DRIVER_NAME "mc13783-rtc" |
@@ -28,6 +29,34 @@ struct mc13783_rtc { | |||
28 | int valid; | 29 | int valid; |
29 | }; | 30 | }; |
30 | 31 | ||
32 | static int mc13783_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13783 *mc13783, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; | ||
42 | return func(priv->mc13783, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13783_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13783_lock(priv->mc13783); | ||
52 | |||
53 | ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13783_unlock(priv->mc13783); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
31 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | 60 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) |
32 | { | 61 | { |
33 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 62 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
@@ -78,6 +107,7 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
78 | { | 107 | { |
79 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 108 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
80 | unsigned int seconds, days; | 109 | unsigned int seconds, days; |
110 | unsigned int alarmseconds; | ||
81 | int ret; | 111 | int ret; |
82 | 112 | ||
83 | seconds = secs % 86400; | 113 | seconds = secs % 86400; |
@@ -86,7 +116,22 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
86 | mc13783_lock(priv->mc13783); | 116 | mc13783_lock(priv->mc13783); |
87 | 117 | ||
88 | /* | 118 | /* |
89 | * first write seconds=0 to prevent a day switch between writing days | 119 | * temporarily invalidate alarm to prevent triggering it when the day is |
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13783_reg_write(priv->mc13783, | ||
128 | MC13783_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
90 | * and seconds below | 135 | * and seconds below |
91 | */ | 136 | */ |
92 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | 137 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); |
@@ -101,11 +146,19 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
101 | if (unlikely(ret)) | 146 | if (unlikely(ret)) |
102 | goto out; | 147 | goto out; |
103 | 148 | ||
104 | ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST); | 149 | /* restore alarm */ |
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13783_reg_write(priv->mc13783, | ||
152 | MC13783_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST); | ||
105 | if (unlikely(ret)) | 158 | if (unlikely(ret)) |
106 | goto out; | 159 | goto out; |
107 | 160 | ||
108 | ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | 161 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); |
109 | out: | 162 | out: |
110 | priv->valid = !ret; | 163 | priv->valid = !ret; |
111 | 164 | ||
@@ -114,41 +167,139 @@ out: | |||
114 | return ret; | 167 | return ret; |
115 | } | 168 | } |
116 | 169 | ||
117 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | 170 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
118 | { | 171 | { |
119 | struct mc13783_rtc *priv = dev; | 172 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
120 | struct mc13783 *mc13783 = priv->mc13783; | 173 | unsigned seconds, days; |
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
121 | 177 | ||
122 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | 178 | mc13783_lock(priv->mc13783); |
123 | 179 | ||
124 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | 180 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); |
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
125 | 191 | ||
126 | mc13783_ackirq(mc13783, irq); | 192 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, |
193 | &enabled, &pending); | ||
127 | 194 | ||
128 | return IRQ_HANDLED; | 195 | out: |
196 | mc13783_unlock(priv->mc13783); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
129 | } | 210 | } |
130 | 211 | ||
131 | static int mc13783_rtc_update_irq_enable(struct device *dev, | 212 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
132 | unsigned int enabled) | ||
133 | { | 213 | { |
134 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 214 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
135 | int ret = -ENODATA; | 215 | unsigned long s1970; |
216 | unsigned seconds, days; | ||
217 | int ret; | ||
136 | 218 | ||
137 | mc13783_lock(priv->mc13783); | 219 | mc13783_lock(priv->mc13783); |
138 | if (!priv->valid) | 220 | |
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
139 | goto out; | 224 | goto out; |
140 | 225 | ||
141 | ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783, | 226 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); |
142 | MC13783_IRQ_1HZ); | 227 | if (unlikely(ret)) |
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13783_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); | ||
250 | |||
143 | out: | 251 | out: |
144 | mc13783_unlock(priv->mc13783); | 252 | mc13783_unlock(priv->mc13783); |
145 | 253 | ||
146 | return ret; | 254 | return ret; |
147 | } | 255 | } |
148 | 256 | ||
257 | static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13783_rtc *priv = dev; | ||
260 | struct mc13783 *mc13783 = priv->mc13783; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13783_irq_ack(mc13783, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13783_rtc *priv = dev; | ||
274 | struct mc13783 *mc13783 = priv->mc13783; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13783_irq_ack(mc13783, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13783_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); | ||
295 | } | ||
296 | |||
149 | static const struct rtc_class_ops mc13783_rtc_ops = { | 297 | static const struct rtc_class_ops mc13783_rtc_ops = { |
150 | .read_time = mc13783_rtc_read_time, | 298 | .read_time = mc13783_rtc_read_time, |
151 | .set_mmss = mc13783_rtc_set_mmss, | 299 | .set_mmss = mc13783_rtc_set_mmss, |
300 | .read_alarm = mc13783_rtc_read_alarm, | ||
301 | .set_alarm = mc13783_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, | ||
152 | .update_irq_enable = mc13783_rtc_update_irq_enable, | 303 | .update_irq_enable = mc13783_rtc_update_irq_enable, |
153 | }; | 304 | }; |
154 | 305 | ||
@@ -160,7 +311,7 @@ static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | |||
160 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | 311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); |
161 | priv->valid = 0; | 312 | priv->valid = 0; |
162 | 313 | ||
163 | mc13783_mask(mc13783, irq); | 314 | mc13783_irq_mask(mc13783, irq); |
164 | 315 | ||
165 | return IRQ_HANDLED; | 316 | return IRQ_HANDLED; |
166 | } | 317 | } |
@@ -169,50 +320,64 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
169 | { | 320 | { |
170 | int ret; | 321 | int ret; |
171 | struct mc13783_rtc *priv; | 322 | struct mc13783_rtc *priv; |
323 | struct mc13783 *mc13783; | ||
324 | int rtcrst_pending; | ||
172 | 325 | ||
173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
174 | if (!priv) | 327 | if (!priv) |
175 | return -ENOMEM; | 328 | return -ENOMEM; |
176 | 329 | ||
177 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | 330 | mc13783 = dev_get_drvdata(pdev->dev.parent); |
178 | platform_set_drvdata(pdev, priv); | 331 | priv->mc13783 = mc13783; |
179 | 332 | ||
180 | priv->valid = 1; | 333 | platform_set_drvdata(pdev, priv); |
181 | 334 | ||
182 | mc13783_lock(priv->mc13783); | 335 | mc13783_lock(mc13783); |
183 | 336 | ||
184 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, | 337 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, |
185 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | 338 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); |
186 | if (ret) | 339 | if (ret) |
187 | goto err_reset_irq_request; | 340 | goto err_reset_irq_request; |
188 | 341 | ||
189 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, | 342 | ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST, |
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ, | ||
190 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | 350 | mc13783_rtc_update_handler, DRIVER_NAME, priv); |
191 | if (ret) | 351 | if (ret) |
192 | goto err_update_irq_request; | 352 | goto err_update_irq_request; |
193 | 353 | ||
194 | mc13783_unlock(priv->mc13783); | 354 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA, |
355 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
195 | 358 | ||
196 | priv->rtc = rtc_device_register(pdev->name, | 359 | priv->rtc = rtc_device_register(pdev->name, |
197 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | 360 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); |
198 | |||
199 | if (IS_ERR(priv->rtc)) { | 361 | if (IS_ERR(priv->rtc)) { |
200 | ret = PTR_ERR(priv->rtc); | 362 | ret = PTR_ERR(priv->rtc); |
201 | 363 | ||
202 | mc13783_lock(priv->mc13783); | 364 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); |
365 | err_alarm_irq_request: | ||
203 | 366 | ||
204 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 367 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); |
205 | err_update_irq_request: | 368 | err_update_irq_request: |
206 | 369 | ||
207 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 370 | err_reset_irq_status: |
208 | err_reset_irq_request: | ||
209 | 371 | ||
210 | mc13783_unlock(priv->mc13783); | 372 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); |
373 | err_reset_irq_request: | ||
211 | 374 | ||
212 | platform_set_drvdata(pdev, NULL); | 375 | platform_set_drvdata(pdev, NULL); |
213 | kfree(priv); | 376 | kfree(priv); |
214 | } | 377 | } |
215 | 378 | ||
379 | mc13783_unlock(mc13783); | ||
380 | |||
216 | return ret; | 381 | return ret; |
217 | } | 382 | } |
218 | 383 | ||
@@ -220,10 +385,11 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | |||
220 | { | 385 | { |
221 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | 386 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); |
222 | 387 | ||
223 | rtc_device_unregister(priv->rtc); | ||
224 | |||
225 | mc13783_lock(priv->mc13783); | 388 | mc13783_lock(priv->mc13783); |
226 | 389 | ||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
227 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 393 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); |
228 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 394 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); |
229 | 395 | ||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c new file mode 100644 index 000000000000..f0dbf9cb8f9c --- /dev/null +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -0,0 +1,388 @@ | |||
1 | /* | ||
2 | * Real-time clock driver for MPC5121 | ||
3 | * | ||
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | ||
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/of_device.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | struct mpc5121_rtc_regs { | ||
21 | u8 set_time; /* RTC + 0x00 */ | ||
22 | u8 hour_set; /* RTC + 0x01 */ | ||
23 | u8 minute_set; /* RTC + 0x02 */ | ||
24 | u8 second_set; /* RTC + 0x03 */ | ||
25 | |||
26 | u8 set_date; /* RTC + 0x04 */ | ||
27 | u8 month_set; /* RTC + 0x05 */ | ||
28 | u8 weekday_set; /* RTC + 0x06 */ | ||
29 | u8 date_set; /* RTC + 0x07 */ | ||
30 | |||
31 | u8 write_sw; /* RTC + 0x08 */ | ||
32 | u8 sw_set; /* RTC + 0x09 */ | ||
33 | u16 year_set; /* RTC + 0x0a */ | ||
34 | |||
35 | u8 alm_enable; /* RTC + 0x0c */ | ||
36 | u8 alm_hour_set; /* RTC + 0x0d */ | ||
37 | u8 alm_min_set; /* RTC + 0x0e */ | ||
38 | u8 int_enable; /* RTC + 0x0f */ | ||
39 | |||
40 | u8 reserved1; | ||
41 | u8 hour; /* RTC + 0x11 */ | ||
42 | u8 minute; /* RTC + 0x12 */ | ||
43 | u8 second; /* RTC + 0x13 */ | ||
44 | |||
45 | u8 month; /* RTC + 0x14 */ | ||
46 | u8 wday_mday; /* RTC + 0x15 */ | ||
47 | u16 year; /* RTC + 0x16 */ | ||
48 | |||
49 | u8 int_alm; /* RTC + 0x18 */ | ||
50 | u8 int_sw; /* RTC + 0x19 */ | ||
51 | u8 alm_status; /* RTC + 0x1a */ | ||
52 | u8 sw_minute; /* RTC + 0x1b */ | ||
53 | |||
54 | u8 bus_error_1; /* RTC + 0x1c */ | ||
55 | u8 int_day; /* RTC + 0x1d */ | ||
56 | u8 int_min; /* RTC + 0x1e */ | ||
57 | u8 int_sec; /* RTC + 0x1f */ | ||
58 | |||
59 | /* | ||
60 | * target_time: | ||
61 | * intended to be used for hibernation but hibernation | ||
62 | * does not work on silicon rev 1.5 so use it for non-volatile | ||
63 | * storage of offset between the actual_time register and linux | ||
64 | * time | ||
65 | */ | ||
66 | u32 target_time; /* RTC + 0x20 */ | ||
67 | /* | ||
68 | * actual_time: | ||
69 | * readonly time since VBAT_RTC was last connected | ||
70 | */ | ||
71 | u32 actual_time; /* RTC + 0x24 */ | ||
72 | u32 keep_alive; /* RTC + 0x28 */ | ||
73 | }; | ||
74 | |||
75 | struct mpc5121_rtc_data { | ||
76 | unsigned irq; | ||
77 | unsigned irq_periodic; | ||
78 | struct mpc5121_rtc_regs __iomem *regs; | ||
79 | struct rtc_device *rtc; | ||
80 | struct rtc_wkalrm wkalarm; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * Update second/minute/hour registers. | ||
85 | * | ||
86 | * This is just so alarm will work. | ||
87 | */ | ||
88 | static void mpc5121_rtc_update_smh(struct mpc5121_rtc_regs __iomem *regs, | ||
89 | struct rtc_time *tm) | ||
90 | { | ||
91 | out_8(®s->second_set, tm->tm_sec); | ||
92 | out_8(®s->minute_set, tm->tm_min); | ||
93 | out_8(®s->hour_set, tm->tm_hour); | ||
94 | |||
95 | /* set time sequence */ | ||
96 | out_8(®s->set_time, 0x1); | ||
97 | out_8(®s->set_time, 0x3); | ||
98 | out_8(®s->set_time, 0x1); | ||
99 | out_8(®s->set_time, 0x0); | ||
100 | } | ||
101 | |||
102 | static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
103 | { | ||
104 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
105 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
106 | unsigned long now; | ||
107 | |||
108 | /* | ||
109 | * linux time is actual_time plus the offset saved in target_time | ||
110 | */ | ||
111 | now = in_be32(®s->actual_time) + in_be32(®s->target_time); | ||
112 | |||
113 | rtc_time_to_tm(now, tm); | ||
114 | |||
115 | /* | ||
116 | * update second minute hour registers | ||
117 | * so alarms will work | ||
118 | */ | ||
119 | mpc5121_rtc_update_smh(regs, tm); | ||
120 | |||
121 | return rtc_valid_tm(tm); | ||
122 | } | ||
123 | |||
124 | static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
125 | { | ||
126 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
127 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
128 | int ret; | ||
129 | unsigned long now; | ||
130 | |||
131 | /* | ||
132 | * The actual_time register is read only so we write the offset | ||
133 | * between it and linux time to the target_time register. | ||
134 | */ | ||
135 | ret = rtc_tm_to_time(tm, &now); | ||
136 | if (ret == 0) | ||
137 | out_be32(®s->target_time, now - in_be32(®s->actual_time)); | ||
138 | |||
139 | /* | ||
140 | * update second minute hour registers | ||
141 | * so alarms will work | ||
142 | */ | ||
143 | mpc5121_rtc_update_smh(regs, tm); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
149 | { | ||
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
151 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
152 | |||
153 | *alarm = rtc->wkalarm; | ||
154 | |||
155 | alarm->pending = in_8(®s->alm_status); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int mpc5121_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
161 | { | ||
162 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
163 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
164 | |||
165 | /* | ||
166 | * the alarm has no seconds so deal with it | ||
167 | */ | ||
168 | if (alarm->time.tm_sec) { | ||
169 | alarm->time.tm_sec = 0; | ||
170 | alarm->time.tm_min++; | ||
171 | if (alarm->time.tm_min >= 60) { | ||
172 | alarm->time.tm_min = 0; | ||
173 | alarm->time.tm_hour++; | ||
174 | if (alarm->time.tm_hour >= 24) | ||
175 | alarm->time.tm_hour = 0; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | alarm->time.tm_mday = -1; | ||
180 | alarm->time.tm_mon = -1; | ||
181 | alarm->time.tm_year = -1; | ||
182 | |||
183 | out_8(®s->alm_min_set, alarm->time.tm_min); | ||
184 | out_8(®s->alm_hour_set, alarm->time.tm_hour); | ||
185 | |||
186 | out_8(®s->alm_enable, alarm->enabled); | ||
187 | |||
188 | rtc->wkalarm = *alarm; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static irqreturn_t mpc5121_rtc_handler(int irq, void *dev) | ||
193 | { | ||
194 | struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev); | ||
195 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
196 | |||
197 | if (in_8(®s->int_alm)) { | ||
198 | /* acknowledge and clear status */ | ||
199 | out_8(®s->int_alm, 1); | ||
200 | out_8(®s->alm_status, 1); | ||
201 | |||
202 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | |||
206 | return IRQ_NONE; | ||
207 | } | ||
208 | |||
209 | static irqreturn_t mpc5121_rtc_handler_upd(int irq, void *dev) | ||
210 | { | ||
211 | struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev); | ||
212 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
213 | |||
214 | if (in_8(®s->int_sec) && (in_8(®s->int_enable) & 0x1)) { | ||
215 | /* acknowledge */ | ||
216 | out_8(®s->int_sec, 1); | ||
217 | |||
218 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
219 | return IRQ_HANDLED; | ||
220 | } | ||
221 | |||
222 | return IRQ_NONE; | ||
223 | } | ||
224 | |||
225 | static int mpc5121_rtc_alarm_irq_enable(struct device *dev, | ||
226 | unsigned int enabled) | ||
227 | { | ||
228 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
229 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
230 | int val; | ||
231 | |||
232 | if (enabled) | ||
233 | val = 1; | ||
234 | else | ||
235 | val = 0; | ||
236 | |||
237 | out_8(®s->alm_enable, val); | ||
238 | rtc->wkalarm.enabled = val; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int mpc5121_rtc_update_irq_enable(struct device *dev, | ||
244 | unsigned int enabled) | ||
245 | { | ||
246 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
247 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
248 | int val; | ||
249 | |||
250 | val = in_8(®s->int_enable); | ||
251 | |||
252 | if (enabled) | ||
253 | val = (val & ~0x8) | 0x1; | ||
254 | else | ||
255 | val &= ~0x1; | ||
256 | |||
257 | out_8(®s->int_enable, val); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct rtc_class_ops mpc5121_rtc_ops = { | ||
263 | .read_time = mpc5121_rtc_read_time, | ||
264 | .set_time = mpc5121_rtc_set_time, | ||
265 | .read_alarm = mpc5121_rtc_read_alarm, | ||
266 | .set_alarm = mpc5121_rtc_set_alarm, | ||
267 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, | ||
269 | }; | ||
270 | |||
271 | static int __devinit mpc5121_rtc_probe(struct of_device *op, | ||
272 | const struct of_device_id *match) | ||
273 | { | ||
274 | struct mpc5121_rtc_data *rtc; | ||
275 | int err = 0; | ||
276 | u32 ka; | ||
277 | |||
278 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
279 | if (!rtc) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | rtc->regs = of_iomap(op->node, 0); | ||
283 | if (!rtc->regs) { | ||
284 | dev_err(&op->dev, "%s: couldn't map io space\n", __func__); | ||
285 | err = -ENOSYS; | ||
286 | goto out_free; | ||
287 | } | ||
288 | |||
289 | device_init_wakeup(&op->dev, 1); | ||
290 | |||
291 | dev_set_drvdata(&op->dev, rtc); | ||
292 | |||
293 | rtc->irq = irq_of_parse_and_map(op->node, 1); | ||
294 | err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, | ||
295 | "mpc5121-rtc", &op->dev); | ||
296 | if (err) { | ||
297 | dev_err(&op->dev, "%s: could not request irq: %i\n", | ||
298 | __func__, rtc->irq); | ||
299 | goto out_dispose; | ||
300 | } | ||
301 | |||
302 | rtc->irq_periodic = irq_of_parse_and_map(op->node, 0); | ||
303 | err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, | ||
304 | IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); | ||
305 | if (err) { | ||
306 | dev_err(&op->dev, "%s: could not request irq: %i\n", | ||
307 | __func__, rtc->irq_periodic); | ||
308 | goto out_dispose2; | ||
309 | } | ||
310 | |||
311 | ka = in_be32(&rtc->regs->keep_alive); | ||
312 | if (ka & 0x02) { | ||
313 | dev_warn(&op->dev, | ||
314 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
315 | out_be32(&rtc->regs->keep_alive, ka); | ||
316 | } | ||
317 | |||
318 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
319 | &mpc5121_rtc_ops, THIS_MODULE); | ||
320 | if (IS_ERR(rtc->rtc)) { | ||
321 | err = PTR_ERR(rtc->rtc); | ||
322 | goto out_free_irq; | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | |||
327 | out_free_irq: | ||
328 | free_irq(rtc->irq_periodic, &op->dev); | ||
329 | out_dispose2: | ||
330 | irq_dispose_mapping(rtc->irq_periodic); | ||
331 | free_irq(rtc->irq, &op->dev); | ||
332 | out_dispose: | ||
333 | irq_dispose_mapping(rtc->irq); | ||
334 | iounmap(rtc->regs); | ||
335 | out_free: | ||
336 | kfree(rtc); | ||
337 | |||
338 | return err; | ||
339 | } | ||
340 | |||
341 | static int __devexit mpc5121_rtc_remove(struct of_device *op) | ||
342 | { | ||
343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); | ||
344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
345 | |||
346 | /* disable interrupt, so there are no nasty surprises */ | ||
347 | out_8(®s->alm_enable, 0); | ||
348 | out_8(®s->int_enable, in_8(®s->int_enable) & ~0x1); | ||
349 | |||
350 | rtc_device_unregister(rtc->rtc); | ||
351 | iounmap(rtc->regs); | ||
352 | free_irq(rtc->irq, &op->dev); | ||
353 | free_irq(rtc->irq_periodic, &op->dev); | ||
354 | irq_dispose_mapping(rtc->irq); | ||
355 | irq_dispose_mapping(rtc->irq_periodic); | ||
356 | dev_set_drvdata(&op->dev, NULL); | ||
357 | kfree(rtc); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | ||
363 | { .compatible = "fsl,mpc5121-rtc", }, | ||
364 | {}, | ||
365 | }; | ||
366 | |||
367 | static struct of_platform_driver mpc5121_rtc_driver = { | ||
368 | .owner = THIS_MODULE, | ||
369 | .name = "mpc5121-rtc", | ||
370 | .match_table = mpc5121_rtc_match, | ||
371 | .probe = mpc5121_rtc_probe, | ||
372 | .remove = __devexit_p(mpc5121_rtc_remove), | ||
373 | }; | ||
374 | |||
375 | static int __init mpc5121_rtc_init(void) | ||
376 | { | ||
377 | return of_register_platform_driver(&mpc5121_rtc_driver); | ||
378 | } | ||
379 | module_init(mpc5121_rtc_init); | ||
380 | |||
381 | static void __exit mpc5121_rtc_exit(void) | ||
382 | { | ||
383 | of_unregister_platform_driver(&mpc5121_rtc_driver); | ||
384 | } | ||
385 | module_exit(mpc5121_rtc_exit); | ||
386 | |||
387 | MODULE_LICENSE("GPL"); | ||
388 | MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); | ||
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index 5f5968a48925..b2fff0ca49f8 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | 18 | ||
18 | enum { | 19 | enum { |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index dc052ce6e63a..bcca47298554 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/gfp.h> | ||
16 | 17 | ||
17 | 18 | ||
18 | #define RTC_TIME_REG_OFFS 0 | 19 | #define RTC_TIME_REG_OFFS 0 |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 6bd5072d4eb7..d71fe61db1d6 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
@@ -383,21 +384,29 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
383 | struct rtc_device *rtc; | 384 | struct rtc_device *rtc; |
384 | struct rtc_plat_data *pdata = NULL; | 385 | struct rtc_plat_data *pdata = NULL; |
385 | u32 reg; | 386 | u32 reg; |
386 | int ret, rate; | 387 | unsigned long rate; |
388 | int ret; | ||
387 | 389 | ||
388 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 390 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
389 | if (!res) | 391 | if (!res) |
390 | return -ENODEV; | 392 | return -ENODEV; |
391 | 393 | ||
392 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 394 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
393 | if (!pdata) | 395 | if (!pdata) |
394 | return -ENOMEM; | 396 | return -ENOMEM; |
395 | 397 | ||
396 | pdata->ioaddr = ioremap(res->start, resource_size(res)); | 398 | if (!devm_request_mem_region(&pdev->dev, res->start, |
399 | resource_size(res), pdev->name)) | ||
400 | return -EBUSY; | ||
401 | |||
402 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
403 | resource_size(res)); | ||
397 | 404 | ||
398 | clk = clk_get(&pdev->dev, "ckil"); | 405 | clk = clk_get(&pdev->dev, "ckil"); |
399 | if (IS_ERR(clk)) | 406 | if (IS_ERR(clk)) { |
400 | return PTR_ERR(clk); | 407 | ret = PTR_ERR(clk); |
408 | goto exit_free_pdata; | ||
409 | } | ||
401 | 410 | ||
402 | rate = clk_get_rate(clk); | 411 | rate = clk_get_rate(clk); |
403 | clk_put(clk); | 412 | clk_put(clk); |
@@ -409,8 +418,7 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
409 | else if (rate == 38400) | 418 | else if (rate == 38400) |
410 | reg = RTC_INPUT_CLK_38400HZ; | 419 | reg = RTC_INPUT_CLK_38400HZ; |
411 | else { | 420 | else { |
412 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", | 421 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); |
413 | clk_get_rate(clk)); | ||
414 | ret = -EINVAL; | 422 | ret = -EINVAL; |
415 | goto exit_free_pdata; | 423 | goto exit_free_pdata; |
416 | } | 424 | } |
@@ -446,8 +454,8 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
446 | pdata->irq = platform_get_irq(pdev, 0); | 454 | pdata->irq = platform_get_irq(pdev, 0); |
447 | 455 | ||
448 | if (pdata->irq >= 0 && | 456 | if (pdata->irq >= 0 && |
449 | request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, | 457 | devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, |
450 | pdev->name, pdev) < 0) { | 458 | IRQF_SHARED, pdev->name, pdev) < 0) { |
451 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 459 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
452 | pdata->irq = -1; | 460 | pdata->irq = -1; |
453 | } | 461 | } |
@@ -455,10 +463,10 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
455 | return 0; | 463 | return 0; |
456 | 464 | ||
457 | exit_put_clk: | 465 | exit_put_clk: |
466 | clk_disable(pdata->clk); | ||
458 | clk_put(pdata->clk); | 467 | clk_put(pdata->clk); |
459 | 468 | ||
460 | exit_free_pdata: | 469 | exit_free_pdata: |
461 | kfree(pdata); | ||
462 | 470 | ||
463 | return ret; | 471 | return ret; |
464 | } | 472 | } |
@@ -469,12 +477,8 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) | |||
469 | 477 | ||
470 | rtc_device_unregister(pdata->rtc); | 478 | rtc_device_unregister(pdata->rtc); |
471 | 479 | ||
472 | if (pdata->irq >= 0) | ||
473 | free_irq(pdata->irq, pdev); | ||
474 | |||
475 | clk_disable(pdata->clk); | 480 | clk_disable(pdata->clk); |
476 | clk_put(pdata->clk); | 481 | clk_put(pdata->clk); |
477 | kfree(pdata); | ||
478 | platform_set_drvdata(pdev, NULL); | 482 | platform_set_drvdata(pdev, NULL); |
479 | 483 | ||
480 | return 0; | 484 | return 0; |
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index bf59c9c586b2..a351bd5d8176 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index a99c28992d21..25c0b3fd44f1 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/mfd/ezx-pcap.h> | 18 | #include <linux/mfd/ezx-pcap.h> |
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | 22 | ||
22 | struct pcap_rtc { | 23 | struct pcap_rtc { |
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index e75df9d50e27..71bab0ef5443 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | #include <linux/slab.h> | ||
42 | #include <linux/rtc.h> | 43 | #include <linux/rtc.h> |
43 | #include <linux/spi/spi.h> | 44 | #include <linux/spi/spi.h> |
44 | 45 | ||
@@ -315,7 +316,7 @@ kfree_exit: | |||
315 | return ret; | 316 | return ret; |
316 | } | 317 | } |
317 | 318 | ||
318 | static int pcf2123_remove(struct spi_device *spi) | 319 | static int __devexit pcf2123_remove(struct spi_device *spi) |
319 | { | 320 | { |
320 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; | 321 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; |
321 | int i; | 322 | int i; |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 854c3cb365a1..16edf94ab42f 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
23 | #include <linux/bcd.h> | 24 | #include <linux/bcd.h> |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 65f346b2fbae..1af42b4a6f59 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | #define DRV_VERSION "0.4.3" | 22 | #define DRV_VERSION "0.4.3" |
22 | 23 | ||
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 457231bb1029..bbdb2f02798a 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/amba/bus.h> | 14 | #include <linux/amba/bus.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define RTC_DR (0) | 18 | #define RTC_DR (0) |
18 | #define RTC_MR (4) | 19 | #define RTC_MR (4) |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 0264b117893b..3587d9922f28 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -7,6 +7,9 @@ | |||
7 | * | 7 | * |
8 | * Copyright 2006 (c) MontaVista Software, Inc. | 8 | * Copyright 2006 (c) MontaVista Software, Inc. |
9 | * | 9 | * |
10 | * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | ||
11 | * Copyright 2010 (c) ST-Ericsson AB | ||
12 | * | ||
10 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 15 | * as published by the Free Software Foundation; either version |
@@ -18,6 +21,10 @@ | |||
18 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
19 | #include <linux/amba/bus.h> | 22 | #include <linux/amba/bus.h> |
20 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/bcd.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/version.h> | ||
27 | #include <linux/slab.h> | ||
21 | 28 | ||
22 | /* | 29 | /* |
23 | * Register definitions | 30 | * Register definitions |
@@ -30,35 +37,207 @@ | |||
30 | #define RTC_RIS 0x14 /* Raw interrupt status register */ | 37 | #define RTC_RIS 0x14 /* Raw interrupt status register */ |
31 | #define RTC_MIS 0x18 /* Masked interrupt status register */ | 38 | #define RTC_MIS 0x18 /* Masked interrupt status register */ |
32 | #define RTC_ICR 0x1c /* Interrupt clear register */ | 39 | #define RTC_ICR 0x1c /* Interrupt clear register */ |
40 | /* ST variants have additional timer functionality */ | ||
41 | #define RTC_TDR 0x20 /* Timer data read register */ | ||
42 | #define RTC_TLR 0x24 /* Timer data load register */ | ||
43 | #define RTC_TCR 0x28 /* Timer control register */ | ||
44 | #define RTC_YDR 0x30 /* Year data read register */ | ||
45 | #define RTC_YMR 0x34 /* Year match register */ | ||
46 | #define RTC_YLR 0x38 /* Year data load register */ | ||
47 | |||
48 | #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ | ||
49 | |||
50 | #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ | ||
51 | |||
52 | /* Common bit definitions for Interrupt status and control registers */ | ||
53 | #define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */ | ||
54 | #define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */ | ||
55 | |||
56 | /* Common bit definations for ST v2 for reading/writing time */ | ||
57 | #define RTC_SEC_SHIFT 0 | ||
58 | #define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */ | ||
59 | #define RTC_MIN_SHIFT 6 | ||
60 | #define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */ | ||
61 | #define RTC_HOUR_SHIFT 12 | ||
62 | #define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */ | ||
63 | #define RTC_WDAY_SHIFT 17 | ||
64 | #define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */ | ||
65 | #define RTC_MDAY_SHIFT 20 | ||
66 | #define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */ | ||
67 | #define RTC_MON_SHIFT 25 | ||
68 | #define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */ | ||
69 | |||
70 | #define RTC_TIMER_FREQ 32768 | ||
33 | 71 | ||
34 | struct pl031_local { | 72 | struct pl031_local { |
35 | struct rtc_device *rtc; | 73 | struct rtc_device *rtc; |
36 | void __iomem *base; | 74 | void __iomem *base; |
75 | u8 hw_designer; | ||
76 | u8 hw_revision:4; | ||
37 | }; | 77 | }; |
38 | 78 | ||
39 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | 79 | static int pl031_alarm_irq_enable(struct device *dev, |
80 | unsigned int enabled) | ||
81 | { | ||
82 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
83 | unsigned long imsc; | ||
84 | |||
85 | /* Clear any pending alarm interrupts. */ | ||
86 | writel(RTC_BIT_AI, ldata->base + RTC_ICR); | ||
87 | |||
88 | imsc = readl(ldata->base + RTC_IMSC); | ||
89 | |||
90 | if (enabled == 1) | ||
91 | writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
92 | else | ||
93 | writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Convert Gregorian date to ST v2 RTC format. | ||
100 | */ | ||
101 | static int pl031_stv2_tm_to_time(struct device *dev, | ||
102 | struct rtc_time *tm, unsigned long *st_time, | ||
103 | unsigned long *bcd_year) | ||
104 | { | ||
105 | int year = tm->tm_year + 1900; | ||
106 | int wday = tm->tm_wday; | ||
107 | |||
108 | /* wday masking is not working in hardware so wday must be valid */ | ||
109 | if (wday < -1 || wday > 6) { | ||
110 | dev_err(dev, "invalid wday value %d\n", tm->tm_wday); | ||
111 | return -EINVAL; | ||
112 | } else if (wday == -1) { | ||
113 | /* wday is not provided, calculate it here */ | ||
114 | unsigned long time; | ||
115 | struct rtc_time calc_tm; | ||
116 | |||
117 | rtc_tm_to_time(tm, &time); | ||
118 | rtc_time_to_tm(time, &calc_tm); | ||
119 | wday = calc_tm.tm_wday; | ||
120 | } | ||
121 | |||
122 | *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8); | ||
123 | |||
124 | *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT) | ||
125 | | (tm->tm_mday << RTC_MDAY_SHIFT) | ||
126 | | ((wday + 1) << RTC_WDAY_SHIFT) | ||
127 | | (tm->tm_hour << RTC_HOUR_SHIFT) | ||
128 | | (tm->tm_min << RTC_MIN_SHIFT) | ||
129 | | (tm->tm_sec << RTC_SEC_SHIFT); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Convert ST v2 RTC format to Gregorian date. | ||
136 | */ | ||
137 | static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year, | ||
138 | struct rtc_time *tm) | ||
139 | { | ||
140 | tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100); | ||
141 | tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1; | ||
142 | tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT); | ||
143 | tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1; | ||
144 | tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT); | ||
145 | tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT); | ||
146 | tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT); | ||
147 | |||
148 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
149 | tm->tm_year -= 1900; | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm) | ||
155 | { | ||
156 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
157 | |||
158 | pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR), | ||
159 | readl(ldata->base + RTC_YDR), tm); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm) | ||
165 | { | ||
166 | unsigned long time; | ||
167 | unsigned long bcd_year; | ||
168 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
169 | int ret; | ||
170 | |||
171 | ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); | ||
172 | if (ret == 0) { | ||
173 | writel(bcd_year, ldata->base + RTC_YLR); | ||
174 | writel(time, ldata->base + RTC_LR); | ||
175 | } | ||
176 | |||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
40 | { | 181 | { |
41 | struct rtc_device *rtc = dev_id; | 182 | struct pl031_local *ldata = dev_get_drvdata(dev); |
183 | int ret; | ||
42 | 184 | ||
43 | rtc_update_irq(rtc, 1, RTC_AF); | 185 | ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), |
186 | readl(ldata->base + RTC_YMR), &alarm->time); | ||
44 | 187 | ||
45 | return IRQ_HANDLED; | 188 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; |
189 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
190 | |||
191 | return ret; | ||
46 | } | 192 | } |
47 | 193 | ||
48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 194 | static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
49 | { | 195 | { |
50 | struct pl031_local *ldata = dev_get_drvdata(dev); | 196 | struct pl031_local *ldata = dev_get_drvdata(dev); |
197 | unsigned long time; | ||
198 | unsigned long bcd_year; | ||
199 | int ret; | ||
200 | |||
201 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
202 | ret = rtc_valid_tm(&alarm->time); | ||
203 | if (ret == 0) { | ||
204 | ret = pl031_stv2_tm_to_time(dev, &alarm->time, | ||
205 | &time, &bcd_year); | ||
206 | if (ret == 0) { | ||
207 | writel(bcd_year, ldata->base + RTC_YMR); | ||
208 | writel(time, ldata->base + RTC_MR); | ||
209 | |||
210 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | ||
218 | { | ||
219 | struct pl031_local *ldata = dev_id; | ||
220 | unsigned long rtcmis; | ||
221 | unsigned long events = 0; | ||
222 | |||
223 | rtcmis = readl(ldata->base + RTC_MIS); | ||
224 | if (rtcmis) { | ||
225 | writel(rtcmis, ldata->base + RTC_ICR); | ||
226 | |||
227 | if (rtcmis & RTC_BIT_AI) | ||
228 | events |= (RTC_AF | RTC_IRQF); | ||
229 | |||
230 | /* Timer interrupt is only available in ST variants */ | ||
231 | if ((rtcmis & RTC_BIT_PI) && | ||
232 | (ldata->hw_designer == AMBA_VENDOR_ST)) | ||
233 | events |= (RTC_PF | RTC_IRQF); | ||
234 | |||
235 | rtc_update_irq(ldata->rtc, 1, events); | ||
51 | 236 | ||
52 | switch (cmd) { | 237 | return IRQ_HANDLED; |
53 | case RTC_AIE_OFF: | ||
54 | writel(1, ldata->base + RTC_MIS); | ||
55 | return 0; | ||
56 | case RTC_AIE_ON: | ||
57 | writel(0, ldata->base + RTC_MIS); | ||
58 | return 0; | ||
59 | } | 238 | } |
60 | 239 | ||
61 | return -ENOIOCTLCMD; | 240 | return IRQ_NONE; |
62 | } | 241 | } |
63 | 242 | ||
64 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) | 243 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) |
@@ -74,11 +253,14 @@ static int pl031_set_time(struct device *dev, struct rtc_time *tm) | |||
74 | { | 253 | { |
75 | unsigned long time; | 254 | unsigned long time; |
76 | struct pl031_local *ldata = dev_get_drvdata(dev); | 255 | struct pl031_local *ldata = dev_get_drvdata(dev); |
256 | int ret; | ||
77 | 257 | ||
78 | rtc_tm_to_time(tm, &time); | 258 | ret = rtc_tm_to_time(tm, &time); |
79 | writel(time, ldata->base + RTC_LR); | ||
80 | 259 | ||
81 | return 0; | 260 | if (ret == 0) |
261 | writel(time, ldata->base + RTC_LR); | ||
262 | |||
263 | return ret; | ||
82 | } | 264 | } |
83 | 265 | ||
84 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 266 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
@@ -86,8 +268,9 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
86 | struct pl031_local *ldata = dev_get_drvdata(dev); | 268 | struct pl031_local *ldata = dev_get_drvdata(dev); |
87 | 269 | ||
88 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); | 270 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); |
89 | alarm->pending = readl(ldata->base + RTC_RIS); | 271 | |
90 | alarm->enabled = readl(ldata->base + RTC_IMSC); | 272 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; |
273 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
91 | 274 | ||
92 | return 0; | 275 | return 0; |
93 | } | 276 | } |
@@ -96,22 +279,71 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
96 | { | 279 | { |
97 | struct pl031_local *ldata = dev_get_drvdata(dev); | 280 | struct pl031_local *ldata = dev_get_drvdata(dev); |
98 | unsigned long time; | 281 | unsigned long time; |
282 | int ret; | ||
283 | |||
284 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
285 | ret = rtc_valid_tm(&alarm->time); | ||
286 | if (ret == 0) { | ||
287 | ret = rtc_tm_to_time(&alarm->time, &time); | ||
288 | if (ret == 0) { | ||
289 | writel(time, ldata->base + RTC_MR); | ||
290 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | /* Periodic interrupt is only available in ST variants. */ | ||
298 | static int pl031_irq_set_state(struct device *dev, int enabled) | ||
299 | { | ||
300 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
301 | |||
302 | if (enabled == 1) { | ||
303 | /* Clear any pending timer interrupt. */ | ||
304 | writel(RTC_BIT_PI, ldata->base + RTC_ICR); | ||
305 | |||
306 | writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI, | ||
307 | ldata->base + RTC_IMSC); | ||
99 | 308 | ||
100 | rtc_tm_to_time(&alarm->time, &time); | 309 | /* Now start the timer */ |
310 | writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN, | ||
311 | ldata->base + RTC_TCR); | ||
101 | 312 | ||
102 | writel(time, ldata->base + RTC_MR); | 313 | } else { |
103 | writel(!alarm->enabled, ldata->base + RTC_MIS); | 314 | writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI), |
315 | ldata->base + RTC_IMSC); | ||
316 | |||
317 | /* Also stop the timer */ | ||
318 | writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN), | ||
319 | ldata->base + RTC_TCR); | ||
320 | } | ||
321 | /* Wait at least 1 RTC32 clock cycle to ensure next access | ||
322 | * to RTC_TCR will succeed. | ||
323 | */ | ||
324 | udelay(40); | ||
104 | 325 | ||
105 | return 0; | 326 | return 0; |
106 | } | 327 | } |
107 | 328 | ||
108 | static const struct rtc_class_ops pl031_ops = { | 329 | static int pl031_irq_set_freq(struct device *dev, int freq) |
109 | .ioctl = pl031_ioctl, | 330 | { |
110 | .read_time = pl031_read_time, | 331 | struct pl031_local *ldata = dev_get_drvdata(dev); |
111 | .set_time = pl031_set_time, | 332 | |
112 | .read_alarm = pl031_read_alarm, | 333 | /* Cant set timer if it is already enabled */ |
113 | .set_alarm = pl031_set_alarm, | 334 | if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) { |
114 | }; | 335 | dev_err(dev, "can't change frequency while timer enabled\n"); |
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | /* If self start bit in RTC_TCR is set timer will start here, | ||
340 | * but we never set that bit. Instead we start the timer when | ||
341 | * set_state is called with enabled == 1. | ||
342 | */ | ||
343 | writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
115 | 347 | ||
116 | static int pl031_remove(struct amba_device *adev) | 348 | static int pl031_remove(struct amba_device *adev) |
117 | { | 349 | { |
@@ -131,18 +363,20 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
131 | { | 363 | { |
132 | int ret; | 364 | int ret; |
133 | struct pl031_local *ldata; | 365 | struct pl031_local *ldata; |
366 | struct rtc_class_ops *ops = id->data; | ||
134 | 367 | ||
135 | ret = amba_request_regions(adev, NULL); | 368 | ret = amba_request_regions(adev, NULL); |
136 | if (ret) | 369 | if (ret) |
137 | goto err_req; | 370 | goto err_req; |
138 | 371 | ||
139 | ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); | 372 | ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); |
140 | if (!ldata) { | 373 | if (!ldata) { |
141 | ret = -ENOMEM; | 374 | ret = -ENOMEM; |
142 | goto out; | 375 | goto out; |
143 | } | 376 | } |
144 | 377 | ||
145 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); | 378 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); |
379 | |||
146 | if (!ldata->base) { | 380 | if (!ldata->base) { |
147 | ret = -ENOMEM; | 381 | ret = -ENOMEM; |
148 | goto out_no_remap; | 382 | goto out_no_remap; |
@@ -150,24 +384,36 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
150 | 384 | ||
151 | amba_set_drvdata(adev, ldata); | 385 | amba_set_drvdata(adev, ldata); |
152 | 386 | ||
153 | if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, | 387 | ldata->hw_designer = amba_manf(adev); |
154 | "rtc-pl031", ldata->rtc)) { | 388 | ldata->hw_revision = amba_rev(adev); |
155 | ret = -EIO; | 389 | |
156 | goto out_no_irq; | 390 | dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer); |
157 | } | 391 | dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); |
158 | 392 | ||
159 | ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, | 393 | /* Enable the clockwatch on ST Variants */ |
160 | THIS_MODULE); | 394 | if ((ldata->hw_designer == AMBA_VENDOR_ST) && |
395 | (ldata->hw_revision > 1)) | ||
396 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | ||
397 | ldata->base + RTC_CR); | ||
398 | |||
399 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, | ||
400 | THIS_MODULE); | ||
161 | if (IS_ERR(ldata->rtc)) { | 401 | if (IS_ERR(ldata->rtc)) { |
162 | ret = PTR_ERR(ldata->rtc); | 402 | ret = PTR_ERR(ldata->rtc); |
163 | goto out_no_rtc; | 403 | goto out_no_rtc; |
164 | } | 404 | } |
165 | 405 | ||
406 | if (request_irq(adev->irq[0], pl031_interrupt, | ||
407 | IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) { | ||
408 | ret = -EIO; | ||
409 | goto out_no_irq; | ||
410 | } | ||
411 | |||
166 | return 0; | 412 | return 0; |
167 | 413 | ||
168 | out_no_rtc: | ||
169 | free_irq(adev->irq[0], ldata->rtc); | ||
170 | out_no_irq: | 414 | out_no_irq: |
415 | rtc_device_unregister(ldata->rtc); | ||
416 | out_no_rtc: | ||
171 | iounmap(ldata->base); | 417 | iounmap(ldata->base); |
172 | amba_set_drvdata(adev, NULL); | 418 | amba_set_drvdata(adev, NULL); |
173 | out_no_remap: | 419 | out_no_remap: |
@@ -175,13 +421,57 @@ out_no_remap: | |||
175 | out: | 421 | out: |
176 | amba_release_regions(adev); | 422 | amba_release_regions(adev); |
177 | err_req: | 423 | err_req: |
424 | |||
178 | return ret; | 425 | return ret; |
179 | } | 426 | } |
180 | 427 | ||
428 | /* Operations for the original ARM version */ | ||
429 | static struct rtc_class_ops arm_pl031_ops = { | ||
430 | .read_time = pl031_read_time, | ||
431 | .set_time = pl031_set_time, | ||
432 | .read_alarm = pl031_read_alarm, | ||
433 | .set_alarm = pl031_set_alarm, | ||
434 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
435 | }; | ||
436 | |||
437 | /* The First ST derivative */ | ||
438 | static struct rtc_class_ops stv1_pl031_ops = { | ||
439 | .read_time = pl031_read_time, | ||
440 | .set_time = pl031_set_time, | ||
441 | .read_alarm = pl031_read_alarm, | ||
442 | .set_alarm = pl031_set_alarm, | ||
443 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
444 | .irq_set_state = pl031_irq_set_state, | ||
445 | .irq_set_freq = pl031_irq_set_freq, | ||
446 | }; | ||
447 | |||
448 | /* And the second ST derivative */ | ||
449 | static struct rtc_class_ops stv2_pl031_ops = { | ||
450 | .read_time = pl031_stv2_read_time, | ||
451 | .set_time = pl031_stv2_set_time, | ||
452 | .read_alarm = pl031_stv2_read_alarm, | ||
453 | .set_alarm = pl031_stv2_set_alarm, | ||
454 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
455 | .irq_set_state = pl031_irq_set_state, | ||
456 | .irq_set_freq = pl031_irq_set_freq, | ||
457 | }; | ||
458 | |||
181 | static struct amba_id pl031_ids[] __initdata = { | 459 | static struct amba_id pl031_ids[] __initdata = { |
182 | { | 460 | { |
183 | .id = 0x00041031, | 461 | .id = 0x00041031, |
184 | .mask = 0x000fffff, | 462 | .mask = 0x000fffff, |
463 | .data = &arm_pl031_ops, | ||
464 | }, | ||
465 | /* ST Micro variants */ | ||
466 | { | ||
467 | .id = 0x00180031, | ||
468 | .mask = 0x00ffffff, | ||
469 | .data = &stv1_pl031_ops, | ||
470 | }, | ||
471 | { | ||
472 | .id = 0x00280031, | ||
473 | .mask = 0x00ffffff, | ||
474 | .data = &stv2_pl031_ops, | ||
185 | }, | 475 | }, |
186 | {0, 0}, | 476 | {0, 0}, |
187 | }; | 477 | }; |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index e6351b743da6..e9c6fa035989 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/slab.h> | ||
29 | 30 | ||
30 | #include <mach/hardware.h> | 31 | #include <mach/hardware.h> |
31 | 32 | ||
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index e1313feb060f..a95f733bb15a 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/slab.h> | ||
15 | 16 | ||
16 | 17 | ||
17 | enum { | 18 | enum { |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 2099037cb3ea..368d0e63cf83 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
23 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
24 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2f2c68d476da..90cf0a6ff23e 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define DRV_VERSION "0.6" | 18 | #define DRV_VERSION "0.6" |
18 | 19 | ||
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index b1a29bcfdf13..b65c82f792d9 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/slab.h> | ||
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/bcd.h> | 25 | #include <linux/bcd.h> |
25 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e0d7b9991505..4969b6059c89 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
24 | #include <linux/slab.h> | ||
24 | 25 | ||
25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e95cc6f8d61e..5efbd5990ff8 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/slab.h> | ||
29 | #include <asm/rtc.h> | 30 | #include <asm/rtc.h> |
30 | 31 | ||
31 | #define DRV_NAME "sh-rtc" | 32 | #define DRV_NAME "sh-rtc" |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 67700831b5c9..875ba099e7a5 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/bcd.h> | 14 | #include <linux/bcd.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/gfp.h> | ||
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index d7ce1a5c857d..7e7d0c806f2d 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
27 | #include <mach/stmp3xxx.h> | 28 | #include <mach/stmp3xxx.h> |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 7dd23a6fc825..380083ca572f 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -107,8 +107,9 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, | |||
107 | char *buf) | 107 | char *buf) |
108 | { | 108 | { |
109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE | 109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE |
110 | if (strcmp(dev_name(&to_rtc_device(dev)->dev), | 110 | if (rtc_hctosys_ret == 0 && |
111 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | 111 | strcmp(dev_name(&to_rtc_device(dev)->dev), |
112 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | ||
112 | return sprintf(buf, "1\n"); | 113 | return sprintf(buf, "1\n"); |
113 | else | 114 | else |
114 | #endif | 115 | #endif |
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index c6a83a2a722c..ed1b86828124 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -57,7 +57,7 @@ enum { | |||
57 | REG_RTC_COMP_LSB_REG, | 57 | REG_RTC_COMP_LSB_REG, |
58 | REG_RTC_COMP_MSB_REG, | 58 | REG_RTC_COMP_MSB_REG, |
59 | }; | 59 | }; |
60 | const static u8 twl4030_rtc_reg_map[] = { | 60 | static const u8 twl4030_rtc_reg_map[] = { |
61 | [REG_SECONDS_REG] = 0x00, | 61 | [REG_SECONDS_REG] = 0x00, |
62 | [REG_MINUTES_REG] = 0x01, | 62 | [REG_MINUTES_REG] = 0x01, |
63 | [REG_HOURS_REG] = 0x02, | 63 | [REG_HOURS_REG] = 0x02, |
@@ -80,7 +80,7 @@ const static u8 twl4030_rtc_reg_map[] = { | |||
80 | [REG_RTC_COMP_LSB_REG] = 0x10, | 80 | [REG_RTC_COMP_LSB_REG] = 0x10, |
81 | [REG_RTC_COMP_MSB_REG] = 0x11, | 81 | [REG_RTC_COMP_MSB_REG] = 0x11, |
82 | }; | 82 | }; |
83 | const static u8 twl6030_rtc_reg_map[] = { | 83 | static const u8 twl6030_rtc_reg_map[] = { |
84 | [REG_SECONDS_REG] = 0x00, | 84 | [REG_SECONDS_REG] = 0x00, |
85 | [REG_MINUTES_REG] = 0x01, | 85 | [REG_MINUTES_REG] = 0x01, |
86 | [REG_HOURS_REG] = 0x02, | 86 | [REG_HOURS_REG] = 0x02, |
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 9ee81d8aa7c0..20bfc64a15c8 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/gfp.h> | ||
15 | #include <asm/txx9/tx4939.h> | 16 | #include <asm/txx9/tx4939.h> |
16 | 17 | ||
17 | struct tx4939rtc_plat_data { | 18 | struct tx4939rtc_plat_data { |
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index bed4cab07043..f71c3ce18036 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/rtc-v3020.h> | 28 | #include <linux/rtc-v3020.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
31 | #include <linux/slab.h> | ||
31 | 32 | ||
32 | #include <linux/io.h> | 33 | #include <linux/io.h> |
33 | 34 | ||
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 000c7e481e59..b16cfe57a484 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/bcd.h> | 20 | #include <linux/bcd.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/ioctl.h> | 22 | #include <linux/ioctl.h> |
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index f1e440521c54..3d0dc76b38af 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -307,11 +307,18 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, | |||
307 | { | 307 | { |
308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
309 | 309 | ||
310 | /* Suppress duplicate changes since genirq nests enable and | ||
311 | * disable calls. */ | ||
312 | if (enabled == wm8350->rtc.update_enabled) | ||
313 | return 0; | ||
314 | |||
310 | if (enabled) | 315 | if (enabled) |
311 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 316 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
312 | else | 317 | else |
313 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 318 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
314 | 319 | ||
320 | wm8350->rtc.update_enabled = enabled; | ||
321 | |||
315 | return 0; | 322 | return 0; |
316 | } | 323 | } |
317 | 324 | ||
@@ -478,8 +485,8 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
478 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 485 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
479 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | 486 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; |
480 | 487 | ||
481 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | 488 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); |
482 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | 489 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); |
483 | 490 | ||
484 | rtc_device_unregister(wm_rtc->rtc); | 491 | rtc_device_unregister(wm_rtc->rtc); |
485 | 492 | ||