diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/rtc | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/rtc')
58 files changed, 3438 insertions, 727 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3c20dae43ce2..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 |
@@ -242,6 +252,15 @@ config RTC_DRV_M41T80_WDT | |||
242 | If you say Y here you will get support for the | 252 | If you say Y here you will get support for the |
243 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. | 253 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
244 | 254 | ||
255 | config RTC_DRV_BQ32K | ||
256 | tristate "TI BQ32000" | ||
257 | help | ||
258 | If you say Y here you will get support for the TI | ||
259 | BQ32000 I2C RTC chip. | ||
260 | |||
261 | This driver can also be built as a module. If so, the module | ||
262 | will be called rtc-bq32k. | ||
263 | |||
245 | config RTC_DRV_DM355EVM | 264 | config RTC_DRV_DM355EVM |
246 | tristate "TI DaVinci DM355 EVM RTC" | 265 | tristate "TI DaVinci DM355 EVM RTC" |
247 | depends on MFD_DM355EVM_MSP | 266 | depends on MFD_DM355EVM_MSP |
@@ -258,14 +277,14 @@ config RTC_DRV_TWL92330 | |||
258 | the Menelaus driver; it's not separate module. | 277 | the Menelaus driver; it's not separate module. |
259 | 278 | ||
260 | config RTC_DRV_TWL4030 | 279 | config RTC_DRV_TWL4030 |
261 | tristate "TI TWL4030/TWL5030/TPS659x0" | 280 | tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" |
262 | depends on RTC_CLASS && TWL4030_CORE | 281 | depends on RTC_CLASS && TWL4030_CORE |
263 | help | 282 | help |
264 | If you say yes here you get support for the RTC on the | 283 | If you say yes here you get support for the RTC on the |
265 | TWL4030 family chips, used mostly with OMAP3 platforms. | 284 | TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. |
266 | 285 | ||
267 | This driver can also be built as a module. If so, the module | 286 | This driver can also be built as a module. If so, the module |
268 | will be called rtc-twl4030. | 287 | will be called rtc-twl. |
269 | 288 | ||
270 | config RTC_DRV_S35390A | 289 | config RTC_DRV_S35390A |
271 | tristate "Seiko Instruments S-35390A" | 290 | tristate "Seiko Instruments S-35390A" |
@@ -509,6 +528,15 @@ config RTC_DRV_M48T59 | |||
509 | This driver can also be built as a module, if so, the module | 528 | This driver can also be built as a module, if so, the module |
510 | will be called "rtc-m48t59". | 529 | will be called "rtc-m48t59". |
511 | 530 | ||
531 | config RTC_DRV_MSM6242 | ||
532 | tristate "Oki MSM6242" | ||
533 | help | ||
534 | If you say yes here you get support for the Oki MSM6242 | ||
535 | timekeeping chip. It is used in some Amiga models (e.g. A2000). | ||
536 | |||
537 | This driver can also be built as a module. If so, the module | ||
538 | will be called rtc-msm6242. | ||
539 | |||
512 | config RTC_MXC | 540 | config RTC_MXC |
513 | tristate "Freescale MXC Real Time Clock" | 541 | tristate "Freescale MXC Real Time Clock" |
514 | depends on ARCH_MXC | 542 | depends on ARCH_MXC |
@@ -529,6 +557,16 @@ config RTC_DRV_BQ4802 | |||
529 | This driver can also be built as a module. If so, the module | 557 | This driver can also be built as a module. If so, the module |
530 | will be called rtc-bq4802. | 558 | will be called rtc-bq4802. |
531 | 559 | ||
560 | config RTC_DRV_RP5C01 | ||
561 | tristate "Ricoh RP5C01" | ||
562 | help | ||
563 | If you say yes here you get support for the Ricoh RP5C01 | ||
564 | timekeeping chip. It is used in some Amiga models (e.g. A3000 | ||
565 | and A4000). | ||
566 | |||
567 | This driver can also be built as a module. If so, the module | ||
568 | will be called rtc-rp5c01. | ||
569 | |||
532 | config RTC_DRV_V3020 | 570 | config RTC_DRV_V3020 |
533 | tristate "EM Microelectronic V3020" | 571 | tristate "EM Microelectronic V3020" |
534 | help | 572 | help |
@@ -573,15 +611,22 @@ config RTC_DRV_AB3100 | |||
573 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | 611 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC |
574 | support. This chip contains a battery- and capacitor-backed RTC. | 612 | support. This chip contains a battery- and capacitor-backed RTC. |
575 | 613 | ||
614 | config RTC_DRV_NUC900 | ||
615 | tristate "NUC910/NUC920 RTC driver" | ||
616 | depends on RTC_CLASS && ARCH_W90X900 | ||
617 | help | ||
618 | If you say yes here you get support for the RTC subsystem of the | ||
619 | NUC910/NUC920 used in embedded systems. | ||
576 | 620 | ||
577 | comment "on-CPU RTC drivers" | 621 | comment "on-CPU RTC drivers" |
578 | 622 | ||
579 | config RTC_DRV_OMAP | 623 | config RTC_DRV_OMAP |
580 | tristate "TI OMAP1" | 624 | tristate "TI OMAP1" |
581 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 | 625 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX |
582 | help | 626 | help |
583 | Say "yes" here to support the real time clock on TI OMAP1 chips. | 627 | Say "yes" here to support the real time clock on TI OMAP1 and |
584 | This driver can also be built as a module called rtc-omap. | 628 | DA8xx/OMAP-L13x chips. This driver can also be built as a |
629 | module called rtc-omap. | ||
585 | 630 | ||
586 | config RTC_DRV_S3C | 631 | config RTC_DRV_S3C |
587 | tristate "Samsung S3C series SoC RTC" | 632 | tristate "Samsung S3C series SoC RTC" |
@@ -780,7 +825,7 @@ config RTC_DRV_TX4939 | |||
780 | 825 | ||
781 | config RTC_DRV_MV | 826 | config RTC_DRV_MV |
782 | tristate "Marvell SoC RTC" | 827 | tristate "Marvell SoC RTC" |
783 | depends on ARCH_KIRKWOOD | 828 | depends on ARCH_KIRKWOOD || ARCH_DOVE |
784 | help | 829 | help |
785 | If you say yes here you will get support for the in-chip RTC | 830 | If you say yes here you will get support for the in-chip RTC |
786 | that can be found in some of Marvell's SoC devices, such as | 831 | that can be found in some of Marvell's SoC devices, such as |
@@ -827,4 +872,20 @@ config RTC_DRV_PCAP | |||
827 | If you say Y here you will get support for the RTC found on | 872 | If you say Y here you will get support for the RTC found on |
828 | the PCAP2 ASIC used on some Motorola phones. | 873 | the PCAP2 ASIC used on some Motorola phones. |
829 | 874 | ||
875 | config RTC_DRV_MC13783 | ||
876 | depends on MFD_MC13783 | ||
877 | tristate "Freescale MC13783 RTC" | ||
878 | help | ||
879 | This enables support for the Freescale MC13783 PMIC RTC | ||
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 | |||
830 | endif # RTC_CLASS | 891 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index aa3fbd5517a1..44ef194a9573 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | |||
23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
24 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o | 24 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o |
25 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 25 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
26 | obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o | ||
26 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | 27 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o |
27 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 28 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
28 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 29 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
@@ -51,8 +52,13 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | |||
51 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 52 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
52 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 53 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
53 | 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 | ||
54 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 56 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
57 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | ||
58 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | ||
59 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | ||
55 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 60 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
61 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | ||
56 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 62 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
57 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | 63 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o |
58 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 64 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
@@ -64,6 +70,7 @@ obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | |||
64 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | 70 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o |
65 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 71 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
66 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | 72 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o |
73 | obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o | ||
67 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 74 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
68 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 75 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
69 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 76 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
@@ -78,7 +85,7 @@ obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | |||
78 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | 85 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o |
79 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | 86 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o |
80 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 87 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
81 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | 88 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
82 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 89 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
83 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 90 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
84 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 91 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.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 e1ec33e40e38..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 | ||
@@ -256,6 +257,8 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
256 | goto out_iounmap; | 257 | goto out_iounmap; |
257 | } | 258 | } |
258 | 259 | ||
260 | platform_set_drvdata(pdev, rtc); | ||
261 | |||
259 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 262 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
260 | &at32_rtc_ops, THIS_MODULE); | 263 | &at32_rtc_ops, THIS_MODULE); |
261 | if (IS_ERR(rtc->rtc)) { | 264 | if (IS_ERR(rtc->rtc)) { |
@@ -264,7 +267,6 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
264 | goto out_free_irq; | 267 | goto out_free_irq; |
265 | } | 268 | } |
266 | 269 | ||
267 | platform_set_drvdata(pdev, rtc); | ||
268 | device_init_wakeup(&pdev->dev, 1); | 270 | device_init_wakeup(&pdev->dev, 1); |
269 | 271 | ||
270 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", | 272 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", |
@@ -273,6 +275,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
273 | return 0; | 275 | return 0; |
274 | 276 | ||
275 | out_free_irq: | 277 | out_free_irq: |
278 | platform_set_drvdata(pdev, NULL); | ||
276 | free_irq(irq, rtc); | 279 | free_irq(irq, rtc); |
277 | out_iounmap: | 280 | out_iounmap: |
278 | iounmap(rtc->regs); | 281 | iounmap(rtc->regs); |
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-bq32k.c b/drivers/rtc/rtc-bq32k.c new file mode 100644 index 000000000000..408cc8f735be --- /dev/null +++ b/drivers/rtc/rtc-bq32k.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Driver for TI BQ32000 RTC. | ||
3 | * | ||
4 | * Copyright (C) 2009 Semihalf. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/bcd.h> | ||
17 | |||
18 | #define BQ32K_SECONDS 0x00 /* Seconds register address */ | ||
19 | #define BQ32K_SECONDS_MASK 0x7F /* Mask over seconds value */ | ||
20 | #define BQ32K_STOP 0x80 /* Oscillator Stop flat */ | ||
21 | |||
22 | #define BQ32K_MINUTES 0x01 /* Minutes register address */ | ||
23 | #define BQ32K_MINUTES_MASK 0x7F /* Mask over minutes value */ | ||
24 | #define BQ32K_OF 0x80 /* Oscillator Failure flag */ | ||
25 | |||
26 | #define BQ32K_HOURS_MASK 0x3F /* Mask over hours value */ | ||
27 | #define BQ32K_CENT 0x40 /* Century flag */ | ||
28 | #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ | ||
29 | |||
30 | struct bq32k_regs { | ||
31 | uint8_t seconds; | ||
32 | uint8_t minutes; | ||
33 | uint8_t cent_hours; | ||
34 | uint8_t day; | ||
35 | uint8_t date; | ||
36 | uint8_t month; | ||
37 | uint8_t years; | ||
38 | }; | ||
39 | |||
40 | static struct i2c_driver bq32k_driver; | ||
41 | |||
42 | static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
43 | { | ||
44 | struct i2c_client *client = to_i2c_client(dev); | ||
45 | struct i2c_msg msgs[] = { | ||
46 | { | ||
47 | .addr = client->addr, | ||
48 | .flags = 0, | ||
49 | .len = 1, | ||
50 | .buf = &off, | ||
51 | }, { | ||
52 | .addr = client->addr, | ||
53 | .flags = I2C_M_RD, | ||
54 | .len = len, | ||
55 | .buf = data, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | if (i2c_transfer(client->adapter, msgs, 2) == 2) | ||
60 | return 0; | ||
61 | |||
62 | return -EIO; | ||
63 | } | ||
64 | |||
65 | static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(dev); | ||
68 | uint8_t buffer[len + 1]; | ||
69 | |||
70 | buffer[0] = off; | ||
71 | memcpy(&buffer[1], data, len); | ||
72 | |||
73 | if (i2c_master_send(client, buffer, len + 1) == len + 1) | ||
74 | return 0; | ||
75 | |||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
80 | { | ||
81 | struct bq32k_regs regs; | ||
82 | int error; | ||
83 | |||
84 | error = bq32k_read(dev, ®s, 0, sizeof(regs)); | ||
85 | if (error) | ||
86 | return error; | ||
87 | |||
88 | tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK); | ||
89 | tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK); | ||
90 | tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK); | ||
91 | tm->tm_mday = bcd2bin(regs.date); | ||
92 | tm->tm_wday = bcd2bin(regs.day) - 1; | ||
93 | tm->tm_mon = bcd2bin(regs.month) - 1; | ||
94 | tm->tm_year = bcd2bin(regs.years) + | ||
95 | ((regs.cent_hours & BQ32K_CENT) ? 100 : 0); | ||
96 | |||
97 | return rtc_valid_tm(tm); | ||
98 | } | ||
99 | |||
100 | static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
101 | { | ||
102 | struct bq32k_regs regs; | ||
103 | |||
104 | regs.seconds = bin2bcd(tm->tm_sec); | ||
105 | regs.minutes = bin2bcd(tm->tm_min); | ||
106 | regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN; | ||
107 | regs.day = bin2bcd(tm->tm_wday + 1); | ||
108 | regs.date = bin2bcd(tm->tm_mday); | ||
109 | regs.month = bin2bcd(tm->tm_mon + 1); | ||
110 | |||
111 | if (tm->tm_year >= 100) { | ||
112 | regs.cent_hours |= BQ32K_CENT; | ||
113 | regs.years = bin2bcd(tm->tm_year - 100); | ||
114 | } else | ||
115 | regs.years = bin2bcd(tm->tm_year); | ||
116 | |||
117 | return bq32k_write(dev, ®s, 0, sizeof(regs)); | ||
118 | } | ||
119 | |||
120 | static const struct rtc_class_ops bq32k_rtc_ops = { | ||
121 | .read_time = bq32k_rtc_read_time, | ||
122 | .set_time = bq32k_rtc_set_time, | ||
123 | }; | ||
124 | |||
125 | static int bq32k_probe(struct i2c_client *client, | ||
126 | const struct i2c_device_id *id) | ||
127 | { | ||
128 | struct device *dev = &client->dev; | ||
129 | struct rtc_device *rtc; | ||
130 | uint8_t reg; | ||
131 | int error; | ||
132 | |||
133 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
134 | return -ENODEV; | ||
135 | |||
136 | /* Check Oscillator Stop flag */ | ||
137 | error = bq32k_read(dev, ®, BQ32K_SECONDS, 1); | ||
138 | if (!error && (reg & BQ32K_STOP)) { | ||
139 | dev_warn(dev, "Oscillator was halted. Restarting...\n"); | ||
140 | reg &= ~BQ32K_STOP; | ||
141 | error = bq32k_write(dev, ®, BQ32K_SECONDS, 1); | ||
142 | } | ||
143 | if (error) | ||
144 | return error; | ||
145 | |||
146 | /* Check Oscillator Failure flag */ | ||
147 | error = bq32k_read(dev, ®, BQ32K_MINUTES, 1); | ||
148 | if (!error && (reg & BQ32K_OF)) { | ||
149 | dev_warn(dev, "Oscillator Failure. Check RTC battery.\n"); | ||
150 | reg &= ~BQ32K_OF; | ||
151 | error = bq32k_write(dev, ®, BQ32K_MINUTES, 1); | ||
152 | } | ||
153 | if (error) | ||
154 | return error; | ||
155 | |||
156 | rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev, | ||
157 | &bq32k_rtc_ops, THIS_MODULE); | ||
158 | if (IS_ERR(rtc)) | ||
159 | return PTR_ERR(rtc); | ||
160 | |||
161 | i2c_set_clientdata(client, rtc); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int __devexit bq32k_remove(struct i2c_client *client) | ||
167 | { | ||
168 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
169 | |||
170 | rtc_device_unregister(rtc); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct i2c_device_id bq32k_id[] = { | ||
175 | { "bq32000", 0 }, | ||
176 | { } | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(i2c, bq32k_id); | ||
179 | |||
180 | static struct i2c_driver bq32k_driver = { | ||
181 | .driver = { | ||
182 | .name = "bq32k", | ||
183 | .owner = THIS_MODULE, | ||
184 | }, | ||
185 | .probe = bq32k_probe, | ||
186 | .remove = __devexit_p(bq32k_remove), | ||
187 | .id_table = bq32k_id, | ||
188 | }; | ||
189 | |||
190 | static __init int bq32k_init(void) | ||
191 | { | ||
192 | return i2c_add_driver(&bq32k_driver); | ||
193 | } | ||
194 | module_init(bq32k_init); | ||
195 | |||
196 | static __exit void bq32k_exit(void) | ||
197 | { | ||
198 | i2c_del_driver(&bq32k_driver); | ||
199 | } | ||
200 | module_exit(bq32k_exit); | ||
201 | |||
202 | MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>"); | ||
203 | MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver"); | ||
204 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index d00a274df8fc..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"); |
@@ -169,6 +170,8 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
169 | goto out_free; | 170 | goto out_free; |
170 | } | 171 | } |
171 | 172 | ||
173 | platform_set_drvdata(pdev, p); | ||
174 | |||
172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | 175 | p->rtc = rtc_device_register("bq4802", &pdev->dev, |
173 | &bq4802_ops, THIS_MODULE); | 176 | &bq4802_ops, THIS_MODULE); |
174 | if (IS_ERR(p->rtc)) { | 177 | if (IS_ERR(p->rtc)) { |
@@ -176,7 +179,6 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
176 | goto out_iounmap; | 179 | goto out_iounmap; |
177 | } | 180 | } |
178 | 181 | ||
179 | platform_set_drvdata(pdev, p); | ||
180 | err = 0; | 182 | err = 0; |
181 | out: | 183 | out: |
182 | return err; | 184 | return err; |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f7a4701bf863..e9aa814ddd23 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -420,49 +420,43 @@ static int cmos_irq_set_state(struct device *dev, int enabled) | |||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
423 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | 423 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
424 | |||
425 | static int | ||
426 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
427 | { | 424 | { |
428 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 425 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
429 | unsigned long flags; | 426 | unsigned long flags; |
430 | 427 | ||
431 | switch (cmd) { | 428 | if (!is_valid_irq(cmos->irq)) |
432 | case RTC_AIE_OFF: | 429 | return -EINVAL; |
433 | case RTC_AIE_ON: | ||
434 | case RTC_UIE_OFF: | ||
435 | case RTC_UIE_ON: | ||
436 | if (!is_valid_irq(cmos->irq)) | ||
437 | return -EINVAL; | ||
438 | break; | ||
439 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
440 | default: | ||
441 | return -ENOIOCTLCMD; | ||
442 | } | ||
443 | 430 | ||
444 | spin_lock_irqsave(&rtc_lock, flags); | 431 | spin_lock_irqsave(&rtc_lock, flags); |
445 | switch (cmd) { | 432 | |
446 | case RTC_AIE_OFF: /* alarm off */ | 433 | if (enabled) |
447 | cmos_irq_disable(cmos, RTC_AIE); | ||
448 | break; | ||
449 | case RTC_AIE_ON: /* alarm on */ | ||
450 | cmos_irq_enable(cmos, RTC_AIE); | 434 | cmos_irq_enable(cmos, RTC_AIE); |
451 | break; | 435 | else |
452 | case RTC_UIE_OFF: /* update off */ | 436 | cmos_irq_disable(cmos, RTC_AIE); |
453 | cmos_irq_disable(cmos, RTC_UIE); | 437 | |
454 | break; | ||
455 | case RTC_UIE_ON: /* update on */ | ||
456 | cmos_irq_enable(cmos, RTC_UIE); | ||
457 | break; | ||
458 | } | ||
459 | spin_unlock_irqrestore(&rtc_lock, flags); | 438 | spin_unlock_irqrestore(&rtc_lock, flags); |
460 | return 0; | 439 | return 0; |
461 | } | 440 | } |
462 | 441 | ||
463 | #else | 442 | static int cmos_update_irq_enable(struct device *dev, unsigned int enabled) |
464 | #define cmos_rtc_ioctl NULL | 443 | { |
465 | #endif | 444 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
445 | unsigned long flags; | ||
446 | |||
447 | if (!is_valid_irq(cmos->irq)) | ||
448 | return -EINVAL; | ||
449 | |||
450 | spin_lock_irqsave(&rtc_lock, flags); | ||
451 | |||
452 | if (enabled) | ||
453 | cmos_irq_enable(cmos, RTC_UIE); | ||
454 | else | ||
455 | cmos_irq_disable(cmos, RTC_UIE); | ||
456 | |||
457 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
458 | return 0; | ||
459 | } | ||
466 | 460 | ||
467 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | 461 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) |
468 | 462 | ||
@@ -503,14 +497,15 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
503 | #endif | 497 | #endif |
504 | 498 | ||
505 | static const struct rtc_class_ops cmos_rtc_ops = { | 499 | static const struct rtc_class_ops cmos_rtc_ops = { |
506 | .ioctl = cmos_rtc_ioctl, | 500 | .read_time = cmos_read_time, |
507 | .read_time = cmos_read_time, | 501 | .set_time = cmos_set_time, |
508 | .set_time = cmos_set_time, | 502 | .read_alarm = cmos_read_alarm, |
509 | .read_alarm = cmos_read_alarm, | 503 | .set_alarm = cmos_set_alarm, |
510 | .set_alarm = cmos_set_alarm, | 504 | .proc = cmos_procfs, |
511 | .proc = cmos_procfs, | 505 | .irq_set_freq = cmos_irq_set_freq, |
512 | .irq_set_freq = cmos_irq_set_freq, | 506 | .irq_set_state = cmos_irq_set_state, |
513 | .irq_set_state = cmos_irq_set_state, | 507 | .alarm_irq_enable = cmos_alarm_irq_enable, |
508 | .update_irq_enable = cmos_update_irq_enable, | ||
514 | }; | 509 | }; |
515 | 510 | ||
516 | /*----------------------------------------------------------------*/ | 511 | /*----------------------------------------------------------------*/ |
@@ -691,7 +686,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
691 | */ | 686 | */ |
692 | #if defined(CONFIG_ATARI) | 687 | #if defined(CONFIG_ATARI) |
693 | address_space = 64; | 688 | address_space = 64; |
694 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) | 689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) | ||
695 | address_space = 128; | 691 | address_space = 128; |
696 | #else | 692 | #else |
697 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 693 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
@@ -871,8 +867,9 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
871 | mask = RTC_IRQMASK; | 867 | mask = RTC_IRQMASK; |
872 | tmp &= ~mask; | 868 | tmp &= ~mask; |
873 | CMOS_WRITE(tmp, RTC_CONTROL); | 869 | CMOS_WRITE(tmp, RTC_CONTROL); |
874 | hpet_mask_rtc_irq_bit(mask); | ||
875 | 870 | ||
871 | /* shut down hpet emulation - we don't need it for alarm */ | ||
872 | hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE); | ||
876 | cmos_checkintr(cmos, tmp); | 873 | cmos_checkintr(cmos, tmp); |
877 | } | 874 | } |
878 | spin_unlock_irq(&rtc_lock); | 875 | spin_unlock_irq(&rtc_lock); |
@@ -1099,9 +1096,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) | |||
1099 | #define cmos_pnp_resume NULL | 1096 | #define cmos_pnp_resume NULL |
1100 | #endif | 1097 | #endif |
1101 | 1098 | ||
1102 | static void cmos_pnp_shutdown(struct device *pdev) | 1099 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) |
1103 | { | 1100 | { |
1104 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) | 1101 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) |
1105 | return; | 1102 | return; |
1106 | 1103 | ||
1107 | cmos_do_shutdown(); | 1104 | cmos_do_shutdown(); |
@@ -1120,15 +1117,12 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1120 | .id_table = rtc_ids, | 1117 | .id_table = rtc_ids, |
1121 | .probe = cmos_pnp_probe, | 1118 | .probe = cmos_pnp_probe, |
1122 | .remove = __exit_p(cmos_pnp_remove), | 1119 | .remove = __exit_p(cmos_pnp_remove), |
1120 | .shutdown = cmos_pnp_shutdown, | ||
1123 | 1121 | ||
1124 | /* flag ensures resume() gets called, and stops syslog spam */ | 1122 | /* flag ensures resume() gets called, and stops syslog spam */ |
1125 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | 1123 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, |
1126 | .suspend = cmos_pnp_suspend, | 1124 | .suspend = cmos_pnp_suspend, |
1127 | .resume = cmos_pnp_resume, | 1125 | .resume = cmos_pnp_resume, |
1128 | .driver = { | ||
1129 | .name = (char *)driver_name, | ||
1130 | .shutdown = cmos_pnp_shutdown, | ||
1131 | } | ||
1132 | }; | 1126 | }; |
1133 | 1127 | ||
1134 | #endif /* CONFIG_PNP */ | 1128 | #endif /* CONFIG_PNP */ |
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-ds1302.c b/drivers/rtc/rtc-ds1302.c index d490628b64da..532acf9b05d8 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -143,7 +143,6 @@ static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
143 | #ifdef RTC_SET_CHARGE | 143 | #ifdef RTC_SET_CHARGE |
144 | case RTC_SET_CHARGE: | 144 | case RTC_SET_CHARGE: |
145 | { | 145 | { |
146 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
147 | int tcs_val; | 146 | int tcs_val; |
148 | 147 | ||
149 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | 148 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) |
@@ -201,7 +200,7 @@ static struct platform_driver ds1302_platform_driver = { | |||
201 | .name = DRV_NAME, | 200 | .name = DRV_NAME, |
202 | .owner = THIS_MODULE, | 201 | .owner = THIS_MODULE, |
203 | }, | 202 | }, |
204 | .remove = __exit_p(ds1302_rtc_remove), | 203 | .remove = __devexit_p(ds1302_rtc_remove), |
205 | }; | 204 | }; |
206 | 205 | ||
207 | static int __init ds1302_rtc_init(void) | 206 | static int __init ds1302_rtc_init(void) |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 2736b11a1b1e..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 | ||
@@ -617,7 +618,6 @@ static struct bin_attribute nvram = { | |||
617 | static int __devinit ds1305_probe(struct spi_device *spi) | 618 | static int __devinit ds1305_probe(struct spi_device *spi) |
618 | { | 619 | { |
619 | struct ds1305 *ds1305; | 620 | struct ds1305 *ds1305; |
620 | struct rtc_device *rtc; | ||
621 | int status; | 621 | int status; |
622 | u8 addr, value; | 622 | u8 addr, value; |
623 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | 623 | struct ds1305_platform_data *pdata = spi->dev.platform_data; |
@@ -756,14 +756,13 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
756 | dev_dbg(&spi->dev, "AM/PM\n"); | 756 | dev_dbg(&spi->dev, "AM/PM\n"); |
757 | 757 | ||
758 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | 758 | /* register RTC ... from here on, ds1305->ctrl needs locking */ |
759 | rtc = rtc_device_register("ds1305", &spi->dev, | 759 | ds1305->rtc = rtc_device_register("ds1305", &spi->dev, |
760 | &ds1305_ops, THIS_MODULE); | 760 | &ds1305_ops, THIS_MODULE); |
761 | if (IS_ERR(rtc)) { | 761 | if (IS_ERR(ds1305->rtc)) { |
762 | status = PTR_ERR(rtc); | 762 | status = PTR_ERR(ds1305->rtc); |
763 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | 763 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); |
764 | goto fail0; | 764 | goto fail0; |
765 | } | 765 | } |
766 | ds1305->rtc = rtc; | ||
767 | 766 | ||
768 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | 767 | /* Maybe set up alarm IRQ; be ready to handle it triggering right |
769 | * away. NOTE that we don't share this. The signal is active low, | 768 | * away. NOTE that we don't share this. The signal is active low, |
@@ -774,12 +773,14 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
774 | if (spi->irq) { | 773 | if (spi->irq) { |
775 | INIT_WORK(&ds1305->work, ds1305_work); | 774 | INIT_WORK(&ds1305->work, ds1305_work); |
776 | status = request_irq(spi->irq, ds1305_irq, | 775 | status = request_irq(spi->irq, ds1305_irq, |
777 | 0, dev_name(&rtc->dev), ds1305); | 776 | 0, dev_name(&ds1305->rtc->dev), ds1305); |
778 | if (status < 0) { | 777 | if (status < 0) { |
779 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | 778 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", |
780 | spi->irq, status); | 779 | spi->irq, status); |
781 | goto fail1; | 780 | goto fail1; |
782 | } | 781 | } |
782 | |||
783 | device_set_wakeup_capable(&spi->dev, 1); | ||
783 | } | 784 | } |
784 | 785 | ||
785 | /* export NVRAM */ | 786 | /* export NVRAM */ |
@@ -794,7 +795,7 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
794 | fail2: | 795 | fail2: |
795 | free_irq(spi->irq, ds1305); | 796 | free_irq(spi->irq, ds1305); |
796 | fail1: | 797 | fail1: |
797 | rtc_device_unregister(rtc); | 798 | rtc_device_unregister(ds1305->rtc); |
798 | fail0: | 799 | fail0: |
799 | kfree(ds1305); | 800 | kfree(ds1305); |
800 | return status; | 801 | return status; |
@@ -802,7 +803,7 @@ fail0: | |||
802 | 803 | ||
803 | static int __devexit ds1305_remove(struct spi_device *spi) | 804 | static int __devexit ds1305_remove(struct spi_device *spi) |
804 | { | 805 | { |
805 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | 806 | struct ds1305 *ds1305 = spi_get_drvdata(spi); |
806 | 807 | ||
807 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | 808 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); |
808 | 809 | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index eb99ee4fa0f5..c4ec5c158aa1 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -874,13 +874,15 @@ read_rtc: | |||
874 | } | 874 | } |
875 | 875 | ||
876 | if (want_irq) { | 876 | if (want_irq) { |
877 | err = request_irq(client->irq, ds1307_irq, 0, | 877 | err = request_irq(client->irq, ds1307_irq, IRQF_SHARED, |
878 | ds1307->rtc->name, client); | 878 | ds1307->rtc->name, client); |
879 | if (err) { | 879 | if (err) { |
880 | dev_err(&client->dev, | 880 | dev_err(&client->dev, |
881 | "unable to request IRQ!\n"); | 881 | "unable to request IRQ!\n"); |
882 | goto exit_irq; | 882 | goto exit_irq; |
883 | } | 883 | } |
884 | |||
885 | device_set_wakeup_capable(&client->dev, 1); | ||
884 | set_bit(HAS_ALARM, &ds1307->flags); | 886 | set_bit(HAS_ALARM, &ds1307->flags); |
885 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | 887 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
886 | } | 888 | } |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 713f7bf5afb3..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 |
@@ -383,6 +384,8 @@ static int ds1374_probe(struct i2c_client *client, | |||
383 | dev_err(&client->dev, "unable to request IRQ\n"); | 384 | dev_err(&client->dev, "unable to request IRQ\n"); |
384 | goto out_free; | 385 | goto out_free; |
385 | } | 386 | } |
387 | |||
388 | device_set_wakeup_capable(&client->dev, 1); | ||
386 | } | 389 | } |
387 | 390 | ||
388 | ds1374->rtc = rtc_device_register(client->name, &client->dev, | 391 | ds1374->rtc = rtc_device_register(client->name, &client->dev, |
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 0b6b7730c716..06b8566c4532 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * An rtc driver for the Dallas DS1511 | 2 | * An rtc driver for the Dallas DS1511 |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> |
5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com> | 5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@lsi.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -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> |
@@ -87,7 +88,6 @@ enum ds1511reg { | |||
87 | struct rtc_plat_data { | 88 | struct rtc_plat_data { |
88 | struct rtc_device *rtc; | 89 | struct rtc_device *rtc; |
89 | void __iomem *ioaddr; /* virtual base address */ | 90 | void __iomem *ioaddr; /* virtual base address */ |
90 | unsigned long baseaddr; /* physical base address */ | ||
91 | int size; /* amount of memory mapped */ | 91 | int size; /* amount of memory mapped */ |
92 | int irq; | 92 | int irq; |
93 | unsigned int irqen; | 93 | unsigned int irqen; |
@@ -95,6 +95,7 @@ struct rtc_plat_data { | |||
95 | int alrm_min; | 95 | int alrm_min; |
96 | int alrm_hour; | 96 | int alrm_hour; |
97 | int alrm_mday; | 97 | int alrm_mday; |
98 | spinlock_t lock; | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static DEFINE_SPINLOCK(ds1511_lock); | 101 | static DEFINE_SPINLOCK(ds1511_lock); |
@@ -302,7 +303,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
302 | { | 303 | { |
303 | unsigned long flags; | 304 | unsigned long flags; |
304 | 305 | ||
305 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 306 | spin_lock_irqsave(&pdata->lock, flags); |
306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 307 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
307 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, | 308 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, |
308 | RTC_ALARM_DATE); | 309 | RTC_ALARM_DATE); |
@@ -317,7 +318,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
317 | RTC_ALARM_SEC); | 318 | RTC_ALARM_SEC); |
318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | 319 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); |
319 | rtc_read(RTC_CMD1); /* clear interrupts */ | 320 | rtc_read(RTC_CMD1); /* clear interrupts */ |
320 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 321 | spin_unlock_irqrestore(&pdata->lock, flags); |
321 | } | 322 | } |
322 | 323 | ||
323 | static int | 324 | static int |
@@ -362,61 +363,63 @@ ds1511_interrupt(int irq, void *dev_id) | |||
362 | { | 363 | { |
363 | struct platform_device *pdev = dev_id; | 364 | struct platform_device *pdev = dev_id; |
364 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 365 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
365 | unsigned long events = RTC_IRQF; | 366 | unsigned long events = 0; |
366 | 367 | ||
368 | spin_lock(&pdata->lock); | ||
367 | /* | 369 | /* |
368 | * read and clear interrupt | 370 | * read and clear interrupt |
369 | */ | 371 | */ |
370 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | 372 | if (rtc_read(RTC_CMD1) & DS1511_IRQF) { |
371 | return IRQ_NONE; | 373 | events = RTC_IRQF; |
372 | } | 374 | if (rtc_read(RTC_ALARM_SEC) & 0x80) |
373 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | 375 | events |= RTC_UF; |
374 | events |= RTC_UF; | 376 | else |
375 | } else { | 377 | events |= RTC_AF; |
376 | events |= RTC_AF; | 378 | if (likely(pdata->rtc)) |
377 | } | 379 | rtc_update_irq(pdata->rtc, 1, events); |
378 | rtc_update_irq(pdata->rtc, 1, events); | 380 | } |
379 | return IRQ_HANDLED; | 381 | spin_unlock(&pdata->lock); |
382 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
380 | } | 383 | } |
381 | 384 | ||
382 | static int | 385 | static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
384 | { | 386 | { |
385 | struct platform_device *pdev = to_platform_device(dev); | 387 | struct platform_device *pdev = to_platform_device(dev); |
386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 388 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
387 | 389 | ||
388 | if (pdata->irq <= 0) { | 390 | if (pdata->irq <= 0) |
389 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 391 | return -EINVAL; |
390 | } | 392 | if (enabled) |
391 | switch (cmd) { | ||
392 | case RTC_AIE_OFF: | ||
393 | pdata->irqen &= ~RTC_AF; | ||
394 | ds1511_rtc_update_alarm(pdata); | ||
395 | break; | ||
396 | case RTC_AIE_ON: | ||
397 | pdata->irqen |= RTC_AF; | 393 | pdata->irqen |= RTC_AF; |
398 | ds1511_rtc_update_alarm(pdata); | 394 | else |
399 | break; | 395 | pdata->irqen &= ~RTC_AF; |
400 | case RTC_UIE_OFF: | 396 | ds1511_rtc_update_alarm(pdata); |
401 | pdata->irqen &= ~RTC_UF; | 397 | return 0; |
402 | ds1511_rtc_update_alarm(pdata); | 398 | } |
403 | break; | 399 | |
404 | case RTC_UIE_ON: | 400 | static int ds1511_rtc_update_irq_enable(struct device *dev, |
401 | unsigned int enabled) | ||
402 | { | ||
403 | struct platform_device *pdev = to_platform_device(dev); | ||
404 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
405 | |||
406 | if (pdata->irq <= 0) | ||
407 | return -EINVAL; | ||
408 | if (enabled) | ||
405 | pdata->irqen |= RTC_UF; | 409 | pdata->irqen |= RTC_UF; |
406 | ds1511_rtc_update_alarm(pdata); | 410 | else |
407 | break; | 411 | pdata->irqen &= ~RTC_UF; |
408 | default: | 412 | ds1511_rtc_update_alarm(pdata); |
409 | return -ENOIOCTLCMD; | ||
410 | } | ||
411 | return 0; | 413 | return 0; |
412 | } | 414 | } |
413 | 415 | ||
414 | static const struct rtc_class_ops ds1511_rtc_ops = { | 416 | static const struct rtc_class_ops ds1511_rtc_ops = { |
415 | .read_time = ds1511_rtc_read_time, | 417 | .read_time = ds1511_rtc_read_time, |
416 | .set_time = ds1511_rtc_set_time, | 418 | .set_time = ds1511_rtc_set_time, |
417 | .read_alarm = ds1511_rtc_read_alarm, | 419 | .read_alarm = ds1511_rtc_read_alarm, |
418 | .set_alarm = ds1511_rtc_set_alarm, | 420 | .set_alarm = ds1511_rtc_set_alarm, |
419 | .ioctl = ds1511_rtc_ioctl, | 421 | .alarm_irq_enable = ds1511_rtc_alarm_irq_enable, |
422 | .update_irq_enable = ds1511_rtc_update_irq_enable, | ||
420 | }; | 423 | }; |
421 | 424 | ||
422 | static ssize_t | 425 | static ssize_t |
@@ -492,29 +495,23 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
492 | { | 495 | { |
493 | struct rtc_device *rtc; | 496 | struct rtc_device *rtc; |
494 | struct resource *res; | 497 | struct resource *res; |
495 | struct rtc_plat_data *pdata = NULL; | 498 | struct rtc_plat_data *pdata; |
496 | int ret = 0; | 499 | int ret = 0; |
497 | 500 | ||
498 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 501 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
499 | if (!res) { | 502 | if (!res) { |
500 | return -ENODEV; | 503 | return -ENODEV; |
501 | } | 504 | } |
502 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 505 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
503 | if (!pdata) { | 506 | if (!pdata) |
504 | return -ENOMEM; | 507 | return -ENOMEM; |
505 | } | ||
506 | pdata->size = res->end - res->start + 1; | 508 | pdata->size = res->end - res->start + 1; |
507 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 509 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
508 | ret = -EBUSY; | 510 | pdev->name)) |
509 | goto out; | 511 | return -EBUSY; |
510 | } | 512 | ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size); |
511 | pdata->baseaddr = res->start; | 513 | if (!ds1511_base) |
512 | pdata->size = pdata->size; | 514 | return -ENOMEM; |
513 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
514 | if (!ds1511_base) { | ||
515 | ret = -ENOMEM; | ||
516 | goto out; | ||
517 | } | ||
518 | pdata->ioaddr = ds1511_base; | 515 | pdata->ioaddr = ds1511_base; |
519 | pdata->irq = platform_get_irq(pdev, 0); | 516 | pdata->irq = platform_get_irq(pdev, 0); |
520 | 517 | ||
@@ -540,13 +537,15 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
540 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 537 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
541 | } | 538 | } |
542 | 539 | ||
540 | spin_lock_init(&pdata->lock); | ||
541 | platform_set_drvdata(pdev, pdata); | ||
543 | /* | 542 | /* |
544 | * if the platform has an interrupt in mind for this device, | 543 | * if the platform has an interrupt in mind for this device, |
545 | * then by all means, set it | 544 | * then by all means, set it |
546 | */ | 545 | */ |
547 | if (pdata->irq > 0) { | 546 | if (pdata->irq > 0) { |
548 | rtc_read(RTC_CMD1); | 547 | rtc_read(RTC_CMD1); |
549 | if (request_irq(pdata->irq, ds1511_interrupt, | 548 | if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, |
550 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | 549 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { |
551 | 550 | ||
552 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 551 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -556,33 +555,13 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
556 | 555 | ||
557 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | 556 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, |
558 | THIS_MODULE); | 557 | THIS_MODULE); |
559 | if (IS_ERR(rtc)) { | 558 | if (IS_ERR(rtc)) |
560 | ret = PTR_ERR(rtc); | 559 | return PTR_ERR(rtc); |
561 | goto out; | ||
562 | } | ||
563 | pdata->rtc = rtc; | 560 | pdata->rtc = rtc; |
564 | platform_set_drvdata(pdev, pdata); | 561 | |
565 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 562 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
566 | if (ret) { | 563 | if (ret) |
567 | goto out; | ||
568 | } | ||
569 | return 0; | ||
570 | out: | ||
571 | if (pdata->rtc) { | ||
572 | rtc_device_unregister(pdata->rtc); | 564 | rtc_device_unregister(pdata->rtc); |
573 | } | ||
574 | if (pdata->irq > 0) { | ||
575 | free_irq(pdata->irq, pdev); | ||
576 | } | ||
577 | if (ds1511_base) { | ||
578 | iounmap(ds1511_base); | ||
579 | ds1511_base = NULL; | ||
580 | } | ||
581 | if (pdata->baseaddr) { | ||
582 | release_mem_region(pdata->baseaddr, pdata->size); | ||
583 | } | ||
584 | |||
585 | kfree(pdata); | ||
586 | return ret; | 565 | return ret; |
587 | } | 566 | } |
588 | 567 | ||
@@ -593,19 +572,13 @@ ds1511_rtc_remove(struct platform_device *pdev) | |||
593 | 572 | ||
594 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 573 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
595 | rtc_device_unregister(pdata->rtc); | 574 | rtc_device_unregister(pdata->rtc); |
596 | pdata->rtc = NULL; | ||
597 | if (pdata->irq > 0) { | 575 | if (pdata->irq > 0) { |
598 | /* | 576 | /* |
599 | * disable the alarm interrupt | 577 | * disable the alarm interrupt |
600 | */ | 578 | */ |
601 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | 579 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); |
602 | rtc_read(RTC_CMD1); | 580 | rtc_read(RTC_CMD1); |
603 | free_irq(pdata->irq, pdev); | ||
604 | } | 581 | } |
605 | iounmap(pdata->ioaddr); | ||
606 | ds1511_base = NULL; | ||
607 | release_mem_region(pdata->baseaddr, pdata->size); | ||
608 | kfree(pdata); | ||
609 | return 0; | 582 | return 0; |
610 | } | 583 | } |
611 | 584 | ||
@@ -636,7 +609,7 @@ ds1511_rtc_exit(void) | |||
636 | module_init(ds1511_rtc_init); | 609 | module_init(ds1511_rtc_init); |
637 | module_exit(ds1511_rtc_exit); | 610 | module_exit(ds1511_rtc_exit); |
638 | 611 | ||
639 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>"); | 612 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); |
640 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | 613 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); |
641 | MODULE_LICENSE("GPL"); | 614 | MODULE_LICENSE("GPL"); |
642 | MODULE_VERSION(DRV_VERSION); | 615 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 717288527c6b..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> |
@@ -18,7 +19,7 @@ | |||
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
20 | 21 | ||
21 | #define DRV_VERSION "0.2" | 22 | #define DRV_VERSION "0.3" |
22 | 23 | ||
23 | #define RTC_REG_SIZE 0x2000 | 24 | #define RTC_REG_SIZE 0x2000 |
24 | #define RTC_OFFSET 0x1ff0 | 25 | #define RTC_OFFSET 0x1ff0 |
@@ -61,7 +62,6 @@ | |||
61 | struct rtc_plat_data { | 62 | struct rtc_plat_data { |
62 | struct rtc_device *rtc; | 63 | struct rtc_device *rtc; |
63 | void __iomem *ioaddr; | 64 | void __iomem *ioaddr; |
64 | resource_size_t baseaddr; | ||
65 | unsigned long last_jiffies; | 65 | unsigned long last_jiffies; |
66 | int irq; | 66 | int irq; |
67 | unsigned int irqen; | 67 | unsigned int irqen; |
@@ -69,6 +69,7 @@ struct rtc_plat_data { | |||
69 | int alrm_min; | 69 | int alrm_min; |
70 | int alrm_hour; | 70 | int alrm_hour; |
71 | int alrm_mday; | 71 | int alrm_mday; |
72 | spinlock_t lock; | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) | 75 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -139,7 +140,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
139 | void __iomem *ioaddr = pdata->ioaddr; | 140 | void __iomem *ioaddr = pdata->ioaddr; |
140 | unsigned long flags; | 141 | unsigned long flags; |
141 | 142 | ||
142 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 143 | spin_lock_irqsave(&pdata->lock, flags); |
143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 144 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
144 | 0x80 : bin2bcd(pdata->alrm_mday), | 145 | 0x80 : bin2bcd(pdata->alrm_mday), |
145 | ioaddr + RTC_DATE_ALARM); | 146 | ioaddr + RTC_DATE_ALARM); |
@@ -154,7 +155,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
154 | ioaddr + RTC_SECONDS_ALARM); | 155 | ioaddr + RTC_SECONDS_ALARM); |
155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); | 156 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); |
156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 157 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
157 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 158 | spin_unlock_irqrestore(&pdata->lock, flags); |
158 | } | 159 | } |
159 | 160 | ||
160 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 161 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -194,64 +195,69 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
194 | struct platform_device *pdev = dev_id; | 195 | struct platform_device *pdev = dev_id; |
195 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 196 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
196 | void __iomem *ioaddr = pdata->ioaddr; | 197 | void __iomem *ioaddr = pdata->ioaddr; |
197 | unsigned long events = RTC_IRQF; | 198 | unsigned long events = 0; |
198 | 199 | ||
200 | spin_lock(&pdata->lock); | ||
199 | /* read and clear interrupt */ | 201 | /* read and clear interrupt */ |
200 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 202 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
201 | return IRQ_NONE; | 203 | events = RTC_IRQF; |
202 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 204 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
203 | events |= RTC_UF; | 205 | events |= RTC_UF; |
204 | else | 206 | else |
205 | events |= RTC_AF; | 207 | events |= RTC_AF; |
206 | rtc_update_irq(pdata->rtc, 1, events); | 208 | if (likely(pdata->rtc)) |
207 | return IRQ_HANDLED; | 209 | rtc_update_irq(pdata->rtc, 1, events); |
210 | } | ||
211 | spin_unlock(&pdata->lock); | ||
212 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
208 | } | 213 | } |
209 | 214 | ||
210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 215 | static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
211 | unsigned long arg) | ||
212 | { | 216 | { |
213 | struct platform_device *pdev = to_platform_device(dev); | 217 | struct platform_device *pdev = to_platform_device(dev); |
214 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 218 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
215 | 219 | ||
216 | if (pdata->irq <= 0) | 220 | if (pdata->irq <= 0) |
217 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 221 | return -EINVAL; |
218 | switch (cmd) { | 222 | if (enabled) |
219 | case RTC_AIE_OFF: | ||
220 | pdata->irqen &= ~RTC_AF; | ||
221 | ds1553_rtc_update_alarm(pdata); | ||
222 | break; | ||
223 | case RTC_AIE_ON: | ||
224 | pdata->irqen |= RTC_AF; | 223 | pdata->irqen |= RTC_AF; |
225 | ds1553_rtc_update_alarm(pdata); | 224 | else |
226 | break; | 225 | pdata->irqen &= ~RTC_AF; |
227 | case RTC_UIE_OFF: | 226 | ds1553_rtc_update_alarm(pdata); |
228 | pdata->irqen &= ~RTC_UF; | 227 | return 0; |
229 | ds1553_rtc_update_alarm(pdata); | 228 | } |
230 | break; | 229 | |
231 | case RTC_UIE_ON: | 230 | static int ds1553_rtc_update_irq_enable(struct device *dev, |
231 | unsigned int enabled) | ||
232 | { | ||
233 | struct platform_device *pdev = to_platform_device(dev); | ||
234 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
235 | |||
236 | if (pdata->irq <= 0) | ||
237 | return -EINVAL; | ||
238 | if (enabled) | ||
232 | pdata->irqen |= RTC_UF; | 239 | pdata->irqen |= RTC_UF; |
233 | ds1553_rtc_update_alarm(pdata); | 240 | else |
234 | break; | 241 | pdata->irqen &= ~RTC_UF; |
235 | default: | 242 | ds1553_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 243 | return 0; |
239 | } | 244 | } |
240 | 245 | ||
241 | static const struct rtc_class_ops ds1553_rtc_ops = { | 246 | static const struct rtc_class_ops ds1553_rtc_ops = { |
242 | .read_time = ds1553_rtc_read_time, | 247 | .read_time = ds1553_rtc_read_time, |
243 | .set_time = ds1553_rtc_set_time, | 248 | .set_time = ds1553_rtc_set_time, |
244 | .read_alarm = ds1553_rtc_read_alarm, | 249 | .read_alarm = ds1553_rtc_read_alarm, |
245 | .set_alarm = ds1553_rtc_set_alarm, | 250 | .set_alarm = ds1553_rtc_set_alarm, |
246 | .ioctl = ds1553_rtc_ioctl, | 251 | .alarm_irq_enable = ds1553_rtc_alarm_irq_enable, |
252 | .update_irq_enable = ds1553_rtc_update_irq_enable, | ||
247 | }; | 253 | }; |
248 | 254 | ||
249 | static ssize_t ds1553_nvram_read(struct kobject *kobj, | 255 | static ssize_t ds1553_nvram_read(struct kobject *kobj, |
250 | struct bin_attribute *bin_attr, | 256 | struct bin_attribute *bin_attr, |
251 | char *buf, loff_t pos, size_t size) | 257 | char *buf, loff_t pos, size_t size) |
252 | { | 258 | { |
253 | struct platform_device *pdev = | 259 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 260 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 261 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 262 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 263 | ssize_t count; |
@@ -265,8 +271,8 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj, | |||
265 | struct bin_attribute *bin_attr, | 271 | struct bin_attribute *bin_attr, |
266 | char *buf, loff_t pos, size_t size) | 272 | char *buf, loff_t pos, size_t size) |
267 | { | 273 | { |
268 | struct platform_device *pdev = | 274 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 275 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 276 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 277 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 278 | ssize_t count; |
@@ -291,26 +297,23 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
291 | struct rtc_device *rtc; | 297 | struct rtc_device *rtc; |
292 | struct resource *res; | 298 | struct resource *res; |
293 | unsigned int cen, sec; | 299 | unsigned int cen, sec; |
294 | struct rtc_plat_data *pdata = NULL; | 300 | struct rtc_plat_data *pdata; |
295 | void __iomem *ioaddr = NULL; | 301 | void __iomem *ioaddr; |
296 | int ret = 0; | 302 | int ret = 0; |
297 | 303 | ||
298 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 304 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
299 | if (!res) | 305 | if (!res) |
300 | return -ENODEV; | 306 | return -ENODEV; |
301 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 307 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
302 | if (!pdata) | 308 | if (!pdata) |
303 | return -ENOMEM; | 309 | return -ENOMEM; |
304 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 310 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
305 | ret = -EBUSY; | 311 | pdev->name)) |
306 | goto out; | 312 | return -EBUSY; |
307 | } | 313 | |
308 | pdata->baseaddr = res->start; | 314 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
309 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 315 | if (!ioaddr) |
310 | if (!ioaddr) { | 316 | return -ENOMEM; |
311 | ret = -ENOMEM; | ||
312 | goto out; | ||
313 | } | ||
314 | pdata->ioaddr = ioaddr; | 317 | pdata->ioaddr = ioaddr; |
315 | pdata->irq = platform_get_irq(pdev, 0); | 318 | pdata->irq = platform_get_irq(pdev, 0); |
316 | 319 | ||
@@ -326,9 +329,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
326 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) | 329 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) |
327 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 330 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
328 | 331 | ||
332 | spin_lock_init(&pdata->lock); | ||
333 | pdata->last_jiffies = jiffies; | ||
334 | platform_set_drvdata(pdev, pdata); | ||
329 | if (pdata->irq > 0) { | 335 | if (pdata->irq > 0) { |
330 | writeb(0, ioaddr + RTC_INTERRUPTS); | 336 | writeb(0, ioaddr + RTC_INTERRUPTS); |
331 | if (request_irq(pdata->irq, ds1553_rtc_interrupt, | 337 | if (devm_request_irq(&pdev->dev, pdata->irq, |
338 | ds1553_rtc_interrupt, | ||
332 | IRQF_DISABLED, pdev->name, pdev) < 0) { | 339 | IRQF_DISABLED, pdev->name, pdev) < 0) { |
333 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 340 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
334 | pdata->irq = 0; | 341 | pdata->irq = 0; |
@@ -337,27 +344,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
337 | 344 | ||
338 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 345 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
339 | &ds1553_rtc_ops, THIS_MODULE); | 346 | &ds1553_rtc_ops, THIS_MODULE); |
340 | if (IS_ERR(rtc)) { | 347 | if (IS_ERR(rtc)) |
341 | ret = PTR_ERR(rtc); | 348 | return PTR_ERR(rtc); |
342 | goto out; | ||
343 | } | ||
344 | pdata->rtc = rtc; | 349 | pdata->rtc = rtc; |
345 | pdata->last_jiffies = jiffies; | 350 | |
346 | platform_set_drvdata(pdev, pdata); | ||
347 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 351 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
348 | if (ret) | 352 | if (ret) |
349 | goto out; | 353 | rtc_device_unregister(rtc); |
350 | return 0; | ||
351 | out: | ||
352 | if (pdata->rtc) | ||
353 | rtc_device_unregister(pdata->rtc); | ||
354 | if (pdata->irq > 0) | ||
355 | free_irq(pdata->irq, pdev); | ||
356 | if (ioaddr) | ||
357 | iounmap(ioaddr); | ||
358 | if (pdata->baseaddr) | ||
359 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
360 | kfree(pdata); | ||
361 | return ret; | 354 | return ret; |
362 | } | 355 | } |
363 | 356 | ||
@@ -367,13 +360,8 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev) | |||
367 | 360 | ||
368 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 361 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
369 | rtc_device_unregister(pdata->rtc); | 362 | rtc_device_unregister(pdata->rtc); |
370 | if (pdata->irq > 0) { | 363 | if (pdata->irq > 0) |
371 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 364 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
372 | free_irq(pdata->irq, pdev); | ||
373 | } | ||
374 | iounmap(pdata->ioaddr); | ||
375 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
376 | kfree(pdata); | ||
377 | return 0; | 365 | return 0; |
378 | } | 366 | } |
379 | 367 | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 09249459e9a4..2b4b0bc42d6f 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -15,13 +15,14 @@ | |||
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> |
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
23 | 24 | ||
24 | #define DRV_VERSION "0.3" | 25 | #define DRV_VERSION "0.4" |
25 | 26 | ||
26 | #define RTC_SIZE 8 | 27 | #define RTC_SIZE 8 |
27 | 28 | ||
@@ -55,7 +56,6 @@ struct rtc_plat_data { | |||
55 | void __iomem *ioaddr_rtc; | 56 | void __iomem *ioaddr_rtc; |
56 | size_t size_nvram; | 57 | size_t size_nvram; |
57 | size_t size; | 58 | size_t size; |
58 | resource_size_t baseaddr; | ||
59 | unsigned long last_jiffies; | 59 | unsigned long last_jiffies; |
60 | struct bin_attribute nvram_attr; | 60 | struct bin_attribute nvram_attr; |
61 | }; | 61 | }; |
@@ -132,8 +132,8 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, | |||
132 | struct bin_attribute *bin_attr, | 132 | struct bin_attribute *bin_attr, |
133 | char *buf, loff_t pos, size_t size) | 133 | char *buf, loff_t pos, size_t size) |
134 | { | 134 | { |
135 | struct platform_device *pdev = | 135 | struct device *dev = container_of(kobj, struct device, kobj); |
136 | to_platform_device(container_of(kobj, struct device, kobj)); | 136 | struct platform_device *pdev = to_platform_device(dev); |
137 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 137 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
138 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 138 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
139 | ssize_t count; | 139 | ssize_t count; |
@@ -147,8 +147,8 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, | |||
147 | struct bin_attribute *bin_attr, | 147 | struct bin_attribute *bin_attr, |
148 | char *buf, loff_t pos, size_t size) | 148 | char *buf, loff_t pos, size_t size) |
149 | { | 149 | { |
150 | struct platform_device *pdev = | 150 | struct device *dev = container_of(kobj, struct device, kobj); |
151 | to_platform_device(container_of(kobj, struct device, kobj)); | 151 | struct platform_device *pdev = to_platform_device(dev); |
152 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 152 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
153 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 153 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
154 | ssize_t count; | 154 | ssize_t count; |
@@ -163,31 +163,29 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
163 | struct rtc_device *rtc; | 163 | struct rtc_device *rtc; |
164 | struct resource *res; | 164 | struct resource *res; |
165 | unsigned int cen, sec; | 165 | unsigned int cen, sec; |
166 | struct rtc_plat_data *pdata = NULL; | 166 | struct rtc_plat_data *pdata; |
167 | void __iomem *ioaddr = NULL; | 167 | void __iomem *ioaddr; |
168 | int ret = 0; | 168 | int ret = 0; |
169 | 169 | ||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
171 | if (!res) | 171 | if (!res) |
172 | return -ENODEV; | 172 | return -ENODEV; |
173 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 173 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
174 | if (!pdata) | 174 | if (!pdata) |
175 | return -ENOMEM; | 175 | return -ENOMEM; |
176 | pdata->size = res->end - res->start + 1; | 176 | pdata->size = res->end - res->start + 1; |
177 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 177 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
178 | ret = -EBUSY; | 178 | pdev->name)) |
179 | goto out; | 179 | return -EBUSY; |
180 | } | 180 | ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size); |
181 | pdata->baseaddr = res->start; | 181 | if (!ioaddr) |
182 | ioaddr = ioremap(pdata->baseaddr, pdata->size); | 182 | return -ENOMEM; |
183 | if (!ioaddr) { | 183 | |
184 | ret = -ENOMEM; | ||
185 | goto out; | ||
186 | } | ||
187 | pdata->ioaddr_nvram = ioaddr; | 184 | pdata->ioaddr_nvram = ioaddr; |
188 | pdata->size_nvram = pdata->size - RTC_SIZE; | 185 | pdata->size_nvram = pdata->size - RTC_SIZE; |
189 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | 186 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; |
190 | 187 | ||
188 | sysfs_bin_attr_init(&pdata->nvram_attr); | ||
191 | pdata->nvram_attr.attr.name = "nvram"; | 189 | pdata->nvram_attr.attr.name = "nvram"; |
192 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | 190 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; |
193 | pdata->nvram_attr.read = ds1742_nvram_read; | 191 | pdata->nvram_attr.read = ds1742_nvram_read; |
@@ -207,31 +205,19 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
207 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) | 205 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) |
208 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 206 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
209 | 207 | ||
208 | pdata->last_jiffies = jiffies; | ||
209 | platform_set_drvdata(pdev, pdata); | ||
210 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 210 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
211 | &ds1742_rtc_ops, THIS_MODULE); | 211 | &ds1742_rtc_ops, THIS_MODULE); |
212 | if (IS_ERR(rtc)) { | 212 | if (IS_ERR(rtc)) |
213 | ret = PTR_ERR(rtc); | 213 | return PTR_ERR(rtc); |
214 | goto out; | ||
215 | } | ||
216 | pdata->rtc = rtc; | 214 | pdata->rtc = rtc; |
217 | pdata->last_jiffies = jiffies; | ||
218 | platform_set_drvdata(pdev, pdata); | ||
219 | 215 | ||
220 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 216 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
221 | if (ret) { | 217 | if (ret) { |
222 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); | 218 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); |
223 | goto out; | 219 | rtc_device_unregister(rtc); |
224 | } | 220 | } |
225 | |||
226 | return 0; | ||
227 | out: | ||
228 | if (pdata->rtc) | ||
229 | rtc_device_unregister(pdata->rtc); | ||
230 | if (pdata->ioaddr_nvram) | ||
231 | iounmap(pdata->ioaddr_nvram); | ||
232 | if (pdata->baseaddr) | ||
233 | release_mem_region(pdata->baseaddr, pdata->size); | ||
234 | kfree(pdata); | ||
235 | return ret; | 221 | return ret; |
236 | } | 222 | } |
237 | 223 | ||
@@ -241,9 +227,6 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev) | |||
241 | 227 | ||
242 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 228 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
243 | rtc_device_unregister(pdata->rtc); | 229 | rtc_device_unregister(pdata->rtc); |
244 | iounmap(pdata->ioaddr_nvram); | ||
245 | release_mem_region(pdata->baseaddr, pdata->size); | ||
246 | kfree(pdata); | ||
247 | return 0; | 230 | return 0; |
248 | } | 231 | } |
249 | 232 | ||
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 3a7be11cc6b9..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) |
@@ -376,20 +377,22 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
376 | } | 377 | } |
377 | 378 | ||
378 | /* Disabling calibration mode */ | 379 | /* Disabling calibration mode */ |
379 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) | 380 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { |
380 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 381 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
381 | fm3130->regs[FM3130_RTC_CONTROL] & | 382 | fm3130->regs[FM3130_RTC_CONTROL] & |
382 | ~(FM3130_RTC_CONTROL_BIT_CAL)); | 383 | ~(FM3130_RTC_CONTROL_BIT_CAL)); |
383 | dev_warn(&client->dev, "Disabling calibration mode!\n"); | 384 | dev_warn(&client->dev, "Disabling calibration mode!\n"); |
385 | } | ||
384 | 386 | ||
385 | /* Disabling read and write modes */ | 387 | /* Disabling read and write modes */ |
386 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || | 388 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || |
387 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) | 389 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) { |
388 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 390 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
389 | fm3130->regs[FM3130_RTC_CONTROL] & | 391 | fm3130->regs[FM3130_RTC_CONTROL] & |
390 | ~(FM3130_RTC_CONTROL_BIT_READ | | 392 | ~(FM3130_RTC_CONTROL_BIT_READ | |
391 | FM3130_RTC_CONTROL_BIT_WRITE)); | 393 | FM3130_RTC_CONTROL_BIT_WRITE)); |
392 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); | 394 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); |
395 | } | ||
393 | 396 | ||
394 | /* oscillator off? turn it on, so clock can tick. */ | 397 | /* oscillator off? turn it on, so clock can tick. */ |
395 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) | 398 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) |
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 0b2197559940..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> |
@@ -142,7 +143,6 @@ static const struct rtc_class_ops m48t35_ops = { | |||
142 | 143 | ||
143 | static int __devinit m48t35_probe(struct platform_device *pdev) | 144 | static int __devinit m48t35_probe(struct platform_device *pdev) |
144 | { | 145 | { |
145 | struct rtc_device *rtc; | ||
146 | struct resource *res; | 146 | struct resource *res; |
147 | struct m48t35_priv *priv; | 147 | struct m48t35_priv *priv; |
148 | int ret = 0; | 148 | int ret = 0; |
@@ -171,20 +171,21 @@ static int __devinit m48t35_probe(struct platform_device *pdev) | |||
171 | ret = -ENOMEM; | 171 | ret = -ENOMEM; |
172 | goto out; | 172 | goto out; |
173 | } | 173 | } |
174 | |||
174 | spin_lock_init(&priv->lock); | 175 | spin_lock_init(&priv->lock); |
175 | rtc = rtc_device_register("m48t35", &pdev->dev, | 176 | |
177 | platform_set_drvdata(pdev, priv); | ||
178 | |||
179 | priv->rtc = rtc_device_register("m48t35", &pdev->dev, | ||
176 | &m48t35_ops, THIS_MODULE); | 180 | &m48t35_ops, THIS_MODULE); |
177 | if (IS_ERR(rtc)) { | 181 | if (IS_ERR(priv->rtc)) { |
178 | ret = PTR_ERR(rtc); | 182 | ret = PTR_ERR(priv->rtc); |
179 | goto out; | 183 | goto out; |
180 | } | 184 | } |
181 | priv->rtc = rtc; | 185 | |
182 | platform_set_drvdata(pdev, priv); | ||
183 | return 0; | 186 | return 0; |
184 | 187 | ||
185 | out: | 188 | out: |
186 | if (priv->rtc) | ||
187 | rtc_device_unregister(priv->rtc); | ||
188 | if (priv->reg) | 189 | if (priv->reg) |
189 | iounmap(priv->reg); | 190 | iounmap(priv->reg); |
190 | if (priv->baseaddr) | 191 | if (priv->baseaddr) |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 33921a6b1707..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) |
@@ -481,6 +482,9 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
481 | goto out; | 482 | goto out; |
482 | } | 483 | } |
483 | 484 | ||
485 | spin_lock_init(&m48t59->lock); | ||
486 | platform_set_drvdata(pdev, m48t59); | ||
487 | |||
484 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); | 488 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
485 | if (IS_ERR(m48t59->rtc)) { | 489 | if (IS_ERR(m48t59->rtc)) { |
486 | ret = PTR_ERR(m48t59->rtc); | 490 | ret = PTR_ERR(m48t59->rtc); |
@@ -490,16 +494,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
490 | m48t59_nvram_attr.size = pdata->offset; | 494 | m48t59_nvram_attr.size = pdata->offset; |
491 | 495 | ||
492 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 496 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
493 | if (ret) | 497 | if (ret) { |
498 | rtc_device_unregister(m48t59->rtc); | ||
494 | goto out; | 499 | goto out; |
500 | } | ||
495 | 501 | ||
496 | spin_lock_init(&m48t59->lock); | ||
497 | platform_set_drvdata(pdev, m48t59); | ||
498 | return 0; | 502 | return 0; |
499 | 503 | ||
500 | out: | 504 | out: |
501 | if (!IS_ERR(m48t59->rtc)) | ||
502 | rtc_device_unregister(m48t59->rtc); | ||
503 | if (m48t59->irq != NO_IRQ) | 505 | if (m48t59->irq != NO_IRQ) |
504 | free_irq(m48t59->irq, &pdev->dev); | 506 | free_irq(m48t59->irq, &pdev->dev); |
505 | if (m48t59->ioaddr) | 507 | if (m48t59->ioaddr) |
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 new file mode 100644 index 000000000000..675bfb515367 --- /dev/null +++ b/drivers/rtc/rtc-mc13783.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13783 PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
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/mfd/mc13783.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13783-rtc" | ||
20 | |||
21 | #define MC13783_RTCTOD 20 | ||
22 | #define MC13783_RTCTODA 21 | ||
23 | #define MC13783_RTCDAY 22 | ||
24 | #define MC13783_RTCDAYA 23 | ||
25 | |||
26 | struct mc13783_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13783 *mc13783; | ||
29 | int valid; | ||
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 | |||
60 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13783_lock(priv->mc13783); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13783_unlock(priv->mc13783); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13783_lock(priv->mc13783); | ||
117 | |||
118 | /* | ||
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 | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
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); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13783_unlock(priv->mc13783); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13783_lock(priv->mc13783); | ||
179 | |||
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; | ||
191 | |||
192 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
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; | ||
210 | } | ||
211 | |||
212 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13783_lock(priv->mc13783); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); | ||
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 | |||
251 | out: | ||
252 | mc13783_unlock(priv->mc13783); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
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 | |||
297 | static const struct rtc_class_ops mc13783_rtc_ops = { | ||
298 | .read_time = mc13783_rtc_read_time, | ||
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, | ||
303 | .update_irq_enable = mc13783_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13783_rtc *priv = dev; | ||
309 | struct mc13783 *mc13783 = priv->mc13783; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13783_irq_mask(mc13783, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13783_rtc *priv; | ||
323 | struct mc13783 *mc13783; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13783 = mc13783; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13783_lock(mc13783); | ||
336 | |||
337 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, | ||
338 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
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, | ||
350 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
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; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13783_unlock(mc13783); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13783_lock(priv->mc13783); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
393 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | ||
394 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13783_unlock(priv->mc13783); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static struct platform_driver mc13783_rtc_driver = { | ||
406 | .remove = __devexit_p(mc13783_rtc_remove), | ||
407 | .driver = { | ||
408 | .name = DRIVER_NAME, | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static int __init mc13783_rtc_init(void) | ||
414 | { | ||
415 | return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe); | ||
416 | } | ||
417 | module_init(mc13783_rtc_init); | ||
418 | |||
419 | static void __exit mc13783_rtc_exit(void) | ||
420 | { | ||
421 | platform_driver_unregister(&mc13783_rtc_driver); | ||
422 | } | ||
423 | module_exit(mc13783_rtc_exit); | ||
424 | |||
425 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
426 | MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC"); | ||
427 | MODULE_LICENSE("GPL v2"); | ||
428 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
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 new file mode 100644 index 000000000000..b2fff0ca49f8 --- /dev/null +++ b/drivers/rtc/rtc-msm6242.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * Oki MSM6242 RTC Driver | ||
3 | * | ||
4 | * Copyright 2009 Geert Uytterhoeven | ||
5 | * | ||
6 | * Based on the A2000 TOD code in arch/m68k/amiga/config.c | ||
7 | * Copyright (C) 1993 Hamish Macdonald | ||
8 | */ | ||
9 | |||
10 | #include <linux/delay.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | |||
19 | enum { | ||
20 | MSM6242_SECOND1 = 0x0, /* 1-second digit register */ | ||
21 | MSM6242_SECOND10 = 0x1, /* 10-second digit register */ | ||
22 | MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */ | ||
23 | MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */ | ||
24 | MSM6242_HOUR1 = 0x4, /* 1-hour digit register */ | ||
25 | MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */ | ||
26 | MSM6242_DAY1 = 0x6, /* 1-day digit register */ | ||
27 | MSM6242_DAY10 = 0x7, /* 10-day digit register */ | ||
28 | MSM6242_MONTH1 = 0x8, /* 1-month digit register */ | ||
29 | MSM6242_MONTH10 = 0x9, /* 10-month digit register */ | ||
30 | MSM6242_YEAR1 = 0xa, /* 1-year digit register */ | ||
31 | MSM6242_YEAR10 = 0xb, /* 10-year digit register */ | ||
32 | MSM6242_WEEK = 0xc, /* Week register */ | ||
33 | MSM6242_CD = 0xd, /* Control Register D */ | ||
34 | MSM6242_CE = 0xe, /* Control Register E */ | ||
35 | MSM6242_CF = 0xf, /* Control Register F */ | ||
36 | }; | ||
37 | |||
38 | #define MSM6242_HOUR10_AM (0 << 2) | ||
39 | #define MSM6242_HOUR10_PM (1 << 2) | ||
40 | #define MSM6242_HOUR10_HR_MASK (3 << 0) | ||
41 | |||
42 | #define MSM6242_WEEK_SUNDAY 0 | ||
43 | #define MSM6242_WEEK_MONDAY 1 | ||
44 | #define MSM6242_WEEK_TUESDAY 2 | ||
45 | #define MSM6242_WEEK_WEDNESDAY 3 | ||
46 | #define MSM6242_WEEK_THURSDAY 4 | ||
47 | #define MSM6242_WEEK_FRIDAY 5 | ||
48 | #define MSM6242_WEEK_SATURDAY 6 | ||
49 | |||
50 | #define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */ | ||
51 | #define MSM6242_CD_IRQ_FLAG (1 << 2) | ||
52 | #define MSM6242_CD_BUSY (1 << 1) | ||
53 | #define MSM6242_CD_HOLD (1 << 0) | ||
54 | |||
55 | #define MSM6242_CE_T_MASK (3 << 2) | ||
56 | #define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */ | ||
57 | #define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */ | ||
58 | #define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */ | ||
59 | #define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */ | ||
60 | |||
61 | #define MSM6242_CE_ITRPT_STND (1 << 1) | ||
62 | #define MSM6242_CE_MASK (1 << 0) /* STD.P output control */ | ||
63 | |||
64 | #define MSM6242_CF_TEST (1 << 3) | ||
65 | #define MSM6242_CF_12H (0 << 2) | ||
66 | #define MSM6242_CF_24H (1 << 2) | ||
67 | #define MSM6242_CF_STOP (1 << 1) | ||
68 | #define MSM6242_CF_REST (1 << 0) /* reset */ | ||
69 | |||
70 | |||
71 | struct msm6242_priv { | ||
72 | u32 __iomem *regs; | ||
73 | struct rtc_device *rtc; | ||
74 | }; | ||
75 | |||
76 | static inline unsigned int msm6242_read(struct msm6242_priv *priv, | ||
77 | unsigned int reg) | ||
78 | { | ||
79 | return __raw_readl(&priv->regs[reg]) & 0xf; | ||
80 | } | ||
81 | |||
82 | static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, | ||
83 | unsigned int reg) | ||
84 | { | ||
85 | return __raw_writel(val, &priv->regs[reg]); | ||
86 | } | ||
87 | |||
88 | static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, | ||
89 | unsigned int reg) | ||
90 | { | ||
91 | msm6242_write(priv, msm6242_read(priv, reg) | val, reg); | ||
92 | } | ||
93 | |||
94 | static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val, | ||
95 | unsigned int reg) | ||
96 | { | ||
97 | msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg); | ||
98 | } | ||
99 | |||
100 | static void msm6242_lock(struct msm6242_priv *priv) | ||
101 | { | ||
102 | int cnt = 5; | ||
103 | |||
104 | msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
105 | |||
106 | while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt) { | ||
107 | msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
108 | udelay(70); | ||
109 | msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
110 | cnt--; | ||
111 | } | ||
112 | |||
113 | if (!cnt) | ||
114 | pr_warning("msm6242: timed out waiting for RTC (0x%x)\n", | ||
115 | msm6242_read(priv, MSM6242_CD)); | ||
116 | } | ||
117 | |||
118 | static void msm6242_unlock(struct msm6242_priv *priv) | ||
119 | { | ||
120 | msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
121 | } | ||
122 | |||
123 | static int msm6242_read_time(struct device *dev, struct rtc_time *tm) | ||
124 | { | ||
125 | struct msm6242_priv *priv = dev_get_drvdata(dev); | ||
126 | |||
127 | msm6242_lock(priv); | ||
128 | |||
129 | tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 + | ||
130 | msm6242_read(priv, MSM6242_SECOND1); | ||
131 | tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 + | ||
132 | msm6242_read(priv, MSM6242_MINUTE1); | ||
133 | tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 + | ||
134 | msm6242_read(priv, MSM6242_HOUR1); | ||
135 | tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 + | ||
136 | msm6242_read(priv, MSM6242_DAY1); | ||
137 | tm->tm_wday = msm6242_read(priv, MSM6242_WEEK); | ||
138 | tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 + | ||
139 | msm6242_read(priv, MSM6242_MONTH1) - 1; | ||
140 | tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 + | ||
141 | msm6242_read(priv, MSM6242_YEAR1); | ||
142 | if (tm->tm_year <= 69) | ||
143 | tm->tm_year += 100; | ||
144 | |||
145 | if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) { | ||
146 | unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) & | ||
147 | MSM6242_HOUR10_PM; | ||
148 | if (!pm && tm->tm_hour == 12) | ||
149 | tm->tm_hour = 0; | ||
150 | else if (pm && tm->tm_hour != 12) | ||
151 | tm->tm_hour += 12; | ||
152 | } | ||
153 | |||
154 | msm6242_unlock(priv); | ||
155 | |||
156 | return rtc_valid_tm(tm); | ||
157 | } | ||
158 | |||
159 | static int msm6242_set_time(struct device *dev, struct rtc_time *tm) | ||
160 | { | ||
161 | struct msm6242_priv *priv = dev_get_drvdata(dev); | ||
162 | |||
163 | msm6242_lock(priv); | ||
164 | |||
165 | msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10); | ||
166 | msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1); | ||
167 | msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10); | ||
168 | msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1); | ||
169 | if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H) | ||
170 | msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); | ||
171 | else if (tm->tm_hour >= 12) | ||
172 | msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10, | ||
173 | MSM6242_HOUR10); | ||
174 | else | ||
175 | msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); | ||
176 | msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1); | ||
177 | msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10); | ||
178 | msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1); | ||
179 | if (tm->tm_wday != -1) | ||
180 | msm6242_write(priv, tm->tm_wday, MSM6242_WEEK); | ||
181 | msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10); | ||
182 | msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1); | ||
183 | if (tm->tm_year >= 100) | ||
184 | tm->tm_year -= 100; | ||
185 | msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10); | ||
186 | msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1); | ||
187 | |||
188 | msm6242_unlock(priv); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static const struct rtc_class_ops msm6242_rtc_ops = { | ||
193 | .read_time = msm6242_read_time, | ||
194 | .set_time = msm6242_set_time, | ||
195 | }; | ||
196 | |||
197 | static int __init msm6242_rtc_probe(struct platform_device *dev) | ||
198 | { | ||
199 | struct resource *res; | ||
200 | struct msm6242_priv *priv; | ||
201 | struct rtc_device *rtc; | ||
202 | int error; | ||
203 | |||
204 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
205 | if (!res) | ||
206 | return -ENODEV; | ||
207 | |||
208 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
209 | if (!priv) | ||
210 | return -ENOMEM; | ||
211 | |||
212 | priv->regs = ioremap(res->start, resource_size(res)); | ||
213 | if (!priv->regs) { | ||
214 | error = -ENOMEM; | ||
215 | goto out_free_priv; | ||
216 | } | ||
217 | |||
218 | rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops, | ||
219 | THIS_MODULE); | ||
220 | if (IS_ERR(rtc)) { | ||
221 | error = PTR_ERR(rtc); | ||
222 | goto out_unmap; | ||
223 | } | ||
224 | |||
225 | priv->rtc = rtc; | ||
226 | platform_set_drvdata(dev, priv); | ||
227 | return 0; | ||
228 | |||
229 | out_unmap: | ||
230 | iounmap(priv->regs); | ||
231 | out_free_priv: | ||
232 | kfree(priv); | ||
233 | return error; | ||
234 | } | ||
235 | |||
236 | static int __exit msm6242_rtc_remove(struct platform_device *dev) | ||
237 | { | ||
238 | struct msm6242_priv *priv = platform_get_drvdata(dev); | ||
239 | |||
240 | rtc_device_unregister(priv->rtc); | ||
241 | iounmap(priv->regs); | ||
242 | kfree(priv); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static struct platform_driver msm6242_rtc_driver = { | ||
247 | .driver = { | ||
248 | .name = "rtc-msm6242", | ||
249 | .owner = THIS_MODULE, | ||
250 | }, | ||
251 | .remove = __exit_p(msm6242_rtc_remove), | ||
252 | }; | ||
253 | |||
254 | static int __init msm6242_rtc_init(void) | ||
255 | { | ||
256 | return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe); | ||
257 | } | ||
258 | |||
259 | static void __exit msm6242_rtc_fini(void) | ||
260 | { | ||
261 | platform_driver_unregister(&msm6242_rtc_driver); | ||
262 | } | ||
263 | |||
264 | module_init(msm6242_rtc_init); | ||
265 | module_exit(msm6242_rtc_fini); | ||
266 | |||
267 | MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); | ||
268 | MODULE_LICENSE("GPL"); | ||
269 | MODULE_DESCRIPTION("Oki MSM6242 RTC driver"); | ||
270 | MODULE_ALIAS("platform:rtc-msm6242"); | ||
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index e0263d2005ee..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 |
@@ -27,10 +28,17 @@ | |||
27 | #define RTC_MONTH_OFFS 8 | 28 | #define RTC_MONTH_OFFS 8 |
28 | #define RTC_YEAR_OFFS 16 | 29 | #define RTC_YEAR_OFFS 16 |
29 | 30 | ||
31 | #define RTC_ALARM_TIME_REG_OFFS 8 | ||
32 | #define RTC_ALARM_DATE_REG_OFFS 0xc | ||
33 | #define RTC_ALARM_VALID (1 << 7) | ||
34 | |||
35 | #define RTC_ALARM_INTERRUPT_MASK_REG_OFFS 0x10 | ||
36 | #define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS 0x14 | ||
30 | 37 | ||
31 | struct rtc_plat_data { | 38 | struct rtc_plat_data { |
32 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
33 | void __iomem *ioaddr; | 40 | void __iomem *ioaddr; |
41 | int irq; | ||
34 | }; | 42 | }; |
35 | 43 | ||
36 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) | 44 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -84,12 +92,134 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
84 | return rtc_valid_tm(tm); | 92 | return rtc_valid_tm(tm); |
85 | } | 93 | } |
86 | 94 | ||
95 | static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
96 | { | ||
97 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
98 | void __iomem *ioaddr = pdata->ioaddr; | ||
99 | u32 rtc_time, rtc_date; | ||
100 | unsigned int year, month, day, hour, minute, second, wday; | ||
101 | |||
102 | rtc_time = readl(ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
103 | rtc_date = readl(ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
104 | |||
105 | second = rtc_time & 0x7f; | ||
106 | minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f; | ||
107 | hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */ | ||
108 | wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7; | ||
109 | |||
110 | day = rtc_date & 0x3f; | ||
111 | month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f; | ||
112 | year = (rtc_date >> RTC_YEAR_OFFS) & 0xff; | ||
113 | |||
114 | alm->time.tm_sec = bcd2bin(second); | ||
115 | alm->time.tm_min = bcd2bin(minute); | ||
116 | alm->time.tm_hour = bcd2bin(hour); | ||
117 | alm->time.tm_mday = bcd2bin(day); | ||
118 | alm->time.tm_wday = bcd2bin(wday); | ||
119 | alm->time.tm_mon = bcd2bin(month) - 1; | ||
120 | /* hw counts from year 2000, but tm_year is relative to 1900 */ | ||
121 | alm->time.tm_year = bcd2bin(year) + 100; | ||
122 | |||
123 | if (rtc_valid_tm(&alm->time) < 0) { | ||
124 | dev_err(dev, "retrieved alarm date/time is not valid.\n"); | ||
125 | rtc_time_to_tm(0, &alm->time); | ||
126 | } | ||
127 | |||
128 | alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
133 | { | ||
134 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
135 | void __iomem *ioaddr = pdata->ioaddr; | ||
136 | u32 rtc_reg = 0; | ||
137 | |||
138 | if (alm->time.tm_sec >= 0) | ||
139 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_sec)) | ||
140 | << RTC_SECONDS_OFFS; | ||
141 | if (alm->time.tm_min >= 0) | ||
142 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_min)) | ||
143 | << RTC_MINUTES_OFFS; | ||
144 | if (alm->time.tm_hour >= 0) | ||
145 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_hour)) | ||
146 | << RTC_HOURS_OFFS; | ||
147 | |||
148 | writel(rtc_reg, ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
149 | |||
150 | if (alm->time.tm_mday >= 0) | ||
151 | rtc_reg = (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mday)) | ||
152 | << RTC_MDAY_OFFS; | ||
153 | else | ||
154 | rtc_reg = 0; | ||
155 | |||
156 | if (alm->time.tm_mon >= 0) | ||
157 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mon + 1)) | ||
158 | << RTC_MONTH_OFFS; | ||
159 | |||
160 | if (alm->time.tm_year >= 0) | ||
161 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_year % 100)) | ||
162 | << RTC_YEAR_OFFS; | ||
163 | |||
164 | writel(rtc_reg, ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
165 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
166 | writel(alm->enabled ? 1 : 0, | ||
167 | ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int mv_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
173 | unsigned long arg) | ||
174 | { | ||
175 | struct platform_device *pdev = to_platform_device(dev); | ||
176 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
177 | void __iomem *ioaddr = pdata->ioaddr; | ||
178 | |||
179 | if (pdata->irq < 0) | ||
180 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
181 | switch (cmd) { | ||
182 | case RTC_AIE_OFF: | ||
183 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
184 | break; | ||
185 | case RTC_AIE_ON: | ||
186 | writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
187 | break; | ||
188 | default: | ||
189 | return -ENOIOCTLCMD; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static irqreturn_t mv_rtc_interrupt(int irq, void *data) | ||
195 | { | ||
196 | struct rtc_plat_data *pdata = data; | ||
197 | void __iomem *ioaddr = pdata->ioaddr; | ||
198 | |||
199 | /* alarm irq? */ | ||
200 | if (!readl(ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS)) | ||
201 | return IRQ_NONE; | ||
202 | |||
203 | /* clear interrupt */ | ||
204 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
205 | rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); | ||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
87 | static const struct rtc_class_ops mv_rtc_ops = { | 209 | static const struct rtc_class_ops mv_rtc_ops = { |
88 | .read_time = mv_rtc_read_time, | 210 | .read_time = mv_rtc_read_time, |
89 | .set_time = mv_rtc_set_time, | 211 | .set_time = mv_rtc_set_time, |
90 | }; | 212 | }; |
91 | 213 | ||
92 | static int __init mv_rtc_probe(struct platform_device *pdev) | 214 | static const struct rtc_class_ops mv_rtc_alarm_ops = { |
215 | .read_time = mv_rtc_read_time, | ||
216 | .set_time = mv_rtc_set_time, | ||
217 | .read_alarm = mv_rtc_read_alarm, | ||
218 | .set_alarm = mv_rtc_set_alarm, | ||
219 | .ioctl = mv_rtc_ioctl, | ||
220 | }; | ||
221 | |||
222 | static int __devinit mv_rtc_probe(struct platform_device *pdev) | ||
93 | { | 223 | { |
94 | struct resource *res; | 224 | struct resource *res; |
95 | struct rtc_plat_data *pdata; | 225 | struct rtc_plat_data *pdata; |
@@ -130,12 +260,31 @@ static int __init mv_rtc_probe(struct platform_device *pdev) | |||
130 | } | 260 | } |
131 | } | 261 | } |
132 | 262 | ||
263 | pdata->irq = platform_get_irq(pdev, 0); | ||
264 | |||
133 | platform_set_drvdata(pdev, pdata); | 265 | platform_set_drvdata(pdev, pdata); |
134 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | 266 | |
135 | &mv_rtc_ops, THIS_MODULE); | 267 | if (pdata->irq >= 0) { |
268 | device_init_wakeup(&pdev->dev, 1); | ||
269 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
270 | &mv_rtc_alarm_ops, | ||
271 | THIS_MODULE); | ||
272 | } else | ||
273 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
274 | &mv_rtc_ops, THIS_MODULE); | ||
136 | if (IS_ERR(pdata->rtc)) | 275 | if (IS_ERR(pdata->rtc)) |
137 | return PTR_ERR(pdata->rtc); | 276 | return PTR_ERR(pdata->rtc); |
138 | 277 | ||
278 | if (pdata->irq >= 0) { | ||
279 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
280 | if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt, | ||
281 | IRQF_DISABLED | IRQF_SHARED, | ||
282 | pdev->name, pdata) < 0) { | ||
283 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
284 | pdata->irq = -1; | ||
285 | } | ||
286 | } | ||
287 | |||
139 | return 0; | 288 | return 0; |
140 | } | 289 | } |
141 | 290 | ||
@@ -143,6 +292,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
143 | { | 292 | { |
144 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 293 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
145 | 294 | ||
295 | if (pdata->irq >= 0) | ||
296 | device_init_wakeup(&pdev->dev, 0); | ||
297 | |||
146 | rtc_device_unregister(pdata->rtc); | 298 | rtc_device_unregister(pdata->rtc); |
147 | return 0; | 299 | return 0; |
148 | } | 300 | } |
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 new file mode 100644 index 000000000000..a351bd5d8176 --- /dev/null +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/bcd.h> | ||
20 | |||
21 | /* RTC Control Registers */ | ||
22 | #define REG_RTC_INIR 0x00 | ||
23 | #define REG_RTC_AER 0x04 | ||
24 | #define REG_RTC_FCR 0x08 | ||
25 | #define REG_RTC_TLR 0x0C | ||
26 | #define REG_RTC_CLR 0x10 | ||
27 | #define REG_RTC_TSSR 0x14 | ||
28 | #define REG_RTC_DWR 0x18 | ||
29 | #define REG_RTC_TAR 0x1C | ||
30 | #define REG_RTC_CAR 0x20 | ||
31 | #define REG_RTC_LIR 0x24 | ||
32 | #define REG_RTC_RIER 0x28 | ||
33 | #define REG_RTC_RIIR 0x2C | ||
34 | #define REG_RTC_TTR 0x30 | ||
35 | |||
36 | #define RTCSET 0x01 | ||
37 | #define AERRWENB 0x10000 | ||
38 | #define INIRRESET 0xa5eb1357 | ||
39 | #define AERPOWERON 0xA965 | ||
40 | #define AERPOWEROFF 0x0000 | ||
41 | #define LEAPYEAR 0x0001 | ||
42 | #define TICKENB 0x80 | ||
43 | #define TICKINTENB 0x0002 | ||
44 | #define ALARMINTENB 0x0001 | ||
45 | #define MODE24 0x0001 | ||
46 | |||
47 | struct nuc900_rtc { | ||
48 | int irq_num; | ||
49 | void __iomem *rtc_reg; | ||
50 | struct rtc_device *rtcdev; | ||
51 | }; | ||
52 | |||
53 | struct nuc900_bcd_time { | ||
54 | int bcd_sec; | ||
55 | int bcd_min; | ||
56 | int bcd_hour; | ||
57 | int bcd_mday; | ||
58 | int bcd_mon; | ||
59 | int bcd_year; | ||
60 | }; | ||
61 | |||
62 | static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | ||
63 | { | ||
64 | struct nuc900_rtc *rtc = _rtc; | ||
65 | unsigned long events = 0, rtc_irq; | ||
66 | |||
67 | rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR); | ||
68 | |||
69 | if (rtc_irq & ALARMINTENB) { | ||
70 | rtc_irq &= ~ALARMINTENB; | ||
71 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
72 | events |= RTC_AF | RTC_IRQF; | ||
73 | } | ||
74 | |||
75 | if (rtc_irq & TICKINTENB) { | ||
76 | rtc_irq &= ~TICKINTENB; | ||
77 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
78 | events |= RTC_UF | RTC_IRQF; | ||
79 | } | ||
80 | |||
81 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
82 | |||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | |||
86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | ||
87 | { | ||
88 | unsigned int i; | ||
89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | ||
90 | |||
91 | mdelay(10); | ||
92 | |||
93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | ||
94 | |||
95 | for (i = 0; i < 1000; i++) { | ||
96 | if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0) | ||
101 | return ERR_PTR(-ENODEV); | ||
102 | |||
103 | return ERR_PTR(-EPERM); | ||
104 | } | ||
105 | |||
106 | static void nuc900_rtc_bcd2bin(unsigned int timereg, | ||
107 | unsigned int calreg, struct rtc_time *tm) | ||
108 | { | ||
109 | tm->tm_mday = bcd2bin(calreg >> 0); | ||
110 | tm->tm_mon = bcd2bin(calreg >> 8); | ||
111 | tm->tm_year = bcd2bin(calreg >> 16) + 100; | ||
112 | |||
113 | tm->tm_sec = bcd2bin(timereg >> 0); | ||
114 | tm->tm_min = bcd2bin(timereg >> 8); | ||
115 | tm->tm_hour = bcd2bin(timereg >> 16); | ||
116 | |||
117 | rtc_valid_tm(tm); | ||
118 | } | ||
119 | |||
120 | static void nuc900_rtc_bin2bcd(struct rtc_time *settm, | ||
121 | struct nuc900_bcd_time *gettm) | ||
122 | { | ||
123 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | ||
124 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | ||
125 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
126 | |||
127 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | ||
128 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | ||
129 | gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16; | ||
130 | } | ||
131 | |||
132 | static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled) | ||
133 | { | ||
134 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
135 | |||
136 | if (enabled) | ||
137 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
138 | (TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
139 | else | ||
140 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
141 | (~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
147 | { | ||
148 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
149 | |||
150 | if (enabled) | ||
151 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
152 | (ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
153 | else | ||
154 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
155 | (~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
161 | { | ||
162 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
163 | unsigned int timeval, clrval; | ||
164 | |||
165 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | ||
166 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | ||
167 | |||
168 | nuc900_rtc_bcd2bin(timeval, clrval, tm); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
174 | { | ||
175 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
176 | struct nuc900_bcd_time gettm; | ||
177 | unsigned long val; | ||
178 | int *err; | ||
179 | |||
180 | nuc900_rtc_bin2bcd(tm, &gettm); | ||
181 | |||
182 | err = check_rtc_access_enable(rtc); | ||
183 | if (IS_ERR(err)) | ||
184 | return PTR_ERR(err); | ||
185 | |||
186 | val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; | ||
187 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CLR); | ||
188 | |||
189 | val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; | ||
190 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TLR); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
196 | { | ||
197 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
198 | unsigned int timeval, carval; | ||
199 | |||
200 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | ||
201 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | ||
202 | |||
203 | nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
209 | { | ||
210 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
211 | struct nuc900_bcd_time tm; | ||
212 | unsigned long val; | ||
213 | int *err; | ||
214 | |||
215 | nuc900_rtc_bin2bcd(&alrm->time, &tm); | ||
216 | |||
217 | err = check_rtc_access_enable(rtc); | ||
218 | if (IS_ERR(err)) | ||
219 | return PTR_ERR(err); | ||
220 | |||
221 | val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; | ||
222 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CAR); | ||
223 | |||
224 | val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; | ||
225 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TAR); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static struct rtc_class_ops nuc900_rtc_ops = { | ||
231 | .read_time = nuc900_rtc_read_time, | ||
232 | .set_time = nuc900_rtc_set_time, | ||
233 | .read_alarm = nuc900_rtc_read_alarm, | ||
234 | .set_alarm = nuc900_rtc_set_alarm, | ||
235 | .alarm_irq_enable = nuc900_alarm_irq_enable, | ||
236 | .update_irq_enable = nuc900_update_irq_enable, | ||
237 | }; | ||
238 | |||
239 | static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | ||
240 | { | ||
241 | struct resource *res; | ||
242 | struct nuc900_rtc *nuc900_rtc; | ||
243 | int err = 0; | ||
244 | |||
245 | nuc900_rtc = kzalloc(sizeof(struct nuc900_rtc), GFP_KERNEL); | ||
246 | if (!nuc900_rtc) { | ||
247 | dev_err(&pdev->dev, "kzalloc nuc900_rtc failed\n"); | ||
248 | return -ENOMEM; | ||
249 | } | ||
250 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
251 | if (!res) { | ||
252 | dev_err(&pdev->dev, "platform_get_resource failed\n"); | ||
253 | err = -ENXIO; | ||
254 | goto fail1; | ||
255 | } | ||
256 | |||
257 | if (!request_mem_region(res->start, resource_size(res), | ||
258 | pdev->name)) { | ||
259 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
260 | err = -EBUSY; | ||
261 | goto fail1; | ||
262 | } | ||
263 | |||
264 | nuc900_rtc->rtc_reg = ioremap(res->start, resource_size(res)); | ||
265 | if (!nuc900_rtc->rtc_reg) { | ||
266 | dev_err(&pdev->dev, "ioremap rtc_reg failed\n"); | ||
267 | err = -ENOMEM; | ||
268 | goto fail2; | ||
269 | } | ||
270 | |||
271 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
272 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
273 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
274 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
275 | err = -EBUSY; | ||
276 | goto fail3; | ||
277 | } | ||
278 | |||
279 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
280 | &nuc900_rtc_ops, THIS_MODULE); | ||
281 | if (IS_ERR(nuc900_rtc->rtcdev)) { | ||
282 | dev_err(&pdev->dev, "rtc device register faild\n"); | ||
283 | err = PTR_ERR(nuc900_rtc->rtcdev); | ||
284 | goto fail4; | ||
285 | } | ||
286 | |||
287 | platform_set_drvdata(pdev, nuc900_rtc); | ||
288 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | ||
289 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | ||
290 | |||
291 | return 0; | ||
292 | |||
293 | fail4: free_irq(nuc900_rtc->irq_num, nuc900_rtc); | ||
294 | fail3: iounmap(nuc900_rtc->rtc_reg); | ||
295 | fail2: release_mem_region(res->start, resource_size(res)); | ||
296 | fail1: kfree(nuc900_rtc); | ||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | ||
301 | { | ||
302 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | ||
303 | struct resource *res; | ||
304 | |||
305 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
306 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | ||
307 | iounmap(nuc900_rtc->rtc_reg); | ||
308 | |||
309 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
310 | release_mem_region(res->start, resource_size(res)); | ||
311 | |||
312 | kfree(nuc900_rtc); | ||
313 | |||
314 | platform_set_drvdata(pdev, NULL); | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static struct platform_driver nuc900_rtc_driver = { | ||
320 | .remove = __devexit_p(nuc900_rtc_remove), | ||
321 | .driver = { | ||
322 | .name = "nuc900-rtc", | ||
323 | .owner = THIS_MODULE, | ||
324 | }, | ||
325 | }; | ||
326 | |||
327 | static int __init nuc900_rtc_init(void) | ||
328 | { | ||
329 | return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe); | ||
330 | } | ||
331 | |||
332 | static void __exit nuc900_rtc_exit(void) | ||
333 | { | ||
334 | platform_driver_unregister(&nuc900_rtc_driver); | ||
335 | } | ||
336 | |||
337 | module_init(nuc900_rtc_init); | ||
338 | module_exit(nuc900_rtc_exit); | ||
339 | |||
340 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
341 | MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); | ||
342 | MODULE_LICENSE("GPL"); | ||
343 | MODULE_ALIAS("platform:nuc900-rtc"); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0587d53987fe..64d9727b7229 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -87,9 +87,10 @@ | |||
87 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 87 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) |
88 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 88 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) |
89 | 89 | ||
90 | static void __iomem *rtc_base; | ||
90 | 91 | ||
91 | #define rtc_read(addr) omap_readb(OMAP_RTC_BASE + (addr)) | 92 | #define rtc_read(addr) __raw_readb(rtc_base + (addr)) |
92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) | 93 | #define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) |
93 | 94 | ||
94 | 95 | ||
95 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 96 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
@@ -330,32 +331,31 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
330 | return -ENOENT; | 331 | return -ENOENT; |
331 | } | 332 | } |
332 | 333 | ||
333 | /* NOTE: using static mapping for RTC registers */ | ||
334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
335 | if (res && res->start != OMAP_RTC_BASE) { | 335 | if (!res) { |
336 | pr_debug("%s: RTC registers at %08x, expected %08x\n", | 336 | pr_debug("%s: RTC resource data missing\n", pdev->name); |
337 | pdev->name, (unsigned) res->start, OMAP_RTC_BASE); | ||
338 | return -ENOENT; | 337 | return -ENOENT; |
339 | } | 338 | } |
340 | 339 | ||
341 | if (res) | 340 | mem = request_mem_region(res->start, resource_size(res), pdev->name); |
342 | mem = request_mem_region(res->start, | ||
343 | res->end - res->start + 1, | ||
344 | pdev->name); | ||
345 | else | ||
346 | mem = NULL; | ||
347 | if (!mem) { | 341 | if (!mem) { |
348 | pr_debug("%s: RTC registers at %08x are not free\n", | 342 | pr_debug("%s: RTC registers at %08x are not free\n", |
349 | pdev->name, OMAP_RTC_BASE); | 343 | pdev->name, res->start); |
350 | return -EBUSY; | 344 | return -EBUSY; |
351 | } | 345 | } |
352 | 346 | ||
347 | rtc_base = ioremap(res->start, resource_size(res)); | ||
348 | if (!rtc_base) { | ||
349 | pr_debug("%s: RTC registers can't be mapped\n", pdev->name); | ||
350 | goto fail; | ||
351 | } | ||
352 | |||
353 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 353 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
354 | &omap_rtc_ops, THIS_MODULE); | 354 | &omap_rtc_ops, THIS_MODULE); |
355 | if (IS_ERR(rtc)) { | 355 | if (IS_ERR(rtc)) { |
356 | pr_debug("%s: can't register RTC device, err %ld\n", | 356 | pr_debug("%s: can't register RTC device, err %ld\n", |
357 | pdev->name, PTR_ERR(rtc)); | 357 | pdev->name, PTR_ERR(rtc)); |
358 | goto fail; | 358 | goto fail0; |
359 | } | 359 | } |
360 | platform_set_drvdata(pdev, rtc); | 360 | platform_set_drvdata(pdev, rtc); |
361 | dev_set_drvdata(&rtc->dev, mem); | 361 | dev_set_drvdata(&rtc->dev, mem); |
@@ -380,13 +380,14 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
380 | dev_name(&rtc->dev), rtc)) { | 380 | dev_name(&rtc->dev), rtc)) { |
381 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", | 381 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", |
382 | pdev->name, omap_rtc_timer); | 382 | pdev->name, omap_rtc_timer); |
383 | goto fail0; | 383 | goto fail1; |
384 | } | 384 | } |
385 | if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, | 385 | if ((omap_rtc_timer != omap_rtc_alarm) && |
386 | dev_name(&rtc->dev), rtc)) { | 386 | (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, |
387 | dev_name(&rtc->dev), rtc))) { | ||
387 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", | 388 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", |
388 | pdev->name, omap_rtc_alarm); | 389 | pdev->name, omap_rtc_alarm); |
389 | goto fail1; | 390 | goto fail2; |
390 | } | 391 | } |
391 | 392 | ||
392 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ | 393 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ |
@@ -419,10 +420,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
419 | 420 | ||
420 | return 0; | 421 | return 0; |
421 | 422 | ||
422 | fail1: | 423 | fail2: |
423 | free_irq(omap_rtc_timer, NULL); | 424 | free_irq(omap_rtc_timer, NULL); |
424 | fail0: | 425 | fail1: |
425 | rtc_device_unregister(rtc); | 426 | rtc_device_unregister(rtc); |
427 | fail0: | ||
428 | iounmap(rtc_base); | ||
426 | fail: | 429 | fail: |
427 | release_resource(mem); | 430 | release_resource(mem); |
428 | return -EIO; | 431 | return -EIO; |
@@ -438,7 +441,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
438 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 441 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
439 | 442 | ||
440 | free_irq(omap_rtc_timer, rtc); | 443 | free_irq(omap_rtc_timer, rtc); |
441 | free_irq(omap_rtc_alarm, rtc); | 444 | |
445 | if (omap_rtc_timer != omap_rtc_alarm) | ||
446 | free_irq(omap_rtc_alarm, rtc); | ||
442 | 447 | ||
443 | release_resource(dev_get_drvdata(&rtc->dev)); | 448 | release_resource(dev_get_drvdata(&rtc->dev)); |
444 | rtc_device_unregister(rtc); | 449 | rtc_device_unregister(rtc); |
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 4c5d5d0c4cfc..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> |
@@ -58,6 +59,7 @@ struct pcf50633_time { | |||
58 | struct pcf50633_rtc { | 59 | struct pcf50633_rtc { |
59 | int alarm_enabled; | 60 | int alarm_enabled; |
60 | int second_enabled; | 61 | int second_enabled; |
62 | int alarm_pending; | ||
61 | 63 | ||
62 | struct pcf50633 *pcf; | 64 | struct pcf50633 *pcf; |
63 | struct rtc_device *rtc_dev; | 65 | struct rtc_device *rtc_dev; |
@@ -209,6 +211,7 @@ static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
209 | rtc = dev_get_drvdata(dev); | 211 | rtc = dev_get_drvdata(dev); |
210 | 212 | ||
211 | alrm->enabled = rtc->alarm_enabled; | 213 | alrm->enabled = rtc->alarm_enabled; |
214 | alrm->pending = rtc->alarm_pending; | ||
212 | 215 | ||
213 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, | 216 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, |
214 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 217 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
@@ -244,6 +247,8 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
244 | /* Returns 0 on success */ | 247 | /* Returns 0 on success */ |
245 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, | 248 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, |
246 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 249 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
250 | if (!alrm->enabled) | ||
251 | rtc->alarm_pending = 0; | ||
247 | 252 | ||
248 | if (!alarm_masked || alrm->enabled) | 253 | if (!alarm_masked || alrm->enabled) |
249 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | 254 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); |
@@ -268,6 +273,7 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
268 | switch (irq) { | 273 | switch (irq) { |
269 | case PCF50633_IRQ_ALARM: | 274 | case PCF50633_IRQ_ALARM: |
270 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); | 275 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); |
276 | rtc->alarm_pending = 1; | ||
271 | break; | 277 | break; |
272 | case PCF50633_IRQ_SECOND: | 278 | case PCF50633_IRQ_SECOND: |
273 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | 279 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); |
@@ -277,16 +283,13 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
277 | 283 | ||
278 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | 284 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) |
279 | { | 285 | { |
280 | struct pcf50633_subdev_pdata *pdata; | ||
281 | struct pcf50633_rtc *rtc; | 286 | struct pcf50633_rtc *rtc; |
282 | 287 | ||
283 | |||
284 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 288 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
285 | if (!rtc) | 289 | if (!rtc) |
286 | return -ENOMEM; | 290 | return -ENOMEM; |
287 | 291 | ||
288 | pdata = pdev->dev.platform_data; | 292 | rtc->pcf = dev_to_pcf50633(pdev->dev.parent); |
289 | rtc->pcf = pdata->pcf; | ||
290 | platform_set_drvdata(pdev, rtc); | 293 | platform_set_drvdata(pdev, rtc); |
291 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, | 294 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, |
292 | &pcf50633_rtc_ops, THIS_MODULE); | 295 | &pcf50633_rtc_ops, THIS_MODULE); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index b725913ccbe8..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 | ||
@@ -212,6 +213,8 @@ static int pcf8563_probe(struct i2c_client *client, | |||
212 | 213 | ||
213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 214 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
214 | 215 | ||
216 | i2c_set_clientdata(client, pcf8563); | ||
217 | |||
215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 218 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
216 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); | 219 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); |
217 | 220 | ||
@@ -220,8 +223,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
220 | goto exit_kfree; | 223 | goto exit_kfree; |
221 | } | 224 | } |
222 | 225 | ||
223 | i2c_set_clientdata(client, pcf8563); | ||
224 | |||
225 | return 0; | 226 | return 0; |
226 | 227 | ||
227 | exit_kfree: | 228 | exit_kfree: |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 7d33cda3f8f6..2d201afead3b 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -277,6 +277,8 @@ static int pcf8583_probe(struct i2c_client *client, | |||
277 | if (!pcf8583) | 277 | if (!pcf8583) |
278 | return -ENOMEM; | 278 | return -ENOMEM; |
279 | 279 | ||
280 | i2c_set_clientdata(client, pcf8583); | ||
281 | |||
280 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, | 282 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, |
281 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); | 283 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); |
282 | 284 | ||
@@ -285,7 +287,6 @@ static int pcf8583_probe(struct i2c_client *client, | |||
285 | goto exit_kfree; | 287 | goto exit_kfree; |
286 | } | 288 | } |
287 | 289 | ||
288 | i2c_set_clientdata(client, pcf8583); | ||
289 | return 0; | 290 | return 0; |
290 | 291 | ||
291 | exit_kfree: | 292 | exit_kfree: |
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 f41873f98f66..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,42 +37,214 @@ | |||
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) | ||
40 | { | 81 | { |
41 | struct rtc_device *rtc = dev_id; | 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); | ||
42 | 89 | ||
43 | rtc_update_irq(rtc, 1, RTC_AF); | 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); | ||
44 | 94 | ||
45 | return IRQ_HANDLED; | 95 | return 0; |
46 | } | 96 | } |
47 | 97 | ||
48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 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) | ||
49 | { | 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; | ||
50 | struct pl031_local *ldata = dev_get_drvdata(dev); | 168 | struct pl031_local *ldata = dev_get_drvdata(dev); |
169 | int ret; | ||
51 | 170 | ||
52 | switch (cmd) { | 171 | ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); |
53 | case RTC_AIE_OFF: | 172 | if (ret == 0) { |
54 | __raw_writel(1, ldata->base + RTC_MIS); | 173 | writel(bcd_year, ldata->base + RTC_YLR); |
55 | return 0; | 174 | writel(time, ldata->base + RTC_LR); |
56 | case RTC_AIE_ON: | ||
57 | __raw_writel(0, ldata->base + RTC_MIS); | ||
58 | return 0; | ||
59 | } | 175 | } |
60 | 176 | ||
61 | return -ENOIOCTLCMD; | 177 | return ret; |
178 | } | ||
179 | |||
180 | static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
181 | { | ||
182 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
183 | int ret; | ||
184 | |||
185 | ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), | ||
186 | readl(ldata->base + RTC_YMR), &alarm->time); | ||
187 | |||
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; | ||
192 | } | ||
193 | |||
194 | static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
195 | { | ||
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); | ||
236 | |||
237 | return IRQ_HANDLED; | ||
238 | } | ||
239 | |||
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) |
65 | { | 244 | { |
66 | struct pl031_local *ldata = dev_get_drvdata(dev); | 245 | struct pl031_local *ldata = dev_get_drvdata(dev); |
67 | 246 | ||
68 | rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm); | 247 | rtc_time_to_tm(readl(ldata->base + RTC_DR), tm); |
69 | 248 | ||
70 | return 0; | 249 | return 0; |
71 | } | 250 | } |
@@ -74,20 +253,24 @@ 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 | __raw_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) |
85 | { | 267 | { |
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(__raw_readl(ldata->base + RTC_MR), &alarm->time); | 270 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); |
89 | alarm->pending = __raw_readl(ldata->base + RTC_RIS); | 271 | |
90 | alarm->enabled = __raw_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); | ||
308 | |||
309 | /* Now start the timer */ | ||
310 | writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN, | ||
311 | ldata->base + RTC_TCR); | ||
99 | 312 | ||
100 | rtc_tm_to_time(&alarm->time, &time); | 313 | } else { |
314 | writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI), | ||
315 | ldata->base + RTC_IMSC); | ||
101 | 316 | ||
102 | __raw_writel(time, ldata->base + RTC_MR); | 317 | /* Also stop the timer */ |
103 | __raw_writel(!alarm->enabled, ldata->base + RTC_MIS); | 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); |
392 | |||
393 | /* Enable the clockwatch on ST Variants */ | ||
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); | ||
158 | 398 | ||
159 | ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, | 399 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, |
160 | THIS_MODULE); | 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,58 @@ 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, | ||
475 | }, | ||
185 | {0, 0}, | 476 | {0, 0}, |
186 | }; | 477 | }; |
187 | 478 | ||
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index 747ca194fad4..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 | ||
@@ -456,7 +457,7 @@ static int pxa_rtc_resume(struct device *dev) | |||
456 | return 0; | 457 | return 0; |
457 | } | 458 | } |
458 | 459 | ||
459 | static struct dev_pm_ops pxa_rtc_pm_ops = { | 460 | static const struct dev_pm_ops pxa_rtc_pm_ops = { |
460 | .suspend = pxa_rtc_suspend, | 461 | .suspend = pxa_rtc_suspend, |
461 | .resume = pxa_rtc_resume, | 462 | .resume = pxa_rtc_resume, |
462 | }; | 463 | }; |
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c new file mode 100644 index 000000000000..a95f733bb15a --- /dev/null +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Ricoh RP5C01 RTC Driver | ||
3 | * | ||
4 | * Copyright 2009 Geert Uytterhoeven | ||
5 | * | ||
6 | * Based on the A3000 TOD code in arch/m68k/amiga/config.c | ||
7 | * Copyright (C) 1993 Hamish Macdonald | ||
8 | */ | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | |||
18 | enum { | ||
19 | RP5C01_1_SECOND = 0x0, /* MODE 00 */ | ||
20 | RP5C01_10_SECOND = 0x1, /* MODE 00 */ | ||
21 | RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */ | ||
22 | RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */ | ||
23 | RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */ | ||
24 | RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */ | ||
25 | RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */ | ||
26 | RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */ | ||
27 | RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */ | ||
28 | RP5C01_1_MONTH = 0x9, /* MODE 00 */ | ||
29 | RP5C01_10_MONTH = 0xa, /* MODE 00 */ | ||
30 | RP5C01_1_YEAR = 0xb, /* MODE 00 */ | ||
31 | RP5C01_10_YEAR = 0xc, /* MODE 00 */ | ||
32 | |||
33 | RP5C01_12_24_SELECT = 0xa, /* MODE 01 */ | ||
34 | RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */ | ||
35 | |||
36 | RP5C01_MODE = 0xd, /* all modes */ | ||
37 | RP5C01_TEST = 0xe, /* all modes */ | ||
38 | RP5C01_RESET = 0xf, /* all modes */ | ||
39 | }; | ||
40 | |||
41 | #define RP5C01_12_24_SELECT_12 (0 << 0) | ||
42 | #define RP5C01_12_24_SELECT_24 (1 << 0) | ||
43 | |||
44 | #define RP5C01_10_HOUR_AM (0 << 1) | ||
45 | #define RP5C01_10_HOUR_PM (1 << 1) | ||
46 | |||
47 | #define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */ | ||
48 | #define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */ | ||
49 | |||
50 | #define RP5C01_MODE_MODE_MASK (3 << 0) | ||
51 | #define RP5C01_MODE_MODE00 (0 << 0) /* time */ | ||
52 | #define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */ | ||
53 | #define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */ | ||
54 | #define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */ | ||
55 | |||
56 | #define RP5C01_RESET_1HZ_PULSE (1 << 3) | ||
57 | #define RP5C01_RESET_16HZ_PULSE (1 << 2) | ||
58 | #define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */ | ||
59 | /* seconds or smaller units */ | ||
60 | #define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */ | ||
61 | |||
62 | |||
63 | struct rp5c01_priv { | ||
64 | u32 __iomem *regs; | ||
65 | struct rtc_device *rtc; | ||
66 | }; | ||
67 | |||
68 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, | ||
69 | unsigned int reg) | ||
70 | { | ||
71 | return __raw_readl(&priv->regs[reg]) & 0xf; | ||
72 | } | ||
73 | |||
74 | static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, | ||
75 | unsigned int reg) | ||
76 | { | ||
77 | return __raw_writel(val, &priv->regs[reg]); | ||
78 | } | ||
79 | |||
80 | static void rp5c01_lock(struct rp5c01_priv *priv) | ||
81 | { | ||
82 | rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE); | ||
83 | } | ||
84 | |||
85 | static void rp5c01_unlock(struct rp5c01_priv *priv) | ||
86 | { | ||
87 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
88 | RP5C01_MODE); | ||
89 | } | ||
90 | |||
91 | static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | ||
92 | { | ||
93 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
94 | |||
95 | rp5c01_lock(priv); | ||
96 | |||
97 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + | ||
98 | rp5c01_read(priv, RP5C01_1_SECOND); | ||
99 | tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 + | ||
100 | rp5c01_read(priv, RP5C01_1_MINUTE); | ||
101 | tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 + | ||
102 | rp5c01_read(priv, RP5C01_1_HOUR); | ||
103 | tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 + | ||
104 | rp5c01_read(priv, RP5C01_1_DAY); | ||
105 | tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK); | ||
106 | tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 + | ||
107 | rp5c01_read(priv, RP5C01_1_MONTH) - 1; | ||
108 | tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 + | ||
109 | rp5c01_read(priv, RP5C01_1_YEAR); | ||
110 | if (tm->tm_year <= 69) | ||
111 | tm->tm_year += 100; | ||
112 | |||
113 | rp5c01_unlock(priv); | ||
114 | |||
115 | return rtc_valid_tm(tm); | ||
116 | } | ||
117 | |||
118 | static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | ||
119 | { | ||
120 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
121 | |||
122 | rp5c01_lock(priv); | ||
123 | |||
124 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); | ||
125 | rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND); | ||
126 | rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE); | ||
127 | rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE); | ||
128 | rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR); | ||
129 | rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR); | ||
130 | rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY); | ||
131 | rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY); | ||
132 | if (tm->tm_wday != -1) | ||
133 | rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK); | ||
134 | rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH); | ||
135 | rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH); | ||
136 | if (tm->tm_year >= 100) | ||
137 | tm->tm_year -= 100; | ||
138 | rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR); | ||
139 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); | ||
140 | |||
141 | rp5c01_unlock(priv); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static const struct rtc_class_ops rp5c01_rtc_ops = { | ||
146 | .read_time = rp5c01_read_time, | ||
147 | .set_time = rp5c01_set_time, | ||
148 | }; | ||
149 | |||
150 | static int __init rp5c01_rtc_probe(struct platform_device *dev) | ||
151 | { | ||
152 | struct resource *res; | ||
153 | struct rp5c01_priv *priv; | ||
154 | struct rtc_device *rtc; | ||
155 | int error; | ||
156 | |||
157 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
158 | if (!res) | ||
159 | return -ENODEV; | ||
160 | |||
161 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
162 | if (!priv) | ||
163 | return -ENOMEM; | ||
164 | |||
165 | priv->regs = ioremap(res->start, resource_size(res)); | ||
166 | if (!priv->regs) { | ||
167 | error = -ENOMEM; | ||
168 | goto out_free_priv; | ||
169 | } | ||
170 | |||
171 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, | ||
172 | THIS_MODULE); | ||
173 | if (IS_ERR(rtc)) { | ||
174 | error = PTR_ERR(rtc); | ||
175 | goto out_unmap; | ||
176 | } | ||
177 | |||
178 | priv->rtc = rtc; | ||
179 | platform_set_drvdata(dev, priv); | ||
180 | return 0; | ||
181 | |||
182 | out_unmap: | ||
183 | iounmap(priv->regs); | ||
184 | out_free_priv: | ||
185 | kfree(priv); | ||
186 | return error; | ||
187 | } | ||
188 | |||
189 | static int __exit rp5c01_rtc_remove(struct platform_device *dev) | ||
190 | { | ||
191 | struct rp5c01_priv *priv = platform_get_drvdata(dev); | ||
192 | |||
193 | rtc_device_unregister(priv->rtc); | ||
194 | iounmap(priv->regs); | ||
195 | kfree(priv); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static struct platform_driver rp5c01_rtc_driver = { | ||
200 | .driver = { | ||
201 | .name = "rtc-rp5c01", | ||
202 | .owner = THIS_MODULE, | ||
203 | }, | ||
204 | .remove = __exit_p(rp5c01_rtc_remove), | ||
205 | }; | ||
206 | |||
207 | static int __init rp5c01_rtc_init(void) | ||
208 | { | ||
209 | return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe); | ||
210 | } | ||
211 | |||
212 | static void __exit rp5c01_rtc_fini(void) | ||
213 | { | ||
214 | platform_driver_unregister(&rp5c01_rtc_driver); | ||
215 | } | ||
216 | |||
217 | module_init(rp5c01_rtc_init); | ||
218 | module_exit(rp5c01_rtc_fini); | ||
219 | |||
220 | MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); | ||
221 | MODULE_LICENSE("GPL"); | ||
222 | MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver"); | ||
223 | MODULE_ALIAS("platform:rtc-rp5c01"); | ||
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-sa1100.c b/drivers/rtc/rtc-sa1100.c index 29f98a70586e..e4a44b641702 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -407,7 +407,7 @@ static int sa1100_rtc_resume(struct device *dev) | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static struct dev_pm_ops sa1100_rtc_pm_ops = { | 410 | static const struct dev_pm_ops sa1100_rtc_pm_ops = { |
411 | .suspend = sa1100_rtc_suspend, | 411 | .suspend = sa1100_rtc_suspend, |
412 | .resume = sa1100_rtc_resume, | 412 | .resume = sa1100_rtc_resume, |
413 | }; | 413 | }; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e6ed5404bca0..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" |
@@ -826,7 +827,7 @@ static int sh_rtc_resume(struct device *dev) | |||
826 | return 0; | 827 | return 0; |
827 | } | 828 | } |
828 | 829 | ||
829 | static struct dev_pm_ops sh_rtc_dev_pm_ops = { | 830 | static const struct dev_pm_ops sh_rtc_dev_pm_ops = { |
830 | .suspend = sh_rtc_suspend, | 831 | .suspend = sh_rtc_suspend, |
831 | .resume = sh_rtc_resume, | 832 | .resume = sh_rtc_resume, |
832 | }; | 833 | }; |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 7d1547b0070e..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> |
@@ -62,7 +63,6 @@ | |||
62 | struct rtc_plat_data { | 63 | struct rtc_plat_data { |
63 | struct rtc_device *rtc; | 64 | struct rtc_device *rtc; |
64 | void __iomem *ioaddr; | 65 | void __iomem *ioaddr; |
65 | unsigned long baseaddr; | ||
66 | unsigned long last_jiffies; | 66 | unsigned long last_jiffies; |
67 | int irq; | 67 | int irq; |
68 | unsigned int irqen; | 68 | unsigned int irqen; |
@@ -70,6 +70,7 @@ struct rtc_plat_data { | |||
70 | int alrm_min; | 70 | int alrm_min; |
71 | int alrm_hour; | 71 | int alrm_hour; |
72 | int alrm_mday; | 72 | int alrm_mday; |
73 | spinlock_t lock; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) | 76 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -142,7 +143,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
142 | unsigned long irqflags; | 143 | unsigned long irqflags; |
143 | u8 flags; | 144 | u8 flags; |
144 | 145 | ||
145 | spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags); | 146 | spin_lock_irqsave(&pdata->lock, irqflags); |
146 | 147 | ||
147 | flags = readb(ioaddr + RTC_FLAGS); | 148 | flags = readb(ioaddr + RTC_FLAGS); |
148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | 149 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); |
@@ -162,7 +163,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); | 163 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); |
163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 164 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
164 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); | 165 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); |
165 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags); | 166 | spin_unlock_irqrestore(&pdata->lock, irqflags); |
166 | } | 167 | } |
167 | 168 | ||
168 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 169 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -202,56 +203,53 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
202 | struct platform_device *pdev = dev_id; | 203 | struct platform_device *pdev = dev_id; |
203 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 204 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
204 | void __iomem *ioaddr = pdata->ioaddr; | 205 | void __iomem *ioaddr = pdata->ioaddr; |
205 | unsigned long events = RTC_IRQF; | 206 | unsigned long events = 0; |
206 | 207 | ||
208 | spin_lock(&pdata->lock); | ||
207 | /* read and clear interrupt */ | 209 | /* read and clear interrupt */ |
208 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 210 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
209 | return IRQ_NONE; | 211 | events = RTC_IRQF; |
210 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 212 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
211 | events |= RTC_UF; | 213 | events |= RTC_UF; |
212 | else | 214 | else |
213 | events |= RTC_AF; | 215 | events |= RTC_AF; |
214 | rtc_update_irq(pdata->rtc, 1, events); | 216 | if (likely(pdata->rtc)) |
215 | return IRQ_HANDLED; | 217 | rtc_update_irq(pdata->rtc, 1, events); |
218 | } | ||
219 | spin_unlock(&pdata->lock); | ||
220 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
216 | } | 221 | } |
217 | 222 | ||
218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 223 | static int stk17ta8_rtc_alarm_irq_enable(struct device *dev, |
219 | unsigned long arg) | 224 | unsigned int enabled) |
220 | { | 225 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | 226 | struct platform_device *pdev = to_platform_device(dev); |
222 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 227 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
223 | 228 | ||
224 | if (pdata->irq <= 0) | 229 | if (pdata->irq <= 0) |
225 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 230 | return -EINVAL; |
226 | switch (cmd) { | 231 | if (enabled) |
227 | case RTC_AIE_OFF: | ||
228 | pdata->irqen &= ~RTC_AF; | ||
229 | stk17ta8_rtc_update_alarm(pdata); | ||
230 | break; | ||
231 | case RTC_AIE_ON: | ||
232 | pdata->irqen |= RTC_AF; | 232 | pdata->irqen |= RTC_AF; |
233 | stk17ta8_rtc_update_alarm(pdata); | 233 | else |
234 | break; | 234 | pdata->irqen &= ~RTC_AF; |
235 | default: | 235 | stk17ta8_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 236 | return 0; |
239 | } | 237 | } |
240 | 238 | ||
241 | static const struct rtc_class_ops stk17ta8_rtc_ops = { | 239 | static const struct rtc_class_ops stk17ta8_rtc_ops = { |
242 | .read_time = stk17ta8_rtc_read_time, | 240 | .read_time = stk17ta8_rtc_read_time, |
243 | .set_time = stk17ta8_rtc_set_time, | 241 | .set_time = stk17ta8_rtc_set_time, |
244 | .read_alarm = stk17ta8_rtc_read_alarm, | 242 | .read_alarm = stk17ta8_rtc_read_alarm, |
245 | .set_alarm = stk17ta8_rtc_set_alarm, | 243 | .set_alarm = stk17ta8_rtc_set_alarm, |
246 | .ioctl = stk17ta8_rtc_ioctl, | 244 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, |
247 | }; | 245 | }; |
248 | 246 | ||
249 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | 247 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, |
250 | struct bin_attribute *attr, char *buf, | 248 | struct bin_attribute *attr, char *buf, |
251 | loff_t pos, size_t size) | 249 | loff_t pos, size_t size) |
252 | { | 250 | { |
253 | struct platform_device *pdev = | 251 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 252 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 253 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 254 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 255 | ssize_t count; |
@@ -265,8 +263,8 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj, | |||
265 | struct bin_attribute *attr, char *buf, | 263 | struct bin_attribute *attr, char *buf, |
266 | loff_t pos, size_t size) | 264 | loff_t pos, size_t size) |
267 | { | 265 | { |
268 | struct platform_device *pdev = | 266 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 267 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 268 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 269 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 270 | ssize_t count; |
@@ -286,33 +284,28 @@ static struct bin_attribute stk17ta8_nvram_attr = { | |||
286 | .write = stk17ta8_nvram_write, | 284 | .write = stk17ta8_nvram_write, |
287 | }; | 285 | }; |
288 | 286 | ||
289 | static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | 287 | static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) |
290 | { | 288 | { |
291 | struct rtc_device *rtc; | ||
292 | struct resource *res; | 289 | struct resource *res; |
293 | unsigned int cal; | 290 | unsigned int cal; |
294 | unsigned int flags; | 291 | unsigned int flags; |
295 | struct rtc_plat_data *pdata; | 292 | struct rtc_plat_data *pdata; |
296 | void __iomem *ioaddr = NULL; | 293 | void __iomem *ioaddr; |
297 | int ret = 0; | 294 | int ret = 0; |
298 | 295 | ||
299 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 296 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
300 | if (!res) | 297 | if (!res) |
301 | return -ENODEV; | 298 | return -ENODEV; |
302 | 299 | ||
303 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 300 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
304 | if (!pdata) | 301 | if (!pdata) |
305 | return -ENOMEM; | 302 | return -ENOMEM; |
306 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 303 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
307 | ret = -EBUSY; | 304 | pdev->name)) |
308 | goto out; | 305 | return -EBUSY; |
309 | } | 306 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
310 | pdata->baseaddr = res->start; | 307 | if (!ioaddr) |
311 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 308 | return -ENOMEM; |
312 | if (!ioaddr) { | ||
313 | ret = -ENOMEM; | ||
314 | goto out; | ||
315 | } | ||
316 | pdata->ioaddr = ioaddr; | 309 | pdata->ioaddr = ioaddr; |
317 | pdata->irq = platform_get_irq(pdev, 0); | 310 | pdata->irq = platform_get_irq(pdev, 0); |
318 | 311 | ||
@@ -328,9 +321,13 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | |||
328 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) | 321 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) |
329 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 322 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
330 | 323 | ||
324 | spin_lock_init(&pdata->lock); | ||
325 | pdata->last_jiffies = jiffies; | ||
326 | platform_set_drvdata(pdev, pdata); | ||
331 | if (pdata->irq > 0) { | 327 | if (pdata->irq > 0) { |
332 | writeb(0, ioaddr + RTC_INTERRUPTS); | 328 | writeb(0, ioaddr + RTC_INTERRUPTS); |
333 | if (request_irq(pdata->irq, stk17ta8_rtc_interrupt, | 329 | if (devm_request_irq(&pdev->dev, pdata->irq, |
330 | stk17ta8_rtc_interrupt, | ||
334 | IRQF_DISABLED | IRQF_SHARED, | 331 | IRQF_DISABLED | IRQF_SHARED, |
335 | pdev->name, pdev) < 0) { | 332 | pdev->name, pdev) < 0) { |
336 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 333 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -338,29 +335,14 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | |||
338 | } | 335 | } |
339 | } | 336 | } |
340 | 337 | ||
341 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 338 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, |
342 | &stk17ta8_rtc_ops, THIS_MODULE); | 339 | &stk17ta8_rtc_ops, THIS_MODULE); |
343 | if (IS_ERR(rtc)) { | 340 | if (IS_ERR(pdata->rtc)) |
344 | ret = PTR_ERR(rtc); | 341 | return PTR_ERR(pdata->rtc); |
345 | goto out; | 342 | |
346 | } | ||
347 | pdata->rtc = rtc; | ||
348 | pdata->last_jiffies = jiffies; | ||
349 | platform_set_drvdata(pdev, pdata); | ||
350 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 343 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
351 | if (ret) | 344 | if (ret) |
352 | goto out; | ||
353 | return 0; | ||
354 | out: | ||
355 | if (pdata->rtc) | ||
356 | rtc_device_unregister(pdata->rtc); | 345 | rtc_device_unregister(pdata->rtc); |
357 | if (pdata->irq > 0) | ||
358 | free_irq(pdata->irq, pdev); | ||
359 | if (ioaddr) | ||
360 | iounmap(ioaddr); | ||
361 | if (pdata->baseaddr) | ||
362 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
363 | kfree(pdata); | ||
364 | return ret; | 346 | return ret; |
365 | } | 347 | } |
366 | 348 | ||
@@ -370,13 +352,8 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev) | |||
370 | 352 | ||
371 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 353 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
372 | rtc_device_unregister(pdata->rtc); | 354 | rtc_device_unregister(pdata->rtc); |
373 | if (pdata->irq > 0) { | 355 | if (pdata->irq > 0) |
374 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 356 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
375 | free_irq(pdata->irq, pdev); | ||
376 | } | ||
377 | iounmap(pdata->ioaddr); | ||
378 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
379 | kfree(pdata); | ||
380 | return 0; | 357 | return 0; |
381 | } | 358 | } |
382 | 359 | ||
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-twl4030.c b/drivers/rtc/rtc-twl.c index 9c8c70c497dc..ed1b86828124 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * rtc-twl4030.c -- TWL4030 Real Time Clock interface | 2 | * rtc-twl.c -- TWL Real Time Clock interface |
3 | * | 3 | * |
4 | * Copyright (C) 2007 MontaVista Software, Inc | 4 | * Copyright (C) 2007 MontaVista Software, Inc |
5 | * Author: Alexandre Rusev <source@mvista.com> | 5 | * Author: Alexandre Rusev <source@mvista.com> |
@@ -28,33 +28,81 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | 30 | ||
31 | #include <linux/i2c/twl4030.h> | 31 | #include <linux/i2c/twl.h> |
32 | 32 | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * RTC block register offsets (use TWL_MODULE_RTC) | 35 | * RTC block register offsets (use TWL_MODULE_RTC) |
36 | */ | 36 | */ |
37 | #define REG_SECONDS_REG 0x00 | 37 | enum { |
38 | #define REG_MINUTES_REG 0x01 | 38 | REG_SECONDS_REG = 0, |
39 | #define REG_HOURS_REG 0x02 | 39 | REG_MINUTES_REG, |
40 | #define REG_DAYS_REG 0x03 | 40 | REG_HOURS_REG, |
41 | #define REG_MONTHS_REG 0x04 | 41 | REG_DAYS_REG, |
42 | #define REG_YEARS_REG 0x05 | 42 | REG_MONTHS_REG, |
43 | #define REG_WEEKS_REG 0x06 | 43 | REG_YEARS_REG, |
44 | 44 | REG_WEEKS_REG, | |
45 | #define REG_ALARM_SECONDS_REG 0x07 | 45 | |
46 | #define REG_ALARM_MINUTES_REG 0x08 | 46 | REG_ALARM_SECONDS_REG, |
47 | #define REG_ALARM_HOURS_REG 0x09 | 47 | REG_ALARM_MINUTES_REG, |
48 | #define REG_ALARM_DAYS_REG 0x0A | 48 | REG_ALARM_HOURS_REG, |
49 | #define REG_ALARM_MONTHS_REG 0x0B | 49 | REG_ALARM_DAYS_REG, |
50 | #define REG_ALARM_YEARS_REG 0x0C | 50 | REG_ALARM_MONTHS_REG, |
51 | 51 | REG_ALARM_YEARS_REG, | |
52 | #define REG_RTC_CTRL_REG 0x0D | 52 | |
53 | #define REG_RTC_STATUS_REG 0x0E | 53 | REG_RTC_CTRL_REG, |
54 | #define REG_RTC_INTERRUPTS_REG 0x0F | 54 | REG_RTC_STATUS_REG, |
55 | 55 | REG_RTC_INTERRUPTS_REG, | |
56 | #define REG_RTC_COMP_LSB_REG 0x10 | 56 | |
57 | #define REG_RTC_COMP_MSB_REG 0x11 | 57 | REG_RTC_COMP_LSB_REG, |
58 | REG_RTC_COMP_MSB_REG, | ||
59 | }; | ||
60 | static const u8 twl4030_rtc_reg_map[] = { | ||
61 | [REG_SECONDS_REG] = 0x00, | ||
62 | [REG_MINUTES_REG] = 0x01, | ||
63 | [REG_HOURS_REG] = 0x02, | ||
64 | [REG_DAYS_REG] = 0x03, | ||
65 | [REG_MONTHS_REG] = 0x04, | ||
66 | [REG_YEARS_REG] = 0x05, | ||
67 | [REG_WEEKS_REG] = 0x06, | ||
68 | |||
69 | [REG_ALARM_SECONDS_REG] = 0x07, | ||
70 | [REG_ALARM_MINUTES_REG] = 0x08, | ||
71 | [REG_ALARM_HOURS_REG] = 0x09, | ||
72 | [REG_ALARM_DAYS_REG] = 0x0A, | ||
73 | [REG_ALARM_MONTHS_REG] = 0x0B, | ||
74 | [REG_ALARM_YEARS_REG] = 0x0C, | ||
75 | |||
76 | [REG_RTC_CTRL_REG] = 0x0D, | ||
77 | [REG_RTC_STATUS_REG] = 0x0E, | ||
78 | [REG_RTC_INTERRUPTS_REG] = 0x0F, | ||
79 | |||
80 | [REG_RTC_COMP_LSB_REG] = 0x10, | ||
81 | [REG_RTC_COMP_MSB_REG] = 0x11, | ||
82 | }; | ||
83 | static const u8 twl6030_rtc_reg_map[] = { | ||
84 | [REG_SECONDS_REG] = 0x00, | ||
85 | [REG_MINUTES_REG] = 0x01, | ||
86 | [REG_HOURS_REG] = 0x02, | ||
87 | [REG_DAYS_REG] = 0x03, | ||
88 | [REG_MONTHS_REG] = 0x04, | ||
89 | [REG_YEARS_REG] = 0x05, | ||
90 | [REG_WEEKS_REG] = 0x06, | ||
91 | |||
92 | [REG_ALARM_SECONDS_REG] = 0x08, | ||
93 | [REG_ALARM_MINUTES_REG] = 0x09, | ||
94 | [REG_ALARM_HOURS_REG] = 0x0A, | ||
95 | [REG_ALARM_DAYS_REG] = 0x0B, | ||
96 | [REG_ALARM_MONTHS_REG] = 0x0C, | ||
97 | [REG_ALARM_YEARS_REG] = 0x0D, | ||
98 | |||
99 | [REG_RTC_CTRL_REG] = 0x10, | ||
100 | [REG_RTC_STATUS_REG] = 0x11, | ||
101 | [REG_RTC_INTERRUPTS_REG] = 0x12, | ||
102 | |||
103 | [REG_RTC_COMP_LSB_REG] = 0x13, | ||
104 | [REG_RTC_COMP_MSB_REG] = 0x14, | ||
105 | }; | ||
58 | 106 | ||
59 | /* RTC_CTRL_REG bitfields */ | 107 | /* RTC_CTRL_REG bitfields */ |
60 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 | 108 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 |
@@ -84,31 +132,32 @@ | |||
84 | #define ALL_TIME_REGS 6 | 132 | #define ALL_TIME_REGS 6 |
85 | 133 | ||
86 | /*----------------------------------------------------------------------*/ | 134 | /*----------------------------------------------------------------------*/ |
135 | static u8 *rtc_reg_map; | ||
87 | 136 | ||
88 | /* | 137 | /* |
89 | * Supports 1 byte read from TWL4030 RTC register. | 138 | * Supports 1 byte read from TWL RTC register. |
90 | */ | 139 | */ |
91 | static int twl4030_rtc_read_u8(u8 *data, u8 reg) | 140 | static int twl_rtc_read_u8(u8 *data, u8 reg) |
92 | { | 141 | { |
93 | int ret; | 142 | int ret; |
94 | 143 | ||
95 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); | 144 | ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
96 | if (ret < 0) | 145 | if (ret < 0) |
97 | pr_err("twl4030_rtc: Could not read TWL4030" | 146 | pr_err("twl_rtc: Could not read TWL" |
98 | "register %X - error %d\n", reg, ret); | 147 | "register %X - error %d\n", reg, ret); |
99 | return ret; | 148 | return ret; |
100 | } | 149 | } |
101 | 150 | ||
102 | /* | 151 | /* |
103 | * Supports 1 byte write to TWL4030 RTC registers. | 152 | * Supports 1 byte write to TWL RTC registers. |
104 | */ | 153 | */ |
105 | static int twl4030_rtc_write_u8(u8 data, u8 reg) | 154 | static int twl_rtc_write_u8(u8 data, u8 reg) |
106 | { | 155 | { |
107 | int ret; | 156 | int ret; |
108 | 157 | ||
109 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); | 158 | ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
110 | if (ret < 0) | 159 | if (ret < 0) |
111 | pr_err("twl4030_rtc: Could not write TWL4030" | 160 | pr_err("twl_rtc: Could not write TWL" |
112 | "register %X - error %d\n", reg, ret); | 161 | "register %X - error %d\n", reg, ret); |
113 | return ret; | 162 | return ret; |
114 | } | 163 | } |
@@ -129,7 +178,7 @@ static int set_rtc_irq_bit(unsigned char bit) | |||
129 | 178 | ||
130 | val = rtc_irq_bits | bit; | 179 | val = rtc_irq_bits | bit; |
131 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; | 180 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; |
132 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 181 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
133 | if (ret == 0) | 182 | if (ret == 0) |
134 | rtc_irq_bits = val; | 183 | rtc_irq_bits = val; |
135 | 184 | ||
@@ -145,14 +194,14 @@ static int mask_rtc_irq_bit(unsigned char bit) | |||
145 | int ret; | 194 | int ret; |
146 | 195 | ||
147 | val = rtc_irq_bits & ~bit; | 196 | val = rtc_irq_bits & ~bit; |
148 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 197 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
149 | if (ret == 0) | 198 | if (ret == 0) |
150 | rtc_irq_bits = val; | 199 | rtc_irq_bits = val; |
151 | 200 | ||
152 | return ret; | 201 | return ret; |
153 | } | 202 | } |
154 | 203 | ||
155 | static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | 204 | static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) |
156 | { | 205 | { |
157 | int ret; | 206 | int ret; |
158 | 207 | ||
@@ -164,7 +213,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | |||
164 | return ret; | 213 | return ret; |
165 | } | 214 | } |
166 | 215 | ||
167 | static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | 216 | static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) |
168 | { | 217 | { |
169 | int ret; | 218 | int ret; |
170 | 219 | ||
@@ -177,7 +226,7 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
177 | } | 226 | } |
178 | 227 | ||
179 | /* | 228 | /* |
180 | * Gets current TWL4030 RTC time and date parameters. | 229 | * Gets current TWL RTC time and date parameters. |
181 | * | 230 | * |
182 | * The RTC's time/alarm representation is not what gmtime(3) requires | 231 | * The RTC's time/alarm representation is not what gmtime(3) requires |
183 | * Linux to use: | 232 | * Linux to use: |
@@ -185,24 +234,24 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
185 | * - Months are 1..12 vs Linux 0-11 | 234 | * - Months are 1..12 vs Linux 0-11 |
186 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | 235 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) |
187 | */ | 236 | */ |
188 | static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | 237 | static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) |
189 | { | 238 | { |
190 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 239 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
191 | int ret; | 240 | int ret; |
192 | u8 save_control; | 241 | u8 save_control; |
193 | 242 | ||
194 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 243 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
195 | if (ret < 0) | 244 | if (ret < 0) |
196 | return ret; | 245 | return ret; |
197 | 246 | ||
198 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; | 247 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; |
199 | 248 | ||
200 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 249 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
201 | if (ret < 0) | 250 | if (ret < 0) |
202 | return ret; | 251 | return ret; |
203 | 252 | ||
204 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 253 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
205 | REG_SECONDS_REG, ALL_TIME_REGS); | 254 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
206 | 255 | ||
207 | if (ret < 0) { | 256 | if (ret < 0) { |
208 | dev_err(dev, "rtc_read_time error %d\n", ret); | 257 | dev_err(dev, "rtc_read_time error %d\n", ret); |
@@ -219,7 +268,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
219 | return ret; | 268 | return ret; |
220 | } | 269 | } |
221 | 270 | ||
222 | static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | 271 | static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) |
223 | { | 272 | { |
224 | unsigned char save_control; | 273 | unsigned char save_control; |
225 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 274 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
@@ -233,18 +282,18 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
233 | rtc_data[6] = bin2bcd(tm->tm_year - 100); | 282 | rtc_data[6] = bin2bcd(tm->tm_year - 100); |
234 | 283 | ||
235 | /* Stop RTC while updating the TC registers */ | 284 | /* Stop RTC while updating the TC registers */ |
236 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 285 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
237 | if (ret < 0) | 286 | if (ret < 0) |
238 | goto out; | 287 | goto out; |
239 | 288 | ||
240 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 289 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
241 | twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 290 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
242 | if (ret < 0) | 291 | if (ret < 0) |
243 | goto out; | 292 | goto out; |
244 | 293 | ||
245 | /* update all the time registers in one shot */ | 294 | /* update all the time registers in one shot */ |
246 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, | 295 | ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, |
247 | REG_SECONDS_REG, ALL_TIME_REGS); | 296 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
248 | if (ret < 0) { | 297 | if (ret < 0) { |
249 | dev_err(dev, "rtc_set_time error %d\n", ret); | 298 | dev_err(dev, "rtc_set_time error %d\n", ret); |
250 | goto out; | 299 | goto out; |
@@ -252,22 +301,22 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
252 | 301 | ||
253 | /* Start back RTC */ | 302 | /* Start back RTC */ |
254 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; | 303 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; |
255 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 304 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
256 | 305 | ||
257 | out: | 306 | out: |
258 | return ret; | 307 | return ret; |
259 | } | 308 | } |
260 | 309 | ||
261 | /* | 310 | /* |
262 | * Gets current TWL4030 RTC alarm time. | 311 | * Gets current TWL RTC alarm time. |
263 | */ | 312 | */ |
264 | static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | 313 | static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) |
265 | { | 314 | { |
266 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 315 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
267 | int ret; | 316 | int ret; |
268 | 317 | ||
269 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 318 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
270 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 319 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
271 | if (ret < 0) { | 320 | if (ret < 0) { |
272 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | 321 | dev_err(dev, "rtc_read_alarm error %d\n", ret); |
273 | return ret; | 322 | return ret; |
@@ -288,12 +337,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
288 | return ret; | 337 | return ret; |
289 | } | 338 | } |
290 | 339 | ||
291 | static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 340 | static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
292 | { | 341 | { |
293 | unsigned char alarm_data[ALL_TIME_REGS + 1]; | 342 | unsigned char alarm_data[ALL_TIME_REGS + 1]; |
294 | int ret; | 343 | int ret; |
295 | 344 | ||
296 | ret = twl4030_rtc_alarm_irq_enable(dev, 0); | 345 | ret = twl_rtc_alarm_irq_enable(dev, 0); |
297 | if (ret) | 346 | if (ret) |
298 | goto out; | 347 | goto out; |
299 | 348 | ||
@@ -305,20 +354,20 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
305 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); | 354 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); |
306 | 355 | ||
307 | /* update all the alarm registers in one shot */ | 356 | /* update all the alarm registers in one shot */ |
308 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, | 357 | ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, |
309 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 358 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
310 | if (ret) { | 359 | if (ret) { |
311 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | 360 | dev_err(dev, "rtc_set_alarm error %d\n", ret); |
312 | goto out; | 361 | goto out; |
313 | } | 362 | } |
314 | 363 | ||
315 | if (alm->enabled) | 364 | if (alm->enabled) |
316 | ret = twl4030_rtc_alarm_irq_enable(dev, 1); | 365 | ret = twl_rtc_alarm_irq_enable(dev, 1); |
317 | out: | 366 | out: |
318 | return ret; | 367 | return ret; |
319 | } | 368 | } |
320 | 369 | ||
321 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | 370 | static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) |
322 | { | 371 | { |
323 | unsigned long events = 0; | 372 | unsigned long events = 0; |
324 | int ret = IRQ_NONE; | 373 | int ret = IRQ_NONE; |
@@ -333,7 +382,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
333 | local_irq_enable(); | 382 | local_irq_enable(); |
334 | #endif | 383 | #endif |
335 | 384 | ||
336 | res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 385 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
337 | if (res) | 386 | if (res) |
338 | goto out; | 387 | goto out; |
339 | /* | 388 | /* |
@@ -347,26 +396,28 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
347 | else | 396 | else |
348 | events |= RTC_IRQF | RTC_UF; | 397 | events |= RTC_IRQF | RTC_UF; |
349 | 398 | ||
350 | res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, | 399 | res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, |
351 | REG_RTC_STATUS_REG); | 400 | REG_RTC_STATUS_REG); |
352 | if (res) | 401 | if (res) |
353 | goto out; | 402 | goto out; |
354 | 403 | ||
355 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 | 404 | if (twl_class_is_4030()) { |
356 | * needs 2 reads to clear the interrupt. One read is done in | 405 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 |
357 | * do_twl4030_pwrirq(). Doing the second read, to clear | 406 | * needs 2 reads to clear the interrupt. One read is done in |
358 | * the bit. | 407 | * do_twl_pwrirq(). Doing the second read, to clear |
359 | * | 408 | * the bit. |
360 | * FIXME the reason PWR_ISR1 needs an extra read is that | 409 | * |
361 | * RTC_IF retriggered until we cleared REG_ALARM_M above. | 410 | * FIXME the reason PWR_ISR1 needs an extra read is that |
362 | * But re-reading like this is a bad hack; by doing so we | 411 | * RTC_IF retriggered until we cleared REG_ALARM_M above. |
363 | * risk wrongly clearing status for some other IRQ (losing | 412 | * But re-reading like this is a bad hack; by doing so we |
364 | * the interrupt). Be smarter about handling RTC_UF ... | 413 | * risk wrongly clearing status for some other IRQ (losing |
365 | */ | 414 | * the interrupt). Be smarter about handling RTC_UF ... |
366 | res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, | 415 | */ |
416 | res = twl_i2c_read_u8(TWL4030_MODULE_INT, | ||
367 | &rd_reg, TWL4030_INT_PWR_ISR1); | 417 | &rd_reg, TWL4030_INT_PWR_ISR1); |
368 | if (res) | 418 | if (res) |
369 | goto out; | 419 | goto out; |
420 | } | ||
370 | 421 | ||
371 | /* Notify RTC core on event */ | 422 | /* Notify RTC core on event */ |
372 | rtc_update_irq(rtc, 1, events); | 423 | rtc_update_irq(rtc, 1, events); |
@@ -376,18 +427,18 @@ out: | |||
376 | return ret; | 427 | return ret; |
377 | } | 428 | } |
378 | 429 | ||
379 | static struct rtc_class_ops twl4030_rtc_ops = { | 430 | static struct rtc_class_ops twl_rtc_ops = { |
380 | .read_time = twl4030_rtc_read_time, | 431 | .read_time = twl_rtc_read_time, |
381 | .set_time = twl4030_rtc_set_time, | 432 | .set_time = twl_rtc_set_time, |
382 | .read_alarm = twl4030_rtc_read_alarm, | 433 | .read_alarm = twl_rtc_read_alarm, |
383 | .set_alarm = twl4030_rtc_set_alarm, | 434 | .set_alarm = twl_rtc_set_alarm, |
384 | .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, | 435 | .alarm_irq_enable = twl_rtc_alarm_irq_enable, |
385 | .update_irq_enable = twl4030_rtc_update_irq_enable, | 436 | .update_irq_enable = twl_rtc_update_irq_enable, |
386 | }; | 437 | }; |
387 | 438 | ||
388 | /*----------------------------------------------------------------------*/ | 439 | /*----------------------------------------------------------------------*/ |
389 | 440 | ||
390 | static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | 441 | static int __devinit twl_rtc_probe(struct platform_device *pdev) |
391 | { | 442 | { |
392 | struct rtc_device *rtc; | 443 | struct rtc_device *rtc; |
393 | int ret = 0; | 444 | int ret = 0; |
@@ -398,7 +449,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
398 | return -EINVAL; | 449 | return -EINVAL; |
399 | 450 | ||
400 | rtc = rtc_device_register(pdev->name, | 451 | rtc = rtc_device_register(pdev->name, |
401 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); | 452 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); |
402 | if (IS_ERR(rtc)) { | 453 | if (IS_ERR(rtc)) { |
403 | ret = PTR_ERR(rtc); | 454 | ret = PTR_ERR(rtc); |
404 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 455 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
@@ -409,7 +460,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
409 | 460 | ||
410 | platform_set_drvdata(pdev, rtc); | 461 | platform_set_drvdata(pdev, rtc); |
411 | 462 | ||
412 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 463 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
413 | if (ret < 0) | 464 | if (ret < 0) |
414 | goto out1; | 465 | goto out1; |
415 | 466 | ||
@@ -420,11 +471,11 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
420 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); | 471 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); |
421 | 472 | ||
422 | /* Clear RTC Power up reset and pending alarm interrupts */ | 473 | /* Clear RTC Power up reset and pending alarm interrupts */ |
423 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); | 474 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); |
424 | if (ret < 0) | 475 | if (ret < 0) |
425 | goto out1; | 476 | goto out1; |
426 | 477 | ||
427 | ret = request_irq(irq, twl4030_rtc_interrupt, | 478 | ret = request_irq(irq, twl_rtc_interrupt, |
428 | IRQF_TRIGGER_RISING, | 479 | IRQF_TRIGGER_RISING, |
429 | dev_name(&rtc->dev), rtc); | 480 | dev_name(&rtc->dev), rtc); |
430 | if (ret < 0) { | 481 | if (ret < 0) { |
@@ -432,21 +483,28 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
432 | goto out1; | 483 | goto out1; |
433 | } | 484 | } |
434 | 485 | ||
486 | if (twl_class_is_6030()) { | ||
487 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
488 | REG_INT_MSK_LINE_A); | ||
489 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
490 | REG_INT_MSK_STS_A); | ||
491 | } | ||
492 | |||
435 | /* Check RTC module status, Enable if it is off */ | 493 | /* Check RTC module status, Enable if it is off */ |
436 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | 494 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); |
437 | if (ret < 0) | 495 | if (ret < 0) |
438 | goto out2; | 496 | goto out2; |
439 | 497 | ||
440 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | 498 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { |
441 | dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); | 499 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); |
442 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | 500 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; |
443 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | 501 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); |
444 | if (ret < 0) | 502 | if (ret < 0) |
445 | goto out2; | 503 | goto out2; |
446 | } | 504 | } |
447 | 505 | ||
448 | /* init cached IRQ enable bits */ | 506 | /* init cached IRQ enable bits */ |
449 | ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 507 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
450 | if (ret < 0) | 508 | if (ret < 0) |
451 | goto out2; | 509 | goto out2; |
452 | 510 | ||
@@ -461,10 +519,10 @@ out0: | |||
461 | } | 519 | } |
462 | 520 | ||
463 | /* | 521 | /* |
464 | * Disable all TWL4030 RTC module interrupts. | 522 | * Disable all TWL RTC module interrupts. |
465 | * Sets status flag to free. | 523 | * Sets status flag to free. |
466 | */ | 524 | */ |
467 | static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | 525 | static int __devexit twl_rtc_remove(struct platform_device *pdev) |
468 | { | 526 | { |
469 | /* leave rtc running, but disable irqs */ | 527 | /* leave rtc running, but disable irqs */ |
470 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 528 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
@@ -472,6 +530,13 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
472 | 530 | ||
473 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | 531 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); |
474 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | 532 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); |
533 | if (twl_class_is_6030()) { | ||
534 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
535 | REG_INT_MSK_LINE_A); | ||
536 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
537 | REG_INT_MSK_STS_A); | ||
538 | } | ||
539 | |||
475 | 540 | ||
476 | free_irq(irq, rtc); | 541 | free_irq(irq, rtc); |
477 | 542 | ||
@@ -480,7 +545,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
480 | return 0; | 545 | return 0; |
481 | } | 546 | } |
482 | 547 | ||
483 | static void twl4030_rtc_shutdown(struct platform_device *pdev) | 548 | static void twl_rtc_shutdown(struct platform_device *pdev) |
484 | { | 549 | { |
485 | /* mask timer interrupts, but leave alarm interrupts on to enable | 550 | /* mask timer interrupts, but leave alarm interrupts on to enable |
486 | power-on when alarm is triggered */ | 551 | power-on when alarm is triggered */ |
@@ -491,7 +556,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev) | |||
491 | 556 | ||
492 | static unsigned char irqstat; | 557 | static unsigned char irqstat; |
493 | 558 | ||
494 | static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 559 | static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
495 | { | 560 | { |
496 | irqstat = rtc_irq_bits; | 561 | irqstat = rtc_irq_bits; |
497 | 562 | ||
@@ -499,42 +564,47 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
499 | return 0; | 564 | return 0; |
500 | } | 565 | } |
501 | 566 | ||
502 | static int twl4030_rtc_resume(struct platform_device *pdev) | 567 | static int twl_rtc_resume(struct platform_device *pdev) |
503 | { | 568 | { |
504 | set_rtc_irq_bit(irqstat); | 569 | set_rtc_irq_bit(irqstat); |
505 | return 0; | 570 | return 0; |
506 | } | 571 | } |
507 | 572 | ||
508 | #else | 573 | #else |
509 | #define twl4030_rtc_suspend NULL | 574 | #define twl_rtc_suspend NULL |
510 | #define twl4030_rtc_resume NULL | 575 | #define twl_rtc_resume NULL |
511 | #endif | 576 | #endif |
512 | 577 | ||
513 | MODULE_ALIAS("platform:twl4030_rtc"); | 578 | MODULE_ALIAS("platform:twl_rtc"); |
514 | 579 | ||
515 | static struct platform_driver twl4030rtc_driver = { | 580 | static struct platform_driver twl4030rtc_driver = { |
516 | .probe = twl4030_rtc_probe, | 581 | .probe = twl_rtc_probe, |
517 | .remove = __devexit_p(twl4030_rtc_remove), | 582 | .remove = __devexit_p(twl_rtc_remove), |
518 | .shutdown = twl4030_rtc_shutdown, | 583 | .shutdown = twl_rtc_shutdown, |
519 | .suspend = twl4030_rtc_suspend, | 584 | .suspend = twl_rtc_suspend, |
520 | .resume = twl4030_rtc_resume, | 585 | .resume = twl_rtc_resume, |
521 | .driver = { | 586 | .driver = { |
522 | .owner = THIS_MODULE, | 587 | .owner = THIS_MODULE, |
523 | .name = "twl4030_rtc", | 588 | .name = "twl_rtc", |
524 | }, | 589 | }, |
525 | }; | 590 | }; |
526 | 591 | ||
527 | static int __init twl4030_rtc_init(void) | 592 | static int __init twl_rtc_init(void) |
528 | { | 593 | { |
594 | if (twl_class_is_4030()) | ||
595 | rtc_reg_map = (u8 *) twl4030_rtc_reg_map; | ||
596 | else | ||
597 | rtc_reg_map = (u8 *) twl6030_rtc_reg_map; | ||
598 | |||
529 | return platform_driver_register(&twl4030rtc_driver); | 599 | return platform_driver_register(&twl4030rtc_driver); |
530 | } | 600 | } |
531 | module_init(twl4030_rtc_init); | 601 | module_init(twl_rtc_init); |
532 | 602 | ||
533 | static void __exit twl4030_rtc_exit(void) | 603 | static void __exit twl_rtc_exit(void) |
534 | { | 604 | { |
535 | platform_driver_unregister(&twl4030rtc_driver); | 605 | platform_driver_unregister(&twl4030rtc_driver); |
536 | } | 606 | } |
537 | module_exit(twl4030_rtc_exit); | 607 | module_exit(twl_rtc_exit); |
538 | 608 | ||
539 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); | 609 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); |
540 | MODULE_LICENSE("GPL"); | 610 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 4a6ed1104fbb..20bfc64a15c8 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -12,11 +12,13 @@ | |||
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 { |
18 | struct rtc_device *rtc; | 19 | struct rtc_device *rtc; |
19 | struct tx4939_rtc_reg __iomem *rtcreg; | 20 | struct tx4939_rtc_reg __iomem *rtcreg; |
21 | spinlock_t lock; | ||
20 | }; | 22 | }; |
21 | 23 | ||
22 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) | 24 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) |
@@ -52,14 +54,14 @@ static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
52 | buf[3] = secs >> 8; | 54 | buf[3] = secs >> 8; |
53 | buf[4] = secs >> 16; | 55 | buf[4] = secs >> 16; |
54 | buf[5] = secs >> 24; | 56 | buf[5] = secs >> 24; |
55 | spin_lock_irq(&pdata->rtc->irq_lock); | 57 | spin_lock_irq(&pdata->lock); |
56 | __raw_writel(0, &rtcreg->adr); | 58 | __raw_writel(0, &rtcreg->adr); |
57 | for (i = 0; i < 6; i++) | 59 | for (i = 0; i < 6; i++) |
58 | __raw_writel(buf[i], &rtcreg->dat); | 60 | __raw_writel(buf[i], &rtcreg->dat); |
59 | ret = tx4939_rtc_cmd(rtcreg, | 61 | ret = tx4939_rtc_cmd(rtcreg, |
60 | TX4939_RTCCTL_COMMAND_SETTIME | | 62 | TX4939_RTCCTL_COMMAND_SETTIME | |
61 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 63 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
62 | spin_unlock_irq(&pdata->rtc->irq_lock); | 64 | spin_unlock_irq(&pdata->lock); |
63 | return ret; | 65 | return ret; |
64 | } | 66 | } |
65 | 67 | ||
@@ -71,18 +73,18 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
71 | unsigned long sec; | 73 | unsigned long sec; |
72 | unsigned char buf[6]; | 74 | unsigned char buf[6]; |
73 | 75 | ||
74 | spin_lock_irq(&pdata->rtc->irq_lock); | 76 | spin_lock_irq(&pdata->lock); |
75 | ret = tx4939_rtc_cmd(rtcreg, | 77 | ret = tx4939_rtc_cmd(rtcreg, |
76 | TX4939_RTCCTL_COMMAND_GETTIME | | 78 | TX4939_RTCCTL_COMMAND_GETTIME | |
77 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 79 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
78 | if (ret) { | 80 | if (ret) { |
79 | spin_unlock_irq(&pdata->rtc->irq_lock); | 81 | spin_unlock_irq(&pdata->lock); |
80 | return ret; | 82 | return ret; |
81 | } | 83 | } |
82 | __raw_writel(2, &rtcreg->adr); | 84 | __raw_writel(2, &rtcreg->adr); |
83 | for (i = 2; i < 6; i++) | 85 | for (i = 2; i < 6; i++) |
84 | buf[i] = __raw_readl(&rtcreg->dat); | 86 | buf[i] = __raw_readl(&rtcreg->dat); |
85 | spin_unlock_irq(&pdata->rtc->irq_lock); | 87 | spin_unlock_irq(&pdata->lock); |
86 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 88 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
87 | rtc_time_to_tm(sec, tm); | 89 | rtc_time_to_tm(sec, tm); |
88 | return rtc_valid_tm(tm); | 90 | return rtc_valid_tm(tm); |
@@ -110,13 +112,13 @@ static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
110 | buf[3] = sec >> 8; | 112 | buf[3] = sec >> 8; |
111 | buf[4] = sec >> 16; | 113 | buf[4] = sec >> 16; |
112 | buf[5] = sec >> 24; | 114 | buf[5] = sec >> 24; |
113 | spin_lock_irq(&pdata->rtc->irq_lock); | 115 | spin_lock_irq(&pdata->lock); |
114 | __raw_writel(0, &rtcreg->adr); | 116 | __raw_writel(0, &rtcreg->adr); |
115 | for (i = 0; i < 6; i++) | 117 | for (i = 0; i < 6; i++) |
116 | __raw_writel(buf[i], &rtcreg->dat); | 118 | __raw_writel(buf[i], &rtcreg->dat); |
117 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | | 119 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | |
118 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); | 120 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); |
119 | spin_unlock_irq(&pdata->rtc->irq_lock); | 121 | spin_unlock_irq(&pdata->lock); |
120 | return ret; | 122 | return ret; |
121 | } | 123 | } |
122 | 124 | ||
@@ -129,12 +131,12 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
129 | unsigned char buf[6]; | 131 | unsigned char buf[6]; |
130 | u32 ctl; | 132 | u32 ctl; |
131 | 133 | ||
132 | spin_lock_irq(&pdata->rtc->irq_lock); | 134 | spin_lock_irq(&pdata->lock); |
133 | ret = tx4939_rtc_cmd(rtcreg, | 135 | ret = tx4939_rtc_cmd(rtcreg, |
134 | TX4939_RTCCTL_COMMAND_GETALARM | | 136 | TX4939_RTCCTL_COMMAND_GETALARM | |
135 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 137 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
136 | if (ret) { | 138 | if (ret) { |
137 | spin_unlock_irq(&pdata->rtc->irq_lock); | 139 | spin_unlock_irq(&pdata->lock); |
138 | return ret; | 140 | return ret; |
139 | } | 141 | } |
140 | __raw_writel(2, &rtcreg->adr); | 142 | __raw_writel(2, &rtcreg->adr); |
@@ -143,7 +145,7 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
143 | ctl = __raw_readl(&rtcreg->ctl); | 145 | ctl = __raw_readl(&rtcreg->ctl); |
144 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; | 146 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; |
145 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; | 147 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; |
146 | spin_unlock_irq(&pdata->rtc->irq_lock); | 148 | spin_unlock_irq(&pdata->lock); |
147 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 149 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
148 | rtc_time_to_tm(sec, &alrm->time); | 150 | rtc_time_to_tm(sec, &alrm->time); |
149 | return rtc_valid_tm(&alrm->time); | 151 | return rtc_valid_tm(&alrm->time); |
@@ -153,11 +155,11 @@ static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
153 | { | 155 | { |
154 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); | 156 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); |
155 | 157 | ||
156 | spin_lock_irq(&pdata->rtc->irq_lock); | 158 | spin_lock_irq(&pdata->lock); |
157 | tx4939_rtc_cmd(pdata->rtcreg, | 159 | tx4939_rtc_cmd(pdata->rtcreg, |
158 | TX4939_RTCCTL_COMMAND_NOP | | 160 | TX4939_RTCCTL_COMMAND_NOP | |
159 | (enabled ? TX4939_RTCCTL_ALME : 0)); | 161 | (enabled ? TX4939_RTCCTL_ALME : 0)); |
160 | spin_unlock_irq(&pdata->rtc->irq_lock); | 162 | spin_unlock_irq(&pdata->lock); |
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
@@ -167,13 +169,14 @@ static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id) | |||
167 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 169 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
168 | unsigned long events = RTC_IRQF; | 170 | unsigned long events = RTC_IRQF; |
169 | 171 | ||
170 | spin_lock(&pdata->rtc->irq_lock); | 172 | spin_lock(&pdata->lock); |
171 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { | 173 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { |
172 | events |= RTC_AF; | 174 | events |= RTC_AF; |
173 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 175 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
174 | } | 176 | } |
175 | spin_unlock(&pdata->rtc->irq_lock); | 177 | spin_unlock(&pdata->lock); |
176 | rtc_update_irq(pdata->rtc, 1, events); | 178 | if (likely(pdata->rtc)) |
179 | rtc_update_irq(pdata->rtc, 1, events); | ||
177 | return IRQ_HANDLED; | 180 | return IRQ_HANDLED; |
178 | } | 181 | } |
179 | 182 | ||
@@ -194,13 +197,13 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
194 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 197 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
195 | ssize_t count; | 198 | ssize_t count; |
196 | 199 | ||
197 | spin_lock_irq(&pdata->rtc->irq_lock); | 200 | spin_lock_irq(&pdata->lock); |
198 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 201 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
199 | count++, size--) { | 202 | count++, size--) { |
200 | __raw_writel(pos++, &rtcreg->adr); | 203 | __raw_writel(pos++, &rtcreg->adr); |
201 | *buf++ = __raw_readl(&rtcreg->dat); | 204 | *buf++ = __raw_readl(&rtcreg->dat); |
202 | } | 205 | } |
203 | spin_unlock_irq(&pdata->rtc->irq_lock); | 206 | spin_unlock_irq(&pdata->lock); |
204 | return count; | 207 | return count; |
205 | } | 208 | } |
206 | 209 | ||
@@ -213,13 +216,13 @@ static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | |||
213 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 216 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
214 | ssize_t count; | 217 | ssize_t count; |
215 | 218 | ||
216 | spin_lock_irq(&pdata->rtc->irq_lock); | 219 | spin_lock_irq(&pdata->lock); |
217 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 220 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
218 | count++, size--) { | 221 | count++, size--) { |
219 | __raw_writel(pos++, &rtcreg->adr); | 222 | __raw_writel(pos++, &rtcreg->adr); |
220 | __raw_writel(*buf++, &rtcreg->dat); | 223 | __raw_writel(*buf++, &rtcreg->dat); |
221 | } | 224 | } |
222 | spin_unlock_irq(&pdata->rtc->irq_lock); | 225 | spin_unlock_irq(&pdata->lock); |
223 | return count; | 226 | return count; |
224 | } | 227 | } |
225 | 228 | ||
@@ -259,6 +262,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
259 | if (!pdata->rtcreg) | 262 | if (!pdata->rtcreg) |
260 | return -EBUSY; | 263 | return -EBUSY; |
261 | 264 | ||
265 | spin_lock_init(&pdata->lock); | ||
262 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 266 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
263 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, | 267 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, |
264 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) | 268 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) |
@@ -277,14 +281,12 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
277 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) | 281 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) |
278 | { | 282 | { |
279 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); | 283 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); |
280 | struct rtc_device *rtc = pdata->rtc; | ||
281 | 284 | ||
282 | spin_lock_irq(&rtc->irq_lock); | ||
283 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
284 | spin_unlock_irq(&rtc->irq_lock); | ||
285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); | 285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); |
286 | rtc_device_unregister(rtc); | 286 | rtc_device_unregister(pdata->rtc); |
287 | platform_set_drvdata(pdev, NULL); | 287 | spin_lock_irq(&pdata->lock); |
288 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
289 | spin_unlock_irq(&pdata->lock); | ||
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
290 | 292 | ||
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 423cd5a30b10..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 | ||
@@ -304,7 +305,6 @@ static int rtc_probe(struct platform_device *pdev) | |||
304 | { | 305 | { |
305 | struct v3020_platform_data *pdata = pdev->dev.platform_data; | 306 | struct v3020_platform_data *pdata = pdev->dev.platform_data; |
306 | struct v3020 *chip; | 307 | struct v3020 *chip; |
307 | struct rtc_device *rtc; | ||
308 | int retval = -EBUSY; | 308 | int retval = -EBUSY; |
309 | int i; | 309 | int i; |
310 | int temp; | 310 | int temp; |
@@ -335,7 +335,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
335 | goto err_io; | 335 | goto err_io; |
336 | } | 336 | } |
337 | 337 | ||
338 | /* Make sure frequency measurment mode, test modes, and lock | 338 | /* Make sure frequency measurement mode, test modes, and lock |
339 | * are all disabled */ | 339 | * are all disabled */ |
340 | v3020_set_reg(chip, V3020_STATUS_0, 0x0); | 340 | v3020_set_reg(chip, V3020_STATUS_0, 0x0); |
341 | 341 | ||
@@ -353,13 +353,12 @@ static int rtc_probe(struct platform_device *pdev) | |||
353 | 353 | ||
354 | platform_set_drvdata(pdev, chip); | 354 | platform_set_drvdata(pdev, chip); |
355 | 355 | ||
356 | rtc = rtc_device_register("v3020", | 356 | chip->rtc = rtc_device_register("v3020", |
357 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); | 357 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); |
358 | if (IS_ERR(rtc)) { | 358 | if (IS_ERR(chip->rtc)) { |
359 | retval = PTR_ERR(rtc); | 359 | retval = PTR_ERR(chip->rtc); |
360 | goto err_io; | 360 | goto err_io; |
361 | } | 361 | } |
362 | chip->rtc = rtc; | ||
363 | 362 | ||
364 | return 0; | 363 | return 0; |
365 | 364 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index fadddac1e5a4..c3244244e8cf 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -327,7 +327,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
327 | if (!res) | 327 | if (!res) |
328 | return -EBUSY; | 328 | return -EBUSY; |
329 | 329 | ||
330 | rtc1_base = ioremap(res->start, res->end - res->start + 1); | 330 | rtc1_base = ioremap(res->start, resource_size(res)); |
331 | if (!rtc1_base) | 331 | if (!rtc1_base) |
332 | return -EBUSY; | 332 | return -EBUSY; |
333 | 333 | ||
@@ -337,7 +337,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
337 | goto err_rtc1_iounmap; | 337 | goto err_rtc1_iounmap; |
338 | } | 338 | } |
339 | 339 | ||
340 | rtc2_base = ioremap(res->start, res->end - res->start + 1); | 340 | rtc2_base = ioremap(res->start, resource_size(res)); |
341 | if (!rtc2_base) { | 341 | if (!rtc2_base) { |
342 | retval = -EBUSY; | 342 | retval = -EBUSY; |
343 | goto err_rtc1_iounmap; | 343 | goto err_rtc1_iounmap; |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 79795cdf6ed8..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> |
@@ -485,7 +486,7 @@ static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | |||
485 | return 0; | 486 | return 0; |
486 | } | 487 | } |
487 | 488 | ||
488 | static struct dev_pm_ops wm831x_rtc_pm_ops = { | 489 | static const struct dev_pm_ops wm831x_rtc_pm_ops = { |
489 | .suspend = wm831x_rtc_suspend, | 490 | .suspend = wm831x_rtc_suspend, |
490 | .resume = wm831x_rtc_resume, | 491 | .resume = wm831x_rtc_resume, |
491 | 492 | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c91edc572eb6..3d0dc76b38af 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -307,17 +307,24 @@ 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 | ||
318 | static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | 325 | static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data) |
319 | void *data) | ||
320 | { | 326 | { |
327 | struct wm8350 *wm8350 = data; | ||
321 | struct rtc_device *rtc = wm8350->rtc.rtc; | 328 | struct rtc_device *rtc = wm8350->rtc.rtc; |
322 | int ret; | 329 | int ret; |
323 | 330 | ||
@@ -330,14 +337,18 @@ static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | |||
330 | dev_err(&(wm8350->rtc.pdev->dev), | 337 | dev_err(&(wm8350->rtc.pdev->dev), |
331 | "Failed to disable alarm: %d\n", ret); | 338 | "Failed to disable alarm: %d\n", ret); |
332 | } | 339 | } |
340 | |||
341 | return IRQ_HANDLED; | ||
333 | } | 342 | } |
334 | 343 | ||
335 | static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | 344 | static irqreturn_t wm8350_rtc_update_handler(int irq, void *data) |
336 | void *data) | ||
337 | { | 345 | { |
346 | struct wm8350 *wm8350 = data; | ||
338 | struct rtc_device *rtc = wm8350->rtc.rtc; | 347 | struct rtc_device *rtc = wm8350->rtc.rtc; |
339 | 348 | ||
340 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); | 349 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); |
350 | |||
351 | return IRQ_HANDLED; | ||
341 | } | 352 | } |
342 | 353 | ||
343 | static const struct rtc_class_ops wm8350_rtc_ops = { | 354 | static const struct rtc_class_ops wm8350_rtc_ops = { |
@@ -350,8 +361,9 @@ static const struct rtc_class_ops wm8350_rtc_ops = { | |||
350 | }; | 361 | }; |
351 | 362 | ||
352 | #ifdef CONFIG_PM | 363 | #ifdef CONFIG_PM |
353 | static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 364 | static int wm8350_rtc_suspend(struct device *dev) |
354 | { | 365 | { |
366 | struct platform_device *pdev = to_platform_device(dev); | ||
355 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 367 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
356 | int ret = 0; | 368 | int ret = 0; |
357 | u16 reg; | 369 | u16 reg; |
@@ -369,8 +381,9 @@ static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
369 | return ret; | 381 | return ret; |
370 | } | 382 | } |
371 | 383 | ||
372 | static int wm8350_rtc_resume(struct platform_device *pdev) | 384 | static int wm8350_rtc_resume(struct device *dev) |
373 | { | 385 | { |
386 | struct platform_device *pdev = to_platform_device(dev); | ||
374 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 387 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
375 | int ret; | 388 | int ret; |
376 | 389 | ||
@@ -455,15 +468,14 @@ static int wm8350_rtc_probe(struct platform_device *pdev) | |||
455 | return ret; | 468 | return ret; |
456 | } | 469 | } |
457 | 470 | ||
458 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
459 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); | ||
460 | |||
461 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, | 471 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, |
462 | wm8350_rtc_update_handler, NULL); | 472 | wm8350_rtc_update_handler, 0, |
473 | "RTC Seconds", wm8350); | ||
474 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
463 | 475 | ||
464 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, | 476 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, |
465 | wm8350_rtc_alarm_handler, NULL); | 477 | wm8350_rtc_alarm_handler, 0, |
466 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); | 478 | "RTC Alarm", wm8350); |
467 | 479 | ||
468 | return 0; | 480 | return 0; |
469 | } | 481 | } |
@@ -473,23 +485,25 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
473 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 485 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
474 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | 486 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; |
475 | 487 | ||
476 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 488 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); |
477 | 489 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); | |
478 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
479 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
480 | 490 | ||
481 | rtc_device_unregister(wm_rtc->rtc); | 491 | rtc_device_unregister(wm_rtc->rtc); |
482 | 492 | ||
483 | return 0; | 493 | return 0; |
484 | } | 494 | } |
485 | 495 | ||
496 | static struct dev_pm_ops wm8350_rtc_pm_ops = { | ||
497 | .suspend = wm8350_rtc_suspend, | ||
498 | .resume = wm8350_rtc_resume, | ||
499 | }; | ||
500 | |||
486 | static struct platform_driver wm8350_rtc_driver = { | 501 | static struct platform_driver wm8350_rtc_driver = { |
487 | .probe = wm8350_rtc_probe, | 502 | .probe = wm8350_rtc_probe, |
488 | .remove = __devexit_p(wm8350_rtc_remove), | 503 | .remove = __devexit_p(wm8350_rtc_remove), |
489 | .suspend = wm8350_rtc_suspend, | ||
490 | .resume = wm8350_rtc_resume, | ||
491 | .driver = { | 504 | .driver = { |
492 | .name = "wm8350-rtc", | 505 | .name = "wm8350-rtc", |
506 | .pm = &wm8350_rtc_pm_ops, | ||
493 | }, | 507 | }, |
494 | }; | 508 | }; |
495 | 509 | ||
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 6583c1a8b070..9aae49139a0a 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -155,11 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | 157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, |
158 | int datetoo, u8 reg_base, unsigned char alm_enable) | 158 | u8 reg_base, unsigned char alm_enable) |
159 | { | 159 | { |
160 | int i, xfer, nbytes; | 160 | int i, xfer; |
161 | unsigned char buf[8]; | ||
162 | unsigned char rdata[10] = { 0, reg_base }; | 161 | unsigned char rdata[10] = { 0, reg_base }; |
162 | unsigned char *buf = rdata + 2; | ||
163 | 163 | ||
164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, | 164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, |
165 | X1205_SR_WEL }; | 165 | X1205_SR_WEL }; |
@@ -170,9 +170,9 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; | 170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; |
171 | 171 | ||
172 | dev_dbg(&client->dev, | 172 | dev_dbg(&client->dev, |
173 | "%s: secs=%d, mins=%d, hours=%d\n", | 173 | "%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n", |
174 | __func__, | 174 | __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, |
175 | tm->tm_sec, tm->tm_min, tm->tm_hour); | 175 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
176 | 176 | ||
177 | buf[CCR_SEC] = bin2bcd(tm->tm_sec); | 177 | buf[CCR_SEC] = bin2bcd(tm->tm_sec); |
178 | buf[CCR_MIN] = bin2bcd(tm->tm_min); | 178 | buf[CCR_MIN] = bin2bcd(tm->tm_min); |
@@ -180,23 +180,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
180 | /* set hour and 24hr bit */ | 180 | /* set hour and 24hr bit */ |
181 | buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL; | 181 | buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL; |
182 | 182 | ||
183 | /* should we also set the date? */ | 183 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); |
184 | if (datetoo) { | ||
185 | dev_dbg(&client->dev, | ||
186 | "%s: mday=%d, mon=%d, year=%d, wday=%d\n", | ||
187 | __func__, | ||
188 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
189 | 184 | ||
190 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); | 185 | /* month, 1 - 12 */ |
186 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | ||
191 | 187 | ||
192 | /* month, 1 - 12 */ | 188 | /* year, since the rtc epoch*/ |
193 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | 189 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); |
194 | 190 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | |
195 | /* year, since the rtc epoch*/ | 191 | buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100); |
196 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); | ||
197 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | ||
198 | buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100); | ||
199 | } | ||
200 | 192 | ||
201 | /* If writing alarm registers, set compare bits on registers 0-4 */ | 193 | /* If writing alarm registers, set compare bits on registers 0-4 */ |
202 | if (reg_base < X1205_CCR_BASE) | 194 | if (reg_base < X1205_CCR_BASE) |
@@ -214,17 +206,8 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
214 | return -EIO; | 206 | return -EIO; |
215 | } | 207 | } |
216 | 208 | ||
217 | 209 | xfer = i2c_master_send(client, rdata, sizeof(rdata)); | |
218 | /* write register's data */ | 210 | if (xfer != sizeof(rdata)) { |
219 | if (datetoo) | ||
220 | nbytes = 8; | ||
221 | else | ||
222 | nbytes = 3; | ||
223 | for (i = 0; i < nbytes; i++) | ||
224 | rdata[2+i] = buf[i]; | ||
225 | |||
226 | xfer = i2c_master_send(client, rdata, nbytes+2); | ||
227 | if (xfer != nbytes+2) { | ||
228 | dev_err(&client->dev, | 211 | dev_err(&client->dev, |
229 | "%s: result=%d addr=%02x, data=%02x\n", | 212 | "%s: result=%d addr=%02x, data=%02x\n", |
230 | __func__, | 213 | __func__, |
@@ -282,7 +265,7 @@ static int x1205_fix_osc(struct i2c_client *client) | |||
282 | 265 | ||
283 | memset(&tm, 0, sizeof(tm)); | 266 | memset(&tm, 0, sizeof(tm)); |
284 | 267 | ||
285 | err = x1205_set_datetime(client, &tm, 1, X1205_CCR_BASE, 0); | 268 | err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0); |
286 | if (err < 0) | 269 | if (err < 0) |
287 | dev_err(&client->dev, "unable to restart the oscillator\n"); | 270 | dev_err(&client->dev, "unable to restart the oscillator\n"); |
288 | 271 | ||
@@ -481,7 +464,7 @@ static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
481 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 464 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
482 | { | 465 | { |
483 | return x1205_set_datetime(to_i2c_client(dev), | 466 | return x1205_set_datetime(to_i2c_client(dev), |
484 | &alrm->time, 1, X1205_ALM0_BASE, alrm->enabled); | 467 | &alrm->time, X1205_ALM0_BASE, alrm->enabled); |
485 | } | 468 | } |
486 | 469 | ||
487 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | 470 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -493,7 +476,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
493 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) | 476 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) |
494 | { | 477 | { |
495 | return x1205_set_datetime(to_i2c_client(dev), | 478 | return x1205_set_datetime(to_i2c_client(dev), |
496 | tm, 1, X1205_CCR_BASE, 0); | 479 | tm, X1205_CCR_BASE, 0); |
497 | } | 480 | } |
498 | 481 | ||
499 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) | 482 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) |