diff options
Diffstat (limited to 'drivers/rtc')
37 files changed, 3269 insertions, 353 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6a1303759432..48ca7132cc05 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -166,6 +166,16 @@ config RTC_DRV_DS1672 | |||
166 | This driver can also be built as a module. If so, the module | 166 | This driver can also be built as a module. If so, the module |
167 | will be called rtc-ds1672. | 167 | will be called rtc-ds1672. |
168 | 168 | ||
169 | config RTC_DRV_DS3232 | ||
170 | tristate "Dallas/Maxim DS3232" | ||
171 | depends on RTC_CLASS && I2C | ||
172 | help | ||
173 | If you say yes here you get support for Dallas Semiconductor | ||
174 | DS3232 real-time clock chips. | ||
175 | |||
176 | This driver can also be built as a module. If so, the module | ||
177 | will be called rtc-ds3232. | ||
178 | |||
169 | config RTC_DRV_MAX6900 | 179 | config RTC_DRV_MAX6900 |
170 | tristate "Maxim MAX6900" | 180 | tristate "Maxim MAX6900" |
171 | help | 181 | help |
@@ -203,6 +213,15 @@ config RTC_DRV_ISL1208 | |||
203 | This driver can also be built as a module. If so, the module | 213 | This driver can also be built as a module. If so, the module |
204 | will be called rtc-isl1208. | 214 | will be called rtc-isl1208. |
205 | 215 | ||
216 | config RTC_DRV_ISL12022 | ||
217 | tristate "Intersil ISL12022" | ||
218 | help | ||
219 | If you say yes here you get support for the | ||
220 | Intersil ISL12022 RTC chip. | ||
221 | |||
222 | This driver can also be built as a module. If so, the module | ||
223 | will be called rtc-isl12022. | ||
224 | |||
206 | config RTC_DRV_X1205 | 225 | config RTC_DRV_X1205 |
207 | tristate "Xicor/Intersil X1205" | 226 | tristate "Xicor/Intersil X1205" |
208 | help | 227 | help |
@@ -537,6 +556,16 @@ config RTC_DRV_MSM6242 | |||
537 | This driver can also be built as a module. If so, the module | 556 | This driver can also be built as a module. If so, the module |
538 | will be called rtc-msm6242. | 557 | will be called rtc-msm6242. |
539 | 558 | ||
559 | config RTC_DRV_IMXDI | ||
560 | tristate "Freescale IMX DryIce Real Time Clock" | ||
561 | depends on ARCH_MX25 | ||
562 | depends on RTC_CLASS | ||
563 | help | ||
564 | Support for Freescale IMX DryIce RTC | ||
565 | |||
566 | This driver can also be built as a module, if so, the module | ||
567 | will be called "rtc-imxdi". | ||
568 | |||
540 | config RTC_MXC | 569 | config RTC_MXC |
541 | tristate "Freescale MXC Real Time Clock" | 570 | tristate "Freescale MXC Real Time Clock" |
542 | depends on ARCH_MXC | 571 | depends on ARCH_MXC |
@@ -611,6 +640,13 @@ config RTC_DRV_AB3100 | |||
611 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | 640 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC |
612 | support. This chip contains a battery- and capacitor-backed RTC. | 641 | support. This chip contains a battery- and capacitor-backed RTC. |
613 | 642 | ||
643 | config RTC_DRV_AB8500 | ||
644 | tristate "ST-Ericsson AB8500 RTC" | ||
645 | depends on AB8500_CORE | ||
646 | help | ||
647 | Select this to enable the ST-Ericsson AB8500 power management IC RTC | ||
648 | support. This chip contains a battery- and capacitor-backed RTC. | ||
649 | |||
614 | config RTC_DRV_NUC900 | 650 | config RTC_DRV_NUC900 |
615 | tristate "NUC910/NUC920 RTC driver" | 651 | tristate "NUC910/NUC920 RTC driver" |
616 | depends on RTC_CLASS && ARCH_W90X900 | 652 | depends on RTC_CLASS && ARCH_W90X900 |
@@ -620,6 +656,16 @@ config RTC_DRV_NUC900 | |||
620 | 656 | ||
621 | comment "on-CPU RTC drivers" | 657 | comment "on-CPU RTC drivers" |
622 | 658 | ||
659 | config RTC_DRV_DAVINCI | ||
660 | tristate "TI DaVinci RTC" | ||
661 | depends on ARCH_DAVINCI_DM365 | ||
662 | help | ||
663 | If you say yes here you get support for the RTC on the | ||
664 | DaVinci platforms (DM365). | ||
665 | |||
666 | This driver can also be built as a module. If so, the module | ||
667 | will be called rtc-davinci. | ||
668 | |||
623 | config RTC_DRV_OMAP | 669 | config RTC_DRV_OMAP |
624 | tristate "TI OMAP1" | 670 | tristate "TI OMAP1" |
625 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX | 671 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX |
@@ -628,9 +674,16 @@ config RTC_DRV_OMAP | |||
628 | DA8xx/OMAP-L13x chips. This driver can also be built as a | 674 | DA8xx/OMAP-L13x chips. This driver can also be built as a |
629 | module called rtc-omap. | 675 | module called rtc-omap. |
630 | 676 | ||
677 | config HAVE_S3C_RTC | ||
678 | bool | ||
679 | help | ||
680 | This will include RTC support for Samsung SoCs. If | ||
681 | you want to include RTC support for any machine, kindly | ||
682 | select this in the respective mach-XXXX/Kconfig file. | ||
683 | |||
631 | config RTC_DRV_S3C | 684 | config RTC_DRV_S3C |
632 | tristate "Samsung S3C series SoC RTC" | 685 | tristate "Samsung S3C series SoC RTC" |
633 | depends on ARCH_S3C2410 | 686 | depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC |
634 | help | 687 | help |
635 | RTC (Realtime Clock) driver for the clock inbuilt into the | 688 | RTC (Realtime Clock) driver for the clock inbuilt into the |
636 | Samsung S3C24XX series of SoCs. This can provide periodic | 689 | Samsung S3C24XX series of SoCs. This can provide periodic |
@@ -757,7 +810,7 @@ config RTC_DRV_AT91SAM9_GPBR | |||
757 | 810 | ||
758 | config RTC_DRV_AU1XXX | 811 | config RTC_DRV_AU1XXX |
759 | tristate "Au1xxx Counter0 RTC support" | 812 | tristate "Au1xxx Counter0 RTC support" |
760 | depends on SOC_AU1X00 | 813 | depends on MIPS_ALCHEMY |
761 | help | 814 | help |
762 | This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year | 815 | This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year |
763 | counter) to be used as a RTC. | 816 | counter) to be used as a RTC. |
@@ -888,4 +941,15 @@ config RTC_DRV_MPC5121 | |||
888 | This driver can also be built as a module. If so, the module | 941 | This driver can also be built as a module. If so, the module |
889 | will be called rtc-mpc5121. | 942 | will be called rtc-mpc5121. |
890 | 943 | ||
944 | config RTC_DRV_JZ4740 | ||
945 | tristate "Ingenic JZ4740 SoC" | ||
946 | depends on RTC_CLASS | ||
947 | depends on MACH_JZ4740 | ||
948 | help | ||
949 | If you say yes here you get support for the Ingenic JZ4740 SoC RTC | ||
950 | controller. | ||
951 | |||
952 | This driver can also be buillt as a module. If so, the module | ||
953 | will be called rtc-jz4740. | ||
954 | |||
891 | endif # RTC_CLASS | 955 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 44ef194a9573..0f207b3b5833 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -18,6 +18,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
18 | # Keep the list ordered. | 18 | # Keep the list ordered. |
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | 20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o |
21 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | ||
21 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 22 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
22 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 23 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 24 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
@@ -27,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o | |||
27 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | 28 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o |
28 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 29 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
29 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
31 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | ||
30 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 32 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
31 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 33 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
32 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | 34 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o |
@@ -39,12 +41,16 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
39 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 41 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
40 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 42 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
41 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 43 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
44 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o | ||
42 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 45 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
43 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 46 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
44 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 47 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
45 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 48 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
46 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | 49 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o |
50 | obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | ||
47 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 51 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
52 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | ||
53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | ||
48 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 54 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
49 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 55 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
50 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 56 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index 4704aac2b5af..d26780ea254b 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
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/mfd/ab3100.h> | 12 | #include <linux/mfd/abx500.h> |
13 | 13 | ||
14 | /* Clock rate in Hz */ | 14 | /* Clock rate in Hz */ |
15 | #define AB3100_RTC_CLOCK_RATE 32768 | 15 | #define AB3100_RTC_CLOCK_RATE 32768 |
@@ -45,7 +45,6 @@ | |||
45 | */ | 45 | */ |
46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | 46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) |
47 | { | 47 | { |
48 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
49 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, | 48 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, |
50 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; | 49 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; |
51 | unsigned char buf[6]; | 50 | unsigned char buf[6]; |
@@ -61,27 +60,26 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
61 | buf[5] = (fat_time >> 40) & 0xFF; | 60 | buf[5] = (fat_time >> 40) & 0xFF; |
62 | 61 | ||
63 | for (i = 0; i < 6; i++) { | 62 | for (i = 0; i < 6; i++) { |
64 | err = ab3100_set_register_interruptible(ab3100_data, | 63 | err = abx500_set_register_interruptible(dev, 0, |
65 | regs[i], buf[i]); | 64 | regs[i], buf[i]); |
66 | if (err) | 65 | if (err) |
67 | return err; | 66 | return err; |
68 | } | 67 | } |
69 | 68 | ||
70 | /* Set the flag to mark that the clock is now set */ | 69 | /* Set the flag to mark that the clock is now set */ |
71 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 70 | return abx500_mask_and_set_register_interruptible(dev, 0, |
72 | AB3100_RTC, | 71 | AB3100_RTC, |
73 | 0xFE, 0x01); | 72 | 0x01, 0x01); |
74 | 73 | ||
75 | } | 74 | } |
76 | 75 | ||
77 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 76 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
78 | { | 77 | { |
79 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
80 | unsigned long time; | 78 | unsigned long time; |
81 | u8 rtcval; | 79 | u8 rtcval; |
82 | int err; | 80 | int err; |
83 | 81 | ||
84 | err = ab3100_get_register_interruptible(ab3100_data, | 82 | err = abx500_get_register_interruptible(dev, 0, |
85 | AB3100_RTC, &rtcval); | 83 | AB3100_RTC, &rtcval); |
86 | if (err) | 84 | if (err) |
87 | return err; | 85 | return err; |
@@ -94,7 +92,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
94 | u8 buf[6]; | 92 | u8 buf[6]; |
95 | 93 | ||
96 | /* Read out time registers */ | 94 | /* Read out time registers */ |
97 | err = ab3100_get_register_page_interruptible(ab3100_data, | 95 | err = abx500_get_register_page_interruptible(dev, 0, |
98 | AB3100_TI0, | 96 | AB3100_TI0, |
99 | buf, 6); | 97 | buf, 6); |
100 | if (err != 0) | 98 | if (err != 0) |
@@ -114,7 +112,6 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
114 | 112 | ||
115 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 113 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
116 | { | 114 | { |
117 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
118 | unsigned long time; | 115 | unsigned long time; |
119 | u64 fat_time; | 116 | u64 fat_time; |
120 | u8 buf[6]; | 117 | u8 buf[6]; |
@@ -122,7 +119,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
122 | int err; | 119 | int err; |
123 | 120 | ||
124 | /* Figure out if alarm is enabled or not */ | 121 | /* Figure out if alarm is enabled or not */ |
125 | err = ab3100_get_register_interruptible(ab3100_data, | 122 | err = abx500_get_register_interruptible(dev, 0, |
126 | AB3100_RTC, &rtcval); | 123 | AB3100_RTC, &rtcval); |
127 | if (err) | 124 | if (err) |
128 | return err; | 125 | return err; |
@@ -133,7 +130,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
133 | /* No idea how this could be represented */ | 130 | /* No idea how this could be represented */ |
134 | alarm->pending = 0; | 131 | alarm->pending = 0; |
135 | /* Read out alarm registers, only 4 bytes */ | 132 | /* Read out alarm registers, only 4 bytes */ |
136 | err = ab3100_get_register_page_interruptible(ab3100_data, | 133 | err = abx500_get_register_page_interruptible(dev, 0, |
137 | AB3100_AL0, buf, 4); | 134 | AB3100_AL0, buf, 4); |
138 | if (err) | 135 | if (err) |
139 | return err; | 136 | return err; |
@@ -148,7 +145,6 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
148 | 145 | ||
149 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 146 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
150 | { | 147 | { |
151 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
152 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; | 148 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; |
153 | unsigned char buf[4]; | 149 | unsigned char buf[4]; |
154 | unsigned long secs; | 150 | unsigned long secs; |
@@ -165,21 +161,19 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
165 | 161 | ||
166 | /* Set the alarm */ | 162 | /* Set the alarm */ |
167 | for (i = 0; i < 4; i++) { | 163 | for (i = 0; i < 4; i++) { |
168 | err = ab3100_set_register_interruptible(ab3100_data, | 164 | err = abx500_set_register_interruptible(dev, 0, |
169 | regs[i], buf[i]); | 165 | regs[i], buf[i]); |
170 | if (err) | 166 | if (err) |
171 | return err; | 167 | return err; |
172 | } | 168 | } |
173 | /* Then enable the alarm */ | 169 | /* Then enable the alarm */ |
174 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 170 | return abx500_mask_and_set_register_interruptible(dev, 0, |
175 | AB3100_RTC, ~(1 << 2), | 171 | AB3100_RTC, (1 << 2), |
176 | alarm->enabled << 2); | 172 | alarm->enabled << 2); |
177 | } | 173 | } |
178 | 174 | ||
179 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | 175 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) |
180 | { | 176 | { |
181 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
182 | |||
183 | /* | 177 | /* |
184 | * It's not possible to enable/disable the alarm IRQ for this RTC. | 178 | * It's not possible to enable/disable the alarm IRQ for this RTC. |
185 | * It does not actually trigger any IRQ: instead its only function is | 179 | * It does not actually trigger any IRQ: instead its only function is |
@@ -188,12 +182,12 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | |||
188 | * and need to be handled there instead. | 182 | * and need to be handled there instead. |
189 | */ | 183 | */ |
190 | if (enabled) | 184 | if (enabled) |
191 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 185 | return abx500_mask_and_set_register_interruptible(dev, 0, |
192 | AB3100_RTC, ~(1 << 2), | 186 | AB3100_RTC, (1 << 2), |
193 | 1 << 2); | 187 | 1 << 2); |
194 | else | 188 | else |
195 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 189 | return abx500_mask_and_set_register_interruptible(dev, 0, |
196 | AB3100_RTC, ~(1 << 2), | 190 | AB3100_RTC, (1 << 2), |
197 | 0); | 191 | 0); |
198 | } | 192 | } |
199 | 193 | ||
@@ -210,10 +204,9 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
210 | int err; | 204 | int err; |
211 | u8 regval; | 205 | u8 regval; |
212 | struct rtc_device *rtc; | 206 | struct rtc_device *rtc; |
213 | struct ab3100 *ab3100_data = platform_get_drvdata(pdev); | ||
214 | 207 | ||
215 | /* The first RTC register needs special treatment */ | 208 | /* The first RTC register needs special treatment */ |
216 | err = ab3100_get_register_interruptible(ab3100_data, | 209 | err = abx500_get_register_interruptible(&pdev->dev, 0, |
217 | AB3100_RTC, ®val); | 210 | AB3100_RTC, ®val); |
218 | if (err) { | 211 | if (err) { |
219 | dev_err(&pdev->dev, "unable to read RTC register\n"); | 212 | dev_err(&pdev->dev, "unable to read RTC register\n"); |
@@ -231,7 +224,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
231 | * This bit remains until RTC power is lost. | 224 | * This bit remains until RTC power is lost. |
232 | */ | 225 | */ |
233 | regval = 1 | RTC_SETTING; | 226 | regval = 1 | RTC_SETTING; |
234 | err = ab3100_set_register_interruptible(ab3100_data, | 227 | err = abx500_set_register_interruptible(&pdev->dev, 0, |
235 | AB3100_RTC, regval); | 228 | AB3100_RTC, regval); |
236 | /* Ignore any error on this write */ | 229 | /* Ignore any error on this write */ |
237 | } | 230 | } |
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c new file mode 100644 index 000000000000..2fda03125e55 --- /dev/null +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> | ||
6 | * | ||
7 | * RTC clock driver for the RTC part of the AB8500 Power management chip. | ||
8 | * Based on RTC clock driver for the AB3100 Analog Baseband Chip by | ||
9 | * Linus Walleij <linus.walleij@stericsson.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/mfd/ab8500.h> | ||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #define AB8500_RTC_SOFF_STAT_REG 0x0F00 | ||
21 | #define AB8500_RTC_CC_CONF_REG 0x0F01 | ||
22 | #define AB8500_RTC_READ_REQ_REG 0x0F02 | ||
23 | #define AB8500_RTC_WATCH_TSECMID_REG 0x0F03 | ||
24 | #define AB8500_RTC_WATCH_TSECHI_REG 0x0F04 | ||
25 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | ||
26 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06 | ||
27 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07 | ||
28 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08 | ||
29 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09 | ||
30 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A | ||
31 | #define AB8500_RTC_STAT_REG 0x0F0B | ||
32 | #define AB8500_RTC_BKUP_CHG_REG 0x0F0C | ||
33 | #define AB8500_RTC_FORCE_BKUP_REG 0x0F0D | ||
34 | #define AB8500_RTC_CALIB_REG 0x0F0E | ||
35 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F0F | ||
36 | #define AB8500_REV_REG 0x1080 | ||
37 | |||
38 | /* RtcReadRequest bits */ | ||
39 | #define RTC_READ_REQUEST 0x01 | ||
40 | #define RTC_WRITE_REQUEST 0x02 | ||
41 | |||
42 | /* RtcCtrl bits */ | ||
43 | #define RTC_ALARM_ENA 0x04 | ||
44 | #define RTC_STATUS_DATA 0x01 | ||
45 | |||
46 | #define COUNTS_PER_SEC (0xF000 / 60) | ||
47 | #define AB8500_RTC_EPOCH 2000 | ||
48 | |||
49 | static const unsigned long ab8500_rtc_time_regs[] = { | ||
50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, | ||
51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, | ||
52 | AB8500_RTC_WATCH_TSECMID_REG | ||
53 | }; | ||
54 | |||
55 | static const unsigned long ab8500_rtc_alarm_regs[] = { | ||
56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, | ||
57 | AB8500_RTC_ALRM_MIN_LOW_REG | ||
58 | }; | ||
59 | |||
60 | /* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ | ||
61 | static unsigned long get_elapsed_seconds(int year) | ||
62 | { | ||
63 | unsigned long secs; | ||
64 | struct rtc_time tm = { | ||
65 | .tm_year = year - 1900, | ||
66 | .tm_mday = 1, | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * This function calculates secs from 1970 and not from | ||
71 | * 1900, even if we supply the offset from year 1900. | ||
72 | */ | ||
73 | rtc_tm_to_time(&tm, &secs); | ||
74 | return secs; | ||
75 | } | ||
76 | |||
77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
78 | { | ||
79 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
80 | unsigned long timeout = jiffies + HZ; | ||
81 | int retval, i; | ||
82 | unsigned long mins, secs; | ||
83 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
84 | |||
85 | /* Request a data read */ | ||
86 | retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, | ||
87 | RTC_READ_REQUEST); | ||
88 | if (retval < 0) | ||
89 | return retval; | ||
90 | |||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | ||
92 | if (ab8500->revision == 0) { | ||
93 | msleep(1); | ||
94 | } else { | ||
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | ||
96 | while (time_before(jiffies, timeout)) { | ||
97 | retval = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG); | ||
98 | if (retval < 0) | ||
99 | return retval; | ||
100 | |||
101 | if (!(retval & RTC_READ_REQUEST)) | ||
102 | break; | ||
103 | |||
104 | msleep(1); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* Read the Watchtime registers */ | ||
109 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
110 | retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]); | ||
111 | if (retval < 0) | ||
112 | return retval; | ||
113 | buf[i] = retval; | ||
114 | } | ||
115 | |||
116 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | ||
117 | |||
118 | secs = (buf[3] << 8) | buf[4]; | ||
119 | secs = secs / COUNTS_PER_SEC; | ||
120 | secs = secs + (mins * 60); | ||
121 | |||
122 | /* Add back the initially subtracted number of seconds */ | ||
123 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
124 | |||
125 | rtc_time_to_tm(secs, tm); | ||
126 | return rtc_valid_tm(tm); | ||
127 | } | ||
128 | |||
129 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
130 | { | ||
131 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
132 | int retval, i; | ||
133 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
134 | unsigned long no_secs, no_mins, secs = 0; | ||
135 | |||
136 | if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
137 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
138 | AB8500_RTC_EPOCH); | ||
139 | return -EINVAL; | ||
140 | } | ||
141 | |||
142 | /* Get the number of seconds since 1970 */ | ||
143 | rtc_tm_to_time(tm, &secs); | ||
144 | |||
145 | /* | ||
146 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
147 | * we only have a small counter in the RTC. | ||
148 | */ | ||
149 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
150 | |||
151 | no_mins = secs / 60; | ||
152 | |||
153 | no_secs = secs % 60; | ||
154 | /* Make the seconds count as per the RTC resolution */ | ||
155 | no_secs = no_secs * COUNTS_PER_SEC; | ||
156 | |||
157 | buf[4] = no_secs & 0xFF; | ||
158 | buf[3] = (no_secs >> 8) & 0xFF; | ||
159 | |||
160 | buf[2] = no_mins & 0xFF; | ||
161 | buf[1] = (no_mins >> 8) & 0xFF; | ||
162 | buf[0] = (no_mins >> 16) & 0xFF; | ||
163 | |||
164 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
165 | retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]); | ||
166 | if (retval < 0) | ||
167 | return retval; | ||
168 | } | ||
169 | |||
170 | /* Request a data write */ | ||
171 | return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
172 | } | ||
173 | |||
174 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
175 | { | ||
176 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
177 | int retval, i; | ||
178 | int rtc_ctrl; | ||
179 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
180 | unsigned long secs, mins; | ||
181 | |||
182 | /* Check if the alarm is enabled or not */ | ||
183 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
184 | if (rtc_ctrl < 0) | ||
185 | return rtc_ctrl; | ||
186 | |||
187 | if (rtc_ctrl & RTC_ALARM_ENA) | ||
188 | alarm->enabled = 1; | ||
189 | else | ||
190 | alarm->enabled = 0; | ||
191 | |||
192 | alarm->pending = 0; | ||
193 | |||
194 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
195 | retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]); | ||
196 | if (retval < 0) | ||
197 | return retval; | ||
198 | buf[i] = retval; | ||
199 | } | ||
200 | |||
201 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | ||
202 | secs = mins * 60; | ||
203 | |||
204 | /* Add back the initially subtracted number of seconds */ | ||
205 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
206 | |||
207 | rtc_time_to_tm(secs, &alarm->time); | ||
208 | |||
209 | return rtc_valid_tm(&alarm->time); | ||
210 | } | ||
211 | |||
212 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
213 | { | ||
214 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
215 | |||
216 | return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | ||
217 | enabled ? RTC_ALARM_ENA : 0); | ||
218 | } | ||
219 | |||
220 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
221 | { | ||
222 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
223 | int retval, i; | ||
224 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
225 | unsigned long mins, secs = 0; | ||
226 | |||
227 | if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
228 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
229 | AB8500_RTC_EPOCH); | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
233 | /* Get the number of seconds since 1970 */ | ||
234 | rtc_tm_to_time(&alarm->time, &secs); | ||
235 | |||
236 | /* | ||
237 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
238 | * we only have a small counter in the RTC. | ||
239 | */ | ||
240 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
241 | |||
242 | mins = secs / 60; | ||
243 | |||
244 | buf[2] = mins & 0xFF; | ||
245 | buf[1] = (mins >> 8) & 0xFF; | ||
246 | buf[0] = (mins >> 16) & 0xFF; | ||
247 | |||
248 | /* Set the alarm time */ | ||
249 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
250 | retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]); | ||
251 | if (retval < 0) | ||
252 | return retval; | ||
253 | } | ||
254 | |||
255 | return ab8500_rtc_irq_enable(dev, alarm->enabled); | ||
256 | } | ||
257 | |||
258 | static irqreturn_t rtc_alarm_handler(int irq, void *data) | ||
259 | { | ||
260 | struct rtc_device *rtc = data; | ||
261 | unsigned long events = RTC_IRQF | RTC_AF; | ||
262 | |||
263 | dev_dbg(&rtc->dev, "%s\n", __func__); | ||
264 | rtc_update_irq(rtc, 1, events); | ||
265 | |||
266 | return IRQ_HANDLED; | ||
267 | } | ||
268 | |||
269 | static const struct rtc_class_ops ab8500_rtc_ops = { | ||
270 | .read_time = ab8500_rtc_read_time, | ||
271 | .set_time = ab8500_rtc_set_time, | ||
272 | .read_alarm = ab8500_rtc_read_alarm, | ||
273 | .set_alarm = ab8500_rtc_set_alarm, | ||
274 | .alarm_irq_enable = ab8500_rtc_irq_enable, | ||
275 | }; | ||
276 | |||
277 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | ||
278 | { | ||
279 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
280 | int err; | ||
281 | struct rtc_device *rtc; | ||
282 | int rtc_ctrl; | ||
283 | int irq; | ||
284 | |||
285 | irq = platform_get_irq_byname(pdev, "ALARM"); | ||
286 | if (irq < 0) | ||
287 | return irq; | ||
288 | |||
289 | /* For RTC supply test */ | ||
290 | err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA, | ||
291 | RTC_STATUS_DATA); | ||
292 | if (err < 0) | ||
293 | return err; | ||
294 | |||
295 | /* Wait for reset by the PorRtc */ | ||
296 | msleep(1); | ||
297 | |||
298 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
299 | if (rtc_ctrl < 0) | ||
300 | return rtc_ctrl; | ||
301 | |||
302 | /* Check if the RTC Supply fails */ | ||
303 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | ||
304 | dev_err(&pdev->dev, "RTC supply failure\n"); | ||
305 | return -ENODEV; | ||
306 | } | ||
307 | |||
308 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, | ||
309 | THIS_MODULE); | ||
310 | if (IS_ERR(rtc)) { | ||
311 | dev_err(&pdev->dev, "Registration failed\n"); | ||
312 | err = PTR_ERR(rtc); | ||
313 | return err; | ||
314 | } | ||
315 | |||
316 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, | ||
317 | "ab8500-rtc", rtc); | ||
318 | if (err < 0) { | ||
319 | rtc_device_unregister(rtc); | ||
320 | return err; | ||
321 | } | ||
322 | |||
323 | platform_set_drvdata(pdev, rtc); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int __devexit ab8500_rtc_remove(struct platform_device *pdev) | ||
329 | { | ||
330 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
331 | int irq = platform_get_irq_byname(pdev, "ALARM"); | ||
332 | |||
333 | free_irq(irq, rtc); | ||
334 | rtc_device_unregister(rtc); | ||
335 | platform_set_drvdata(pdev, NULL); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct platform_driver ab8500_rtc_driver = { | ||
341 | .driver = { | ||
342 | .name = "ab8500-rtc", | ||
343 | .owner = THIS_MODULE, | ||
344 | }, | ||
345 | .probe = ab8500_rtc_probe, | ||
346 | .remove = __devexit_p(ab8500_rtc_remove), | ||
347 | }; | ||
348 | |||
349 | static int __init ab8500_rtc_init(void) | ||
350 | { | ||
351 | return platform_driver_register(&ab8500_rtc_driver); | ||
352 | } | ||
353 | |||
354 | static void __exit ab8500_rtc_exit(void) | ||
355 | { | ||
356 | platform_driver_unregister(&ab8500_rtc_driver); | ||
357 | } | ||
358 | |||
359 | module_init(ab8500_rtc_init); | ||
360 | module_exit(ab8500_rtc_exit); | ||
361 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); | ||
362 | MODULE_DESCRIPTION("AB8500 RTC Driver"); | ||
363 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index e9aa814ddd23..5856167a0c90 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -238,31 +238,32 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
238 | rtc_control = CMOS_READ(RTC_CONTROL); | 238 | rtc_control = CMOS_READ(RTC_CONTROL); |
239 | spin_unlock_irq(&rtc_lock); | 239 | spin_unlock_irq(&rtc_lock); |
240 | 240 | ||
241 | /* REVISIT this assumes PC style usage: always BCD */ | 241 | if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
242 | 242 | if (((unsigned)t->time.tm_sec) < 0x60) | |
243 | if (((unsigned)t->time.tm_sec) < 0x60) | 243 | t->time.tm_sec = bcd2bin(t->time.tm_sec); |
244 | t->time.tm_sec = bcd2bin(t->time.tm_sec); | ||
245 | else | ||
246 | t->time.tm_sec = -1; | ||
247 | if (((unsigned)t->time.tm_min) < 0x60) | ||
248 | t->time.tm_min = bcd2bin(t->time.tm_min); | ||
249 | else | ||
250 | t->time.tm_min = -1; | ||
251 | if (((unsigned)t->time.tm_hour) < 0x24) | ||
252 | t->time.tm_hour = bcd2bin(t->time.tm_hour); | ||
253 | else | ||
254 | t->time.tm_hour = -1; | ||
255 | |||
256 | if (cmos->day_alrm) { | ||
257 | if (((unsigned)t->time.tm_mday) <= 0x31) | ||
258 | t->time.tm_mday = bcd2bin(t->time.tm_mday); | ||
259 | else | 244 | else |
260 | t->time.tm_mday = -1; | 245 | t->time.tm_sec = -1; |
261 | if (cmos->mon_alrm) { | 246 | if (((unsigned)t->time.tm_min) < 0x60) |
262 | if (((unsigned)t->time.tm_mon) <= 0x12) | 247 | t->time.tm_min = bcd2bin(t->time.tm_min); |
263 | t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1; | 248 | else |
249 | t->time.tm_min = -1; | ||
250 | if (((unsigned)t->time.tm_hour) < 0x24) | ||
251 | t->time.tm_hour = bcd2bin(t->time.tm_hour); | ||
252 | else | ||
253 | t->time.tm_hour = -1; | ||
254 | |||
255 | if (cmos->day_alrm) { | ||
256 | if (((unsigned)t->time.tm_mday) <= 0x31) | ||
257 | t->time.tm_mday = bcd2bin(t->time.tm_mday); | ||
264 | else | 258 | else |
265 | t->time.tm_mon = -1; | 259 | t->time.tm_mday = -1; |
260 | |||
261 | if (cmos->mon_alrm) { | ||
262 | if (((unsigned)t->time.tm_mon) <= 0x12) | ||
263 | t->time.tm_mon = bcd2bin(t->time.tm_mon)-1; | ||
264 | else | ||
265 | t->time.tm_mon = -1; | ||
266 | } | ||
266 | } | 267 | } |
267 | } | 268 | } |
268 | t->time.tm_year = -1; | 269 | t->time.tm_year = -1; |
@@ -322,29 +323,26 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) | |||
322 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 323 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
323 | { | 324 | { |
324 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 325 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
325 | unsigned char mon, mday, hrs, min, sec; | 326 | unsigned char mon, mday, hrs, min, sec, rtc_control; |
326 | 327 | ||
327 | if (!is_valid_irq(cmos->irq)) | 328 | if (!is_valid_irq(cmos->irq)) |
328 | return -EIO; | 329 | return -EIO; |
329 | 330 | ||
330 | /* REVISIT this assumes PC style usage: always BCD */ | ||
331 | |||
332 | /* Writing 0xff means "don't care" or "match all". */ | ||
333 | |||
334 | mon = t->time.tm_mon + 1; | 331 | mon = t->time.tm_mon + 1; |
335 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; | ||
336 | |||
337 | mday = t->time.tm_mday; | 332 | mday = t->time.tm_mday; |
338 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; | ||
339 | |||
340 | hrs = t->time.tm_hour; | 333 | hrs = t->time.tm_hour; |
341 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; | ||
342 | |||
343 | min = t->time.tm_min; | 334 | min = t->time.tm_min; |
344 | min = (min < 60) ? bin2bcd(min) : 0xff; | ||
345 | |||
346 | sec = t->time.tm_sec; | 335 | sec = t->time.tm_sec; |
347 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; | 336 | |
337 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
338 | if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
339 | /* Writing 0xff means "don't care" or "match all". */ | ||
340 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; | ||
341 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; | ||
342 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; | ||
343 | min = (min < 60) ? bin2bcd(min) : 0xff; | ||
344 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; | ||
345 | } | ||
348 | 346 | ||
349 | spin_lock_irq(&rtc_lock); | 347 | spin_lock_irq(&rtc_lock); |
350 | 348 | ||
@@ -478,7 +476,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
478 | "update_IRQ\t: %s\n" | 476 | "update_IRQ\t: %s\n" |
479 | "HPET_emulated\t: %s\n" | 477 | "HPET_emulated\t: %s\n" |
480 | // "square_wave\t: %s\n" | 478 | // "square_wave\t: %s\n" |
481 | // "BCD\t\t: %s\n" | 479 | "BCD\t\t: %s\n" |
482 | "DST_enable\t: %s\n" | 480 | "DST_enable\t: %s\n" |
483 | "periodic_freq\t: %d\n" | 481 | "periodic_freq\t: %d\n" |
484 | "batt_status\t: %s\n", | 482 | "batt_status\t: %s\n", |
@@ -486,7 +484,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
486 | (rtc_control & RTC_UIE) ? "yes" : "no", | 484 | (rtc_control & RTC_UIE) ? "yes" : "no", |
487 | is_hpet_enabled() ? "yes" : "no", | 485 | is_hpet_enabled() ? "yes" : "no", |
488 | // (rtc_control & RTC_SQWE) ? "yes" : "no", | 486 | // (rtc_control & RTC_SQWE) ? "yes" : "no", |
489 | // (rtc_control & RTC_DM_BINARY) ? "no" : "yes", | 487 | (rtc_control & RTC_DM_BINARY) ? "no" : "yes", |
490 | (rtc_control & RTC_DST_EN) ? "yes" : "no", | 488 | (rtc_control & RTC_DST_EN) ? "yes" : "no", |
491 | cmos->rtc->irq_freq, | 489 | cmos->rtc->irq_freq, |
492 | (valid & RTC_VRT) ? "okay" : "dead"); | 490 | (valid & RTC_VRT) ? "okay" : "dead"); |
@@ -519,7 +517,8 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
519 | #define NVRAM_OFFSET (RTC_REG_D + 1) | 517 | #define NVRAM_OFFSET (RTC_REG_D + 1) |
520 | 518 | ||
521 | static ssize_t | 519 | static ssize_t |
522 | cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 520 | cmos_nvram_read(struct file *filp, struct kobject *kobj, |
521 | struct bin_attribute *attr, | ||
523 | char *buf, loff_t off, size_t count) | 522 | char *buf, loff_t off, size_t count) |
524 | { | 523 | { |
525 | int retval; | 524 | int retval; |
@@ -547,7 +546,8 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
547 | } | 546 | } |
548 | 547 | ||
549 | static ssize_t | 548 | static ssize_t |
550 | cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 549 | cmos_nvram_write(struct file *filp, struct kobject *kobj, |
550 | struct bin_attribute *attr, | ||
551 | char *buf, loff_t off, size_t count) | 551 | char *buf, loff_t off, size_t count) |
552 | { | 552 | { |
553 | struct cmos_rtc *cmos; | 553 | struct cmos_rtc *cmos; |
@@ -719,6 +719,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
719 | } | 719 | } |
720 | } | 720 | } |
721 | 721 | ||
722 | cmos_rtc.dev = dev; | ||
723 | dev_set_drvdata(dev, &cmos_rtc); | ||
724 | |||
722 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, | 725 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, |
723 | &cmos_rtc_ops, THIS_MODULE); | 726 | &cmos_rtc_ops, THIS_MODULE); |
724 | if (IS_ERR(cmos_rtc.rtc)) { | 727 | if (IS_ERR(cmos_rtc.rtc)) { |
@@ -726,8 +729,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
726 | goto cleanup0; | 729 | goto cleanup0; |
727 | } | 730 | } |
728 | 731 | ||
729 | cmos_rtc.dev = dev; | ||
730 | dev_set_drvdata(dev, &cmos_rtc); | ||
731 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); | 732 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); |
732 | 733 | ||
733 | spin_lock_irq(&rtc_lock); | 734 | spin_lock_irq(&rtc_lock); |
@@ -749,12 +750,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
749 | 750 | ||
750 | spin_unlock_irq(&rtc_lock); | 751 | spin_unlock_irq(&rtc_lock); |
751 | 752 | ||
752 | /* FIXME teach the alarm code how to handle binary mode; | 753 | /* FIXME: |
753 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 754 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
754 | */ | 755 | */ |
755 | if (is_valid_irq(rtc_irq) && | 756 | if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { |
756 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | 757 | dev_warn(dev, "only 24-hr supported\n"); |
757 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | ||
758 | retval = -ENXIO; | 758 | retval = -ENXIO; |
759 | goto cleanup1; | 759 | goto cleanup1; |
760 | } | 760 | } |
@@ -970,7 +970,6 @@ static inline int cmos_poweroff(struct device *dev) | |||
970 | 970 | ||
971 | #include <linux/acpi.h> | 971 | #include <linux/acpi.h> |
972 | 972 | ||
973 | #ifdef CONFIG_PM | ||
974 | static u32 rtc_handler(void *context) | 973 | static u32 rtc_handler(void *context) |
975 | { | 974 | { |
976 | acpi_clear_event(ACPI_EVENT_RTC); | 975 | acpi_clear_event(ACPI_EVENT_RTC); |
@@ -999,11 +998,6 @@ static void rtc_wake_off(struct device *dev) | |||
999 | { | 998 | { |
1000 | acpi_disable_event(ACPI_EVENT_RTC, 0); | 999 | acpi_disable_event(ACPI_EVENT_RTC, 0); |
1001 | } | 1000 | } |
1002 | #else | ||
1003 | #define rtc_wake_setup() do{}while(0) | ||
1004 | #define rtc_wake_on NULL | ||
1005 | #define rtc_wake_off NULL | ||
1006 | #endif | ||
1007 | 1001 | ||
1008 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | 1002 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find |
1009 | * its device node and pass extra config data. This helps its driver use | 1003 | * its device node and pass extra config data. This helps its driver use |
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c new file mode 100644 index 000000000000..34647fc1ee98 --- /dev/null +++ b/drivers/rtc/rtc-davinci.c | |||
@@ -0,0 +1,674 @@ | |||
1 | /* | ||
2 | * DaVinci Power Management and Real Time Clock Driver for TI platforms | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments, Inc | ||
5 | * | ||
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/rtc.h> | ||
29 | #include <linux/bcd.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | /* | ||
35 | * The DaVinci RTC is a simple RTC with the following | ||
36 | * Sec: 0 - 59 : BCD count | ||
37 | * Min: 0 - 59 : BCD count | ||
38 | * Hour: 0 - 23 : BCD count | ||
39 | * Day: 0 - 0x7FFF(32767) : Binary count ( Over 89 years ) | ||
40 | */ | ||
41 | |||
42 | /* PRTC interface registers */ | ||
43 | #define DAVINCI_PRTCIF_PID 0x00 | ||
44 | #define PRTCIF_CTLR 0x04 | ||
45 | #define PRTCIF_LDATA 0x08 | ||
46 | #define PRTCIF_UDATA 0x0C | ||
47 | #define PRTCIF_INTEN 0x10 | ||
48 | #define PRTCIF_INTFLG 0x14 | ||
49 | |||
50 | /* PRTCIF_CTLR bit fields */ | ||
51 | #define PRTCIF_CTLR_BUSY BIT(31) | ||
52 | #define PRTCIF_CTLR_SIZE BIT(25) | ||
53 | #define PRTCIF_CTLR_DIR BIT(24) | ||
54 | #define PRTCIF_CTLR_BENU_MSB BIT(23) | ||
55 | #define PRTCIF_CTLR_BENU_3RD_BYTE BIT(22) | ||
56 | #define PRTCIF_CTLR_BENU_2ND_BYTE BIT(21) | ||
57 | #define PRTCIF_CTLR_BENU_LSB BIT(20) | ||
58 | #define PRTCIF_CTLR_BENU_MASK (0x00F00000) | ||
59 | #define PRTCIF_CTLR_BENL_MSB BIT(19) | ||
60 | #define PRTCIF_CTLR_BENL_3RD_BYTE BIT(18) | ||
61 | #define PRTCIF_CTLR_BENL_2ND_BYTE BIT(17) | ||
62 | #define PRTCIF_CTLR_BENL_LSB BIT(16) | ||
63 | #define PRTCIF_CTLR_BENL_MASK (0x000F0000) | ||
64 | |||
65 | /* PRTCIF_INTEN bit fields */ | ||
66 | #define PRTCIF_INTEN_RTCSS BIT(1) | ||
67 | #define PRTCIF_INTEN_RTCIF BIT(0) | ||
68 | #define PRTCIF_INTEN_MASK (PRTCIF_INTEN_RTCSS \ | ||
69 | | PRTCIF_INTEN_RTCIF) | ||
70 | |||
71 | /* PRTCIF_INTFLG bit fields */ | ||
72 | #define PRTCIF_INTFLG_RTCSS BIT(1) | ||
73 | #define PRTCIF_INTFLG_RTCIF BIT(0) | ||
74 | #define PRTCIF_INTFLG_MASK (PRTCIF_INTFLG_RTCSS \ | ||
75 | | PRTCIF_INTFLG_RTCIF) | ||
76 | |||
77 | /* PRTC subsystem registers */ | ||
78 | #define PRTCSS_RTC_INTC_EXTENA1 (0x0C) | ||
79 | #define PRTCSS_RTC_CTRL (0x10) | ||
80 | #define PRTCSS_RTC_WDT (0x11) | ||
81 | #define PRTCSS_RTC_TMR0 (0x12) | ||
82 | #define PRTCSS_RTC_TMR1 (0x13) | ||
83 | #define PRTCSS_RTC_CCTRL (0x14) | ||
84 | #define PRTCSS_RTC_SEC (0x15) | ||
85 | #define PRTCSS_RTC_MIN (0x16) | ||
86 | #define PRTCSS_RTC_HOUR (0x17) | ||
87 | #define PRTCSS_RTC_DAY0 (0x18) | ||
88 | #define PRTCSS_RTC_DAY1 (0x19) | ||
89 | #define PRTCSS_RTC_AMIN (0x1A) | ||
90 | #define PRTCSS_RTC_AHOUR (0x1B) | ||
91 | #define PRTCSS_RTC_ADAY0 (0x1C) | ||
92 | #define PRTCSS_RTC_ADAY1 (0x1D) | ||
93 | #define PRTCSS_RTC_CLKC_CNT (0x20) | ||
94 | |||
95 | /* PRTCSS_RTC_INTC_EXTENA1 */ | ||
96 | #define PRTCSS_RTC_INTC_EXTENA1_MASK (0x07) | ||
97 | |||
98 | /* PRTCSS_RTC_CTRL bit fields */ | ||
99 | #define PRTCSS_RTC_CTRL_WDTBUS BIT(7) | ||
100 | #define PRTCSS_RTC_CTRL_WEN BIT(6) | ||
101 | #define PRTCSS_RTC_CTRL_WDRT BIT(5) | ||
102 | #define PRTCSS_RTC_CTRL_WDTFLG BIT(4) | ||
103 | #define PRTCSS_RTC_CTRL_TE BIT(3) | ||
104 | #define PRTCSS_RTC_CTRL_TIEN BIT(2) | ||
105 | #define PRTCSS_RTC_CTRL_TMRFLG BIT(1) | ||
106 | #define PRTCSS_RTC_CTRL_TMMD BIT(0) | ||
107 | |||
108 | /* PRTCSS_RTC_CCTRL bit fields */ | ||
109 | #define PRTCSS_RTC_CCTRL_CALBUSY BIT(7) | ||
110 | #define PRTCSS_RTC_CCTRL_DAEN BIT(5) | ||
111 | #define PRTCSS_RTC_CCTRL_HAEN BIT(4) | ||
112 | #define PRTCSS_RTC_CCTRL_MAEN BIT(3) | ||
113 | #define PRTCSS_RTC_CCTRL_ALMFLG BIT(2) | ||
114 | #define PRTCSS_RTC_CCTRL_AIEN BIT(1) | ||
115 | #define PRTCSS_RTC_CCTRL_CAEN BIT(0) | ||
116 | |||
117 | static DEFINE_SPINLOCK(davinci_rtc_lock); | ||
118 | |||
119 | struct davinci_rtc { | ||
120 | struct rtc_device *rtc; | ||
121 | void __iomem *base; | ||
122 | resource_size_t pbase; | ||
123 | size_t base_size; | ||
124 | int irq; | ||
125 | }; | ||
126 | |||
127 | static inline void rtcif_write(struct davinci_rtc *davinci_rtc, | ||
128 | u32 val, u32 addr) | ||
129 | { | ||
130 | writel(val, davinci_rtc->base + addr); | ||
131 | } | ||
132 | |||
133 | static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr) | ||
134 | { | ||
135 | return readl(davinci_rtc->base + addr); | ||
136 | } | ||
137 | |||
138 | static inline void rtcif_wait(struct davinci_rtc *davinci_rtc) | ||
139 | { | ||
140 | while (rtcif_read(davinci_rtc, PRTCIF_CTLR) & PRTCIF_CTLR_BUSY) | ||
141 | cpu_relax(); | ||
142 | } | ||
143 | |||
144 | static inline void rtcss_write(struct davinci_rtc *davinci_rtc, | ||
145 | unsigned long val, u8 addr) | ||
146 | { | ||
147 | rtcif_wait(davinci_rtc); | ||
148 | |||
149 | rtcif_write(davinci_rtc, PRTCIF_CTLR_BENL_LSB | addr, PRTCIF_CTLR); | ||
150 | rtcif_write(davinci_rtc, val, PRTCIF_LDATA); | ||
151 | |||
152 | rtcif_wait(davinci_rtc); | ||
153 | } | ||
154 | |||
155 | static inline u8 rtcss_read(struct davinci_rtc *davinci_rtc, u8 addr) | ||
156 | { | ||
157 | rtcif_wait(davinci_rtc); | ||
158 | |||
159 | rtcif_write(davinci_rtc, PRTCIF_CTLR_DIR | PRTCIF_CTLR_BENL_LSB | addr, | ||
160 | PRTCIF_CTLR); | ||
161 | |||
162 | rtcif_wait(davinci_rtc); | ||
163 | |||
164 | return rtcif_read(davinci_rtc, PRTCIF_LDATA); | ||
165 | } | ||
166 | |||
167 | static inline void davinci_rtcss_calendar_wait(struct davinci_rtc *davinci_rtc) | ||
168 | { | ||
169 | while (rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & | ||
170 | PRTCSS_RTC_CCTRL_CALBUSY) | ||
171 | cpu_relax(); | ||
172 | } | ||
173 | |||
174 | static irqreturn_t davinci_rtc_interrupt(int irq, void *class_dev) | ||
175 | { | ||
176 | struct davinci_rtc *davinci_rtc = class_dev; | ||
177 | unsigned long events = 0; | ||
178 | u32 irq_flg; | ||
179 | u8 alm_irq, tmr_irq; | ||
180 | u8 rtc_ctrl, rtc_cctrl; | ||
181 | int ret = IRQ_NONE; | ||
182 | |||
183 | irq_flg = rtcif_read(davinci_rtc, PRTCIF_INTFLG) & | ||
184 | PRTCIF_INTFLG_RTCSS; | ||
185 | |||
186 | alm_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & | ||
187 | PRTCSS_RTC_CCTRL_ALMFLG; | ||
188 | |||
189 | tmr_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) & | ||
190 | PRTCSS_RTC_CTRL_TMRFLG; | ||
191 | |||
192 | if (irq_flg) { | ||
193 | if (alm_irq) { | ||
194 | events |= RTC_IRQF | RTC_AF; | ||
195 | rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
196 | rtc_cctrl |= PRTCSS_RTC_CCTRL_ALMFLG; | ||
197 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
198 | } else if (tmr_irq) { | ||
199 | events |= RTC_IRQF | RTC_PF; | ||
200 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
201 | rtc_ctrl |= PRTCSS_RTC_CTRL_TMRFLG; | ||
202 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
203 | } | ||
204 | |||
205 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, | ||
206 | PRTCIF_INTFLG); | ||
207 | rtc_update_irq(davinci_rtc->rtc, 1, events); | ||
208 | |||
209 | ret = IRQ_HANDLED; | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int | ||
216 | davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
217 | { | ||
218 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
219 | u8 rtc_ctrl; | ||
220 | unsigned long flags; | ||
221 | int ret = 0; | ||
222 | |||
223 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
224 | |||
225 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
226 | |||
227 | switch (cmd) { | ||
228 | case RTC_WIE_ON: | ||
229 | rtc_ctrl |= PRTCSS_RTC_CTRL_WEN | PRTCSS_RTC_CTRL_WDTFLG; | ||
230 | break; | ||
231 | case RTC_WIE_OFF: | ||
232 | rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN; | ||
233 | break; | ||
234 | case RTC_UIE_OFF: | ||
235 | case RTC_UIE_ON: | ||
236 | ret = -ENOTTY; | ||
237 | break; | ||
238 | default: | ||
239 | ret = -ENOIOCTLCMD; | ||
240 | } | ||
241 | |||
242 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
243 | |||
244 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int convertfromdays(u16 days, struct rtc_time *tm) | ||
250 | { | ||
251 | int tmp_days, year, mon; | ||
252 | |||
253 | for (year = 2000;; year++) { | ||
254 | tmp_days = rtc_year_days(1, 12, year); | ||
255 | if (days >= tmp_days) | ||
256 | days -= tmp_days; | ||
257 | else { | ||
258 | for (mon = 0;; mon++) { | ||
259 | tmp_days = rtc_month_days(mon, year); | ||
260 | if (days >= tmp_days) { | ||
261 | days -= tmp_days; | ||
262 | } else { | ||
263 | tm->tm_year = year - 1900; | ||
264 | tm->tm_mon = mon; | ||
265 | tm->tm_mday = days + 1; | ||
266 | break; | ||
267 | } | ||
268 | } | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int convert2days(u16 *days, struct rtc_time *tm) | ||
276 | { | ||
277 | int i; | ||
278 | *days = 0; | ||
279 | |||
280 | /* epoch == 1900 */ | ||
281 | if (tm->tm_year < 100 || tm->tm_year > 199) | ||
282 | return -EINVAL; | ||
283 | |||
284 | for (i = 2000; i < 1900 + tm->tm_year; i++) | ||
285 | *days += rtc_year_days(1, 12, i); | ||
286 | |||
287 | *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
293 | { | ||
294 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
295 | u16 days = 0; | ||
296 | u8 day0, day1; | ||
297 | unsigned long flags; | ||
298 | |||
299 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
300 | |||
301 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
302 | tm->tm_sec = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_SEC)); | ||
303 | |||
304 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
305 | tm->tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_MIN)); | ||
306 | |||
307 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
308 | tm->tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_HOUR)); | ||
309 | |||
310 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
311 | day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY0); | ||
312 | |||
313 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
314 | day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY1); | ||
315 | |||
316 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
317 | |||
318 | days |= day1; | ||
319 | days <<= 8; | ||
320 | days |= day0; | ||
321 | |||
322 | if (convertfromdays(days, tm) < 0) | ||
323 | return -EINVAL; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
329 | { | ||
330 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
331 | u16 days; | ||
332 | u8 rtc_cctrl; | ||
333 | unsigned long flags; | ||
334 | |||
335 | if (convert2days(&days, tm) < 0) | ||
336 | return -EINVAL; | ||
337 | |||
338 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
339 | |||
340 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
341 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_sec), PRTCSS_RTC_SEC); | ||
342 | |||
343 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
344 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_min), PRTCSS_RTC_MIN); | ||
345 | |||
346 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
347 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_hour), PRTCSS_RTC_HOUR); | ||
348 | |||
349 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
350 | rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_DAY0); | ||
351 | |||
352 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
353 | rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_DAY1); | ||
354 | |||
355 | rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
356 | rtc_cctrl |= PRTCSS_RTC_CCTRL_CAEN; | ||
357 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
358 | |||
359 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int davinci_rtc_alarm_irq_enable(struct device *dev, | ||
365 | unsigned int enabled) | ||
366 | { | ||
367 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
368 | unsigned long flags; | ||
369 | u8 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
370 | |||
371 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
372 | |||
373 | if (enabled) | ||
374 | rtc_cctrl |= PRTCSS_RTC_CCTRL_DAEN | | ||
375 | PRTCSS_RTC_CCTRL_HAEN | | ||
376 | PRTCSS_RTC_CCTRL_MAEN | | ||
377 | PRTCSS_RTC_CCTRL_ALMFLG | | ||
378 | PRTCSS_RTC_CCTRL_AIEN; | ||
379 | else | ||
380 | rtc_cctrl &= ~PRTCSS_RTC_CCTRL_AIEN; | ||
381 | |||
382 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
383 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
384 | |||
385 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
391 | { | ||
392 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
393 | u16 days = 0; | ||
394 | u8 day0, day1; | ||
395 | unsigned long flags; | ||
396 | |||
397 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
398 | |||
399 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
400 | alm->time.tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AMIN)); | ||
401 | |||
402 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
403 | alm->time.tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AHOUR)); | ||
404 | |||
405 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
406 | day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY0); | ||
407 | |||
408 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
409 | day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY1); | ||
410 | |||
411 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
412 | days |= day1; | ||
413 | days <<= 8; | ||
414 | days |= day0; | ||
415 | |||
416 | if (convertfromdays(days, &alm->time) < 0) | ||
417 | return -EINVAL; | ||
418 | |||
419 | alm->pending = !!(rtcss_read(davinci_rtc, | ||
420 | PRTCSS_RTC_CCTRL) & | ||
421 | PRTCSS_RTC_CCTRL_AIEN); | ||
422 | alm->enabled = alm->pending && device_may_wakeup(dev); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
428 | { | ||
429 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
430 | unsigned long flags; | ||
431 | u16 days; | ||
432 | |||
433 | if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0 | ||
434 | && alm->time.tm_year < 0) { | ||
435 | struct rtc_time tm; | ||
436 | unsigned long now, then; | ||
437 | |||
438 | davinci_rtc_read_time(dev, &tm); | ||
439 | rtc_tm_to_time(&tm, &now); | ||
440 | |||
441 | alm->time.tm_mday = tm.tm_mday; | ||
442 | alm->time.tm_mon = tm.tm_mon; | ||
443 | alm->time.tm_year = tm.tm_year; | ||
444 | rtc_tm_to_time(&alm->time, &then); | ||
445 | |||
446 | if (then < now) { | ||
447 | rtc_time_to_tm(now + 24 * 60 * 60, &tm); | ||
448 | alm->time.tm_mday = tm.tm_mday; | ||
449 | alm->time.tm_mon = tm.tm_mon; | ||
450 | alm->time.tm_year = tm.tm_year; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | if (convert2days(&days, &alm->time) < 0) | ||
455 | return -EINVAL; | ||
456 | |||
457 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
458 | |||
459 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
460 | rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_min), PRTCSS_RTC_AMIN); | ||
461 | |||
462 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
463 | rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_hour), PRTCSS_RTC_AHOUR); | ||
464 | |||
465 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
466 | rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_ADAY0); | ||
467 | |||
468 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
469 | rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_ADAY1); | ||
470 | |||
471 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int davinci_rtc_irq_set_state(struct device *dev, int enabled) | ||
477 | { | ||
478 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
479 | unsigned long flags; | ||
480 | u8 rtc_ctrl; | ||
481 | |||
482 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
483 | |||
484 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
485 | |||
486 | if (enabled) { | ||
487 | while (rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) | ||
488 | & PRTCSS_RTC_CTRL_WDTBUS) | ||
489 | cpu_relax(); | ||
490 | |||
491 | rtc_ctrl |= PRTCSS_RTC_CTRL_TE; | ||
492 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
493 | |||
494 | rtcss_write(davinci_rtc, 0x0, PRTCSS_RTC_CLKC_CNT); | ||
495 | |||
496 | rtc_ctrl |= PRTCSS_RTC_CTRL_TIEN | | ||
497 | PRTCSS_RTC_CTRL_TMMD | | ||
498 | PRTCSS_RTC_CTRL_TMRFLG; | ||
499 | } else | ||
500 | rtc_ctrl &= ~PRTCSS_RTC_CTRL_TIEN; | ||
501 | |||
502 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
503 | |||
504 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int davinci_rtc_irq_set_freq(struct device *dev, int freq) | ||
510 | { | ||
511 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
512 | unsigned long flags; | ||
513 | u16 tmr_counter = (0x8000 >> (ffs(freq) - 1)); | ||
514 | |||
515 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
516 | |||
517 | rtcss_write(davinci_rtc, tmr_counter & 0xFF, PRTCSS_RTC_TMR0); | ||
518 | rtcss_write(davinci_rtc, (tmr_counter & 0xFF00) >> 8, PRTCSS_RTC_TMR1); | ||
519 | |||
520 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static struct rtc_class_ops davinci_rtc_ops = { | ||
526 | .ioctl = davinci_rtc_ioctl, | ||
527 | .read_time = davinci_rtc_read_time, | ||
528 | .set_time = davinci_rtc_set_time, | ||
529 | .alarm_irq_enable = davinci_rtc_alarm_irq_enable, | ||
530 | .read_alarm = davinci_rtc_read_alarm, | ||
531 | .set_alarm = davinci_rtc_set_alarm, | ||
532 | .irq_set_state = davinci_rtc_irq_set_state, | ||
533 | .irq_set_freq = davinci_rtc_irq_set_freq, | ||
534 | }; | ||
535 | |||
536 | static int __init davinci_rtc_probe(struct platform_device *pdev) | ||
537 | { | ||
538 | struct device *dev = &pdev->dev; | ||
539 | struct davinci_rtc *davinci_rtc; | ||
540 | struct resource *res, *mem; | ||
541 | int ret = 0; | ||
542 | |||
543 | davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); | ||
544 | if (!davinci_rtc) { | ||
545 | dev_dbg(dev, "could not allocate memory for private data\n"); | ||
546 | return -ENOMEM; | ||
547 | } | ||
548 | |||
549 | davinci_rtc->irq = platform_get_irq(pdev, 0); | ||
550 | if (davinci_rtc->irq < 0) { | ||
551 | dev_err(dev, "no RTC irq\n"); | ||
552 | ret = davinci_rtc->irq; | ||
553 | goto fail1; | ||
554 | } | ||
555 | |||
556 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
557 | if (!res) { | ||
558 | dev_err(dev, "no mem resource\n"); | ||
559 | ret = -EINVAL; | ||
560 | goto fail1; | ||
561 | } | ||
562 | |||
563 | davinci_rtc->pbase = res->start; | ||
564 | davinci_rtc->base_size = resource_size(res); | ||
565 | |||
566 | mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size, | ||
567 | pdev->name); | ||
568 | if (!mem) { | ||
569 | dev_err(dev, "RTC registers at %08x are not free\n", | ||
570 | davinci_rtc->pbase); | ||
571 | ret = -EBUSY; | ||
572 | goto fail1; | ||
573 | } | ||
574 | |||
575 | davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); | ||
576 | if (!davinci_rtc->base) { | ||
577 | dev_err(dev, "unable to ioremap MEM resource\n"); | ||
578 | ret = -ENOMEM; | ||
579 | goto fail2; | ||
580 | } | ||
581 | |||
582 | davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
583 | &davinci_rtc_ops, THIS_MODULE); | ||
584 | if (IS_ERR(davinci_rtc->rtc)) { | ||
585 | dev_err(dev, "unable to register RTC device, err %ld\n", | ||
586 | PTR_ERR(davinci_rtc->rtc)); | ||
587 | goto fail3; | ||
588 | } | ||
589 | |||
590 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); | ||
591 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); | ||
592 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1); | ||
593 | |||
594 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); | ||
595 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); | ||
596 | |||
597 | ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, | ||
598 | IRQF_DISABLED, "davinci_rtc", davinci_rtc); | ||
599 | if (ret < 0) { | ||
600 | dev_err(dev, "unable to register davinci RTC interrupt\n"); | ||
601 | goto fail4; | ||
602 | } | ||
603 | |||
604 | /* Enable interrupts */ | ||
605 | rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN); | ||
606 | rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK, | ||
607 | PRTCSS_RTC_INTC_EXTENA1); | ||
608 | |||
609 | rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL); | ||
610 | |||
611 | platform_set_drvdata(pdev, davinci_rtc); | ||
612 | |||
613 | device_init_wakeup(&pdev->dev, 0); | ||
614 | |||
615 | return 0; | ||
616 | |||
617 | fail4: | ||
618 | rtc_device_unregister(davinci_rtc->rtc); | ||
619 | fail3: | ||
620 | iounmap(davinci_rtc->base); | ||
621 | fail2: | ||
622 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
623 | fail1: | ||
624 | kfree(davinci_rtc); | ||
625 | |||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static int __devexit davinci_rtc_remove(struct platform_device *pdev) | ||
630 | { | ||
631 | struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); | ||
632 | |||
633 | device_init_wakeup(&pdev->dev, 0); | ||
634 | |||
635 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); | ||
636 | |||
637 | free_irq(davinci_rtc->irq, davinci_rtc); | ||
638 | |||
639 | rtc_device_unregister(davinci_rtc->rtc); | ||
640 | |||
641 | iounmap(davinci_rtc->base); | ||
642 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
643 | |||
644 | platform_set_drvdata(pdev, NULL); | ||
645 | |||
646 | kfree(davinci_rtc); | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | static struct platform_driver davinci_rtc_driver = { | ||
652 | .probe = davinci_rtc_probe, | ||
653 | .remove = __devexit_p(davinci_rtc_remove), | ||
654 | .driver = { | ||
655 | .name = "rtc_davinci", | ||
656 | .owner = THIS_MODULE, | ||
657 | }, | ||
658 | }; | ||
659 | |||
660 | static int __init rtc_init(void) | ||
661 | { | ||
662 | return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe); | ||
663 | } | ||
664 | module_init(rtc_init); | ||
665 | |||
666 | static void __exit rtc_exit(void) | ||
667 | { | ||
668 | platform_driver_unregister(&davinci_rtc_driver); | ||
669 | } | ||
670 | module_exit(rtc_exit); | ||
671 | |||
672 | MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>"); | ||
673 | MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver"); | ||
674 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 532acf9b05d8..359d1e04626c 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <asm/rtc.h> | ||
20 | 19 | ||
21 | #define DRV_NAME "rtc-ds1302" | 20 | #define DRV_NAME "rtc-ds1302" |
22 | #define DRV_VERSION "0.1.1" | 21 | #define DRV_VERSION "0.1.1" |
@@ -34,14 +33,55 @@ | |||
34 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | 33 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ |
35 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | 34 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ |
36 | 35 | ||
36 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
37 | #include <asm/rtc.h> | ||
38 | #include <mach/snapgear.h> | ||
39 | |||
37 | #define RTC_RESET 0x1000 | 40 | #define RTC_RESET 0x1000 |
38 | #define RTC_IODATA 0x0800 | 41 | #define RTC_IODATA 0x0800 |
39 | #define RTC_SCLK 0x0400 | 42 | #define RTC_SCLK 0x0400 |
40 | 43 | ||
41 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
42 | #include <mach/snapgear.h> | ||
43 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | 44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) |
44 | #define get_dp() SECUREEDGE_READ_IOPORT() | 45 | #define get_dp() SECUREEDGE_READ_IOPORT() |
46 | #define ds1302_set_tx() | ||
47 | #define ds1302_set_rx() | ||
48 | |||
49 | static inline int ds1302_hw_init(void) | ||
50 | { | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static inline void ds1302_reset(void) | ||
55 | { | ||
56 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
57 | } | ||
58 | |||
59 | static inline void ds1302_clock(void) | ||
60 | { | ||
61 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
62 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
63 | } | ||
64 | |||
65 | static inline void ds1302_start(void) | ||
66 | { | ||
67 | set_dp(get_dp() | RTC_RESET); | ||
68 | } | ||
69 | |||
70 | static inline void ds1302_stop(void) | ||
71 | { | ||
72 | set_dp(get_dp() & ~RTC_RESET); | ||
73 | } | ||
74 | |||
75 | static inline void ds1302_txbit(int bit) | ||
76 | { | ||
77 | set_dp((get_dp() & ~RTC_IODATA) | (bit ? RTC_IODATA : 0)); | ||
78 | } | ||
79 | |||
80 | static inline int ds1302_rxbit(void) | ||
81 | { | ||
82 | return !!(get_dp() & RTC_IODATA); | ||
83 | } | ||
84 | |||
45 | #else | 85 | #else |
46 | #error "Add support for your platform" | 86 | #error "Add support for your platform" |
47 | #endif | 87 | #endif |
@@ -50,11 +90,11 @@ static void ds1302_sendbits(unsigned int val) | |||
50 | { | 90 | { |
51 | int i; | 91 | int i; |
52 | 92 | ||
93 | ds1302_set_tx(); | ||
94 | |||
53 | for (i = 8; (i); i--, val >>= 1) { | 95 | for (i = 8; (i); i--, val >>= 1) { |
54 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | 96 | ds1302_txbit(val & 0x1); |
55 | RTC_IODATA : 0)); | 97 | ds1302_clock(); |
56 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
57 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
58 | } | 98 | } |
59 | } | 99 | } |
60 | 100 | ||
@@ -63,10 +103,11 @@ static unsigned int ds1302_recvbits(void) | |||
63 | unsigned int val; | 103 | unsigned int val; |
64 | int i; | 104 | int i; |
65 | 105 | ||
106 | ds1302_set_rx(); | ||
107 | |||
66 | for (i = 0, val = 0; (i < 8); i++) { | 108 | for (i = 0, val = 0; (i < 8); i++) { |
67 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | 109 | val |= (ds1302_rxbit() << i); |
68 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | 110 | ds1302_clock(); |
69 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
70 | } | 111 | } |
71 | 112 | ||
72 | return val; | 113 | return val; |
@@ -76,23 +117,24 @@ static unsigned int ds1302_readbyte(unsigned int addr) | |||
76 | { | 117 | { |
77 | unsigned int val; | 118 | unsigned int val; |
78 | 119 | ||
79 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 120 | ds1302_reset(); |
80 | 121 | ||
81 | set_dp(get_dp() | RTC_RESET); | 122 | ds1302_start(); |
82 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | 123 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); |
83 | val = ds1302_recvbits(); | 124 | val = ds1302_recvbits(); |
84 | set_dp(get_dp() & ~RTC_RESET); | 125 | ds1302_stop(); |
85 | 126 | ||
86 | return val; | 127 | return val; |
87 | } | 128 | } |
88 | 129 | ||
89 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | 130 | static void ds1302_writebyte(unsigned int addr, unsigned int val) |
90 | { | 131 | { |
91 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 132 | ds1302_reset(); |
92 | set_dp(get_dp() | RTC_RESET); | 133 | |
134 | ds1302_start(); | ||
93 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | 135 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); |
94 | ds1302_sendbits(val); | 136 | ds1302_sendbits(val); |
95 | set_dp(get_dp() & ~RTC_RESET); | 137 | ds1302_stop(); |
96 | } | 138 | } |
97 | 139 | ||
98 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | 140 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -167,13 +209,20 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev) | |||
167 | { | 209 | { |
168 | struct rtc_device *rtc; | 210 | struct rtc_device *rtc; |
169 | 211 | ||
212 | if (ds1302_hw_init()) { | ||
213 | dev_err(&pdev->dev, "Failed to init communication channel"); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
170 | /* Reset */ | 217 | /* Reset */ |
171 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 218 | ds1302_reset(); |
172 | 219 | ||
173 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ | 220 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ |
174 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | 221 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); |
175 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | 222 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) { |
223 | dev_err(&pdev->dev, "Failed to probe"); | ||
176 | return -ENODEV; | 224 | return -ENODEV; |
225 | } | ||
177 | 226 | ||
178 | rtc = rtc_device_register("ds1302", &pdev->dev, | 227 | rtc = rtc_device_register("ds1302", &pdev->dev, |
179 | &ds1302_rtc_ops, THIS_MODULE); | 228 | &ds1302_rtc_ops, THIS_MODULE); |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 7836c9cec557..48da85e97ca4 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -542,7 +542,8 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, | |||
542 | } | 542 | } |
543 | 543 | ||
544 | static ssize_t | 544 | static ssize_t |
545 | ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 545 | ds1305_nvram_read(struct file *filp, struct kobject *kobj, |
546 | struct bin_attribute *attr, | ||
546 | char *buf, loff_t off, size_t count) | 547 | char *buf, loff_t off, size_t count) |
547 | { | 548 | { |
548 | struct spi_device *spi; | 549 | struct spi_device *spi; |
@@ -572,7 +573,8 @@ ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
572 | } | 573 | } |
573 | 574 | ||
574 | static ssize_t | 575 | static ssize_t |
575 | ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 576 | ds1305_nvram_write(struct file *filp, struct kobject *kobj, |
577 | struct bin_attribute *attr, | ||
576 | char *buf, loff_t off, size_t count) | 578 | char *buf, loff_t off, size_t count) |
577 | { | 579 | { |
578 | struct spi_device *spi; | 580 | struct spi_device *spi; |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index c4ec5c158aa1..d827ce570a8c 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -556,7 +556,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { | |||
556 | #define NVRAM_SIZE 56 | 556 | #define NVRAM_SIZE 56 |
557 | 557 | ||
558 | static ssize_t | 558 | static ssize_t |
559 | ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 559 | ds1307_nvram_read(struct file *filp, struct kobject *kobj, |
560 | struct bin_attribute *attr, | ||
560 | char *buf, loff_t off, size_t count) | 561 | char *buf, loff_t off, size_t count) |
561 | { | 562 | { |
562 | struct i2c_client *client; | 563 | struct i2c_client *client; |
@@ -580,7 +581,8 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
580 | } | 581 | } |
581 | 582 | ||
582 | static ssize_t | 583 | static ssize_t |
583 | ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 584 | ds1307_nvram_write(struct file *filp, struct kobject *kobj, |
585 | struct bin_attribute *attr, | ||
584 | char *buf, loff_t off, size_t count) | 586 | char *buf, loff_t off, size_t count) |
585 | { | 587 | { |
586 | struct i2c_client *client; | 588 | struct i2c_client *client; |
@@ -775,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
775 | 777 | ||
776 | read_rtc: | 778 | read_rtc: |
777 | /* read RTC registers */ | 779 | /* read RTC registers */ |
778 | tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); | 780 | tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf); |
779 | if (tmp != 8) { | 781 | if (tmp != 8) { |
780 | pr_debug("read error %d\n", tmp); | 782 | pr_debug("read error %d\n", tmp); |
781 | err = -EIO; | 783 | err = -EIO; |
@@ -860,7 +862,7 @@ read_rtc: | |||
860 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | 862 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) |
861 | tmp += 12; | 863 | tmp += 12; |
862 | i2c_smbus_write_byte_data(client, | 864 | i2c_smbus_write_byte_data(client, |
863 | DS1307_REG_HOUR, | 865 | ds1307->offset + DS1307_REG_HOUR, |
864 | bin2bcd(tmp)); | 866 | bin2bcd(tmp)); |
865 | } | 867 | } |
866 | 868 | ||
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 61945734ad00..1f0007fd4431 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -403,7 +403,6 @@ out_irq: | |||
403 | free_irq(client->irq, client); | 403 | free_irq(client->irq, client); |
404 | 404 | ||
405 | out_free: | 405 | out_free: |
406 | i2c_set_clientdata(client, NULL); | ||
407 | kfree(ds1374); | 406 | kfree(ds1374); |
408 | return ret; | 407 | return ret; |
409 | } | 408 | } |
@@ -422,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
422 | } | 421 | } |
423 | 422 | ||
424 | rtc_device_unregister(ds1374->rtc); | 423 | rtc_device_unregister(ds1374->rtc); |
425 | i2c_set_clientdata(client, NULL); | ||
426 | kfree(ds1374); | 424 | kfree(ds1374); |
427 | return 0; | 425 | return 0; |
428 | } | 426 | } |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 06b8566c4532..37268e97de49 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -423,8 +423,9 @@ static const struct rtc_class_ops ds1511_rtc_ops = { | |||
423 | }; | 423 | }; |
424 | 424 | ||
425 | static ssize_t | 425 | static ssize_t |
426 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | 426 | ds1511_nvram_read(struct file *filp, struct kobject *kobj, |
427 | char *buf, loff_t pos, size_t size) | 427 | struct bin_attribute *ba, |
428 | char *buf, loff_t pos, size_t size) | ||
428 | { | 429 | { |
429 | ssize_t count; | 430 | ssize_t count; |
430 | 431 | ||
@@ -452,8 +453,9 @@ ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | |||
452 | } | 453 | } |
453 | 454 | ||
454 | static ssize_t | 455 | static ssize_t |
455 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | 456 | ds1511_nvram_write(struct file *filp, struct kobject *kobj, |
456 | char *buf, loff_t pos, size_t size) | 457 | struct bin_attribute *bin_attr, |
458 | char *buf, loff_t pos, size_t size) | ||
457 | { | 459 | { |
458 | ssize_t count; | 460 | ssize_t count; |
459 | 461 | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 244f9994bcbb..ff432e2ca275 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -252,7 +252,7 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
252 | .update_irq_enable = ds1553_rtc_update_irq_enable, | 252 | .update_irq_enable = ds1553_rtc_update_irq_enable, |
253 | }; | 253 | }; |
254 | 254 | ||
255 | static ssize_t ds1553_nvram_read(struct kobject *kobj, | 255 | static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, |
256 | struct bin_attribute *bin_attr, | 256 | struct bin_attribute *bin_attr, |
257 | char *buf, loff_t pos, size_t size) | 257 | char *buf, loff_t pos, size_t size) |
258 | { | 258 | { |
@@ -267,7 +267,7 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, | |||
267 | return count; | 267 | return count; |
268 | } | 268 | } |
269 | 269 | ||
270 | static ssize_t ds1553_nvram_write(struct kobject *kobj, | 270 | static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, |
271 | struct bin_attribute *bin_attr, | 271 | struct bin_attribute *bin_attr, |
272 | char *buf, loff_t pos, size_t size) | 272 | char *buf, loff_t pos, size_t size) |
273 | { | 273 | { |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 2b4b0bc42d6f..042630c90dd3 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -128,7 +128,7 @@ static const struct rtc_class_ops ds1742_rtc_ops = { | |||
128 | .set_time = ds1742_rtc_set_time, | 128 | .set_time = ds1742_rtc_set_time, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static ssize_t ds1742_nvram_read(struct kobject *kobj, | 131 | static ssize_t ds1742_nvram_read(struct file *filp, 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 | { |
@@ -143,7 +143,7 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, | |||
143 | return count; | 143 | return count; |
144 | } | 144 | } |
145 | 145 | ||
146 | static ssize_t ds1742_nvram_write(struct kobject *kobj, | 146 | static ssize_t ds1742_nvram_write(struct file *filp, 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 | { |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c new file mode 100644 index 000000000000..9daed8db83d3 --- /dev/null +++ b/drivers/rtc/rtc-ds3232.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | /* | ||
12 | * It would be more efficient to use i2c msgs/i2c_transfer directly but, as | ||
13 | * recommened in .../Documentation/i2c/writing-clients section | ||
14 | * "Sending and receiving", using SMBus level communication is preferred. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/bcd.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define DS3232_REG_SECONDS 0x00 | ||
27 | #define DS3232_REG_MINUTES 0x01 | ||
28 | #define DS3232_REG_HOURS 0x02 | ||
29 | #define DS3232_REG_AMPM 0x02 | ||
30 | #define DS3232_REG_DAY 0x03 | ||
31 | #define DS3232_REG_DATE 0x04 | ||
32 | #define DS3232_REG_MONTH 0x05 | ||
33 | #define DS3232_REG_CENTURY 0x05 | ||
34 | #define DS3232_REG_YEAR 0x06 | ||
35 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ | ||
36 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ | ||
37 | #define DS3232_REG_CR 0x0E /* Control register */ | ||
38 | # define DS3232_REG_CR_nEOSC 0x80 | ||
39 | # define DS3232_REG_CR_INTCN 0x04 | ||
40 | # define DS3232_REG_CR_A2IE 0x02 | ||
41 | # define DS3232_REG_CR_A1IE 0x01 | ||
42 | |||
43 | #define DS3232_REG_SR 0x0F /* control/status register */ | ||
44 | # define DS3232_REG_SR_OSF 0x80 | ||
45 | # define DS3232_REG_SR_BSY 0x04 | ||
46 | # define DS3232_REG_SR_A2F 0x02 | ||
47 | # define DS3232_REG_SR_A1F 0x01 | ||
48 | |||
49 | struct ds3232 { | ||
50 | struct i2c_client *client; | ||
51 | struct rtc_device *rtc; | ||
52 | struct work_struct work; | ||
53 | |||
54 | /* The mutex protects alarm operations, and prevents a race | ||
55 | * between the enable_irq() in the workqueue and the free_irq() | ||
56 | * in the remove function. | ||
57 | */ | ||
58 | struct mutex mutex; | ||
59 | int exiting; | ||
60 | }; | ||
61 | |||
62 | static struct i2c_driver ds3232_driver; | ||
63 | |||
64 | static int ds3232_check_rtc_status(struct i2c_client *client) | ||
65 | { | ||
66 | int ret = 0; | ||
67 | int control, stat; | ||
68 | |||
69 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
70 | if (stat < 0) | ||
71 | return stat; | ||
72 | |||
73 | if (stat & DS3232_REG_SR_OSF) | ||
74 | dev_warn(&client->dev, | ||
75 | "oscillator discontinuity flagged, " | ||
76 | "time unreliable\n"); | ||
77 | |||
78 | stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
79 | |||
80 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | /* If the alarm is pending, clear it before requesting | ||
85 | * the interrupt, so an interrupt event isn't reported | ||
86 | * before everything is initialized. | ||
87 | */ | ||
88 | |||
89 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
90 | if (control < 0) | ||
91 | return control; | ||
92 | |||
93 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
94 | control |= DS3232_REG_CR_INTCN; | ||
95 | |||
96 | return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
97 | } | ||
98 | |||
99 | static int ds3232_read_time(struct device *dev, struct rtc_time *time) | ||
100 | { | ||
101 | struct i2c_client *client = to_i2c_client(dev); | ||
102 | int ret; | ||
103 | u8 buf[7]; | ||
104 | unsigned int year, month, day, hour, minute, second; | ||
105 | unsigned int week, twelve_hr, am_pm; | ||
106 | unsigned int century, add_century = 0; | ||
107 | |||
108 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf); | ||
109 | |||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | if (ret < 7) | ||
113 | return -EIO; | ||
114 | |||
115 | second = buf[0]; | ||
116 | minute = buf[1]; | ||
117 | hour = buf[2]; | ||
118 | week = buf[3]; | ||
119 | day = buf[4]; | ||
120 | month = buf[5]; | ||
121 | year = buf[6]; | ||
122 | |||
123 | /* Extract additional information for AM/PM and century */ | ||
124 | |||
125 | twelve_hr = hour & 0x40; | ||
126 | am_pm = hour & 0x20; | ||
127 | century = month & 0x80; | ||
128 | |||
129 | /* Write to rtc_time structure */ | ||
130 | |||
131 | time->tm_sec = bcd2bin(second); | ||
132 | time->tm_min = bcd2bin(minute); | ||
133 | if (twelve_hr) { | ||
134 | /* Convert to 24 hr */ | ||
135 | if (am_pm) | ||
136 | time->tm_hour = bcd2bin(hour & 0x1F) + 12; | ||
137 | else | ||
138 | time->tm_hour = bcd2bin(hour & 0x1F); | ||
139 | } else { | ||
140 | time->tm_hour = bcd2bin(hour); | ||
141 | } | ||
142 | |||
143 | time->tm_wday = bcd2bin(week); | ||
144 | time->tm_mday = bcd2bin(day); | ||
145 | time->tm_mon = bcd2bin(month & 0x7F); | ||
146 | if (century) | ||
147 | add_century = 100; | ||
148 | |||
149 | time->tm_year = bcd2bin(year) + add_century; | ||
150 | |||
151 | return rtc_valid_tm(time); | ||
152 | } | ||
153 | |||
154 | static int ds3232_set_time(struct device *dev, struct rtc_time *time) | ||
155 | { | ||
156 | struct i2c_client *client = to_i2c_client(dev); | ||
157 | u8 buf[7]; | ||
158 | |||
159 | /* Extract time from rtc_time and load into ds3232*/ | ||
160 | |||
161 | buf[0] = bin2bcd(time->tm_sec); | ||
162 | buf[1] = bin2bcd(time->tm_min); | ||
163 | buf[2] = bin2bcd(time->tm_hour); | ||
164 | buf[3] = bin2bcd(time->tm_wday); /* Day of the week */ | ||
165 | buf[4] = bin2bcd(time->tm_mday); /* Date */ | ||
166 | buf[5] = bin2bcd(time->tm_mon); | ||
167 | if (time->tm_year >= 100) { | ||
168 | buf[5] |= 0x80; | ||
169 | buf[6] = bin2bcd(time->tm_year - 100); | ||
170 | } else { | ||
171 | buf[6] = bin2bcd(time->tm_year); | ||
172 | } | ||
173 | |||
174 | return i2c_smbus_write_i2c_block_data(client, | ||
175 | DS3232_REG_SECONDS, 7, buf); | ||
176 | } | ||
177 | |||
178 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | ||
179 | { | ||
180 | struct i2c_client *client = dev_id; | ||
181 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
182 | |||
183 | disable_irq_nosync(irq); | ||
184 | schedule_work(&ds3232->work); | ||
185 | return IRQ_HANDLED; | ||
186 | } | ||
187 | |||
188 | static void ds3232_work(struct work_struct *work) | ||
189 | { | ||
190 | struct ds3232 *ds3232 = container_of(work, struct ds3232, work); | ||
191 | struct i2c_client *client = ds3232->client; | ||
192 | int stat, control; | ||
193 | |||
194 | mutex_lock(&ds3232->mutex); | ||
195 | |||
196 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
197 | if (stat < 0) | ||
198 | goto unlock; | ||
199 | |||
200 | if (stat & DS3232_REG_SR_A1F) { | ||
201 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
202 | if (control < 0) | ||
203 | goto out; | ||
204 | /* disable alarm1 interrupt */ | ||
205 | control &= ~(DS3232_REG_CR_A1IE); | ||
206 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
207 | |||
208 | /* clear the alarm pend flag */ | ||
209 | stat &= ~DS3232_REG_SR_A1F; | ||
210 | i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
211 | |||
212 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); | ||
213 | } | ||
214 | |||
215 | out: | ||
216 | if (!ds3232->exiting) | ||
217 | enable_irq(client->irq); | ||
218 | unlock: | ||
219 | mutex_unlock(&ds3232->mutex); | ||
220 | } | ||
221 | |||
222 | static const struct rtc_class_ops ds3232_rtc_ops = { | ||
223 | .read_time = ds3232_read_time, | ||
224 | .set_time = ds3232_set_time, | ||
225 | }; | ||
226 | |||
227 | static int __devinit ds3232_probe(struct i2c_client *client, | ||
228 | const struct i2c_device_id *id) | ||
229 | { | ||
230 | struct ds3232 *ds3232; | ||
231 | int ret; | ||
232 | |||
233 | ds3232 = kzalloc(sizeof(struct ds3232), GFP_KERNEL); | ||
234 | if (!ds3232) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | ds3232->client = client; | ||
238 | i2c_set_clientdata(client, ds3232); | ||
239 | |||
240 | INIT_WORK(&ds3232->work, ds3232_work); | ||
241 | mutex_init(&ds3232->mutex); | ||
242 | |||
243 | ret = ds3232_check_rtc_status(client); | ||
244 | if (ret) | ||
245 | goto out_free; | ||
246 | |||
247 | ds3232->rtc = rtc_device_register(client->name, &client->dev, | ||
248 | &ds3232_rtc_ops, THIS_MODULE); | ||
249 | if (IS_ERR(ds3232->rtc)) { | ||
250 | ret = PTR_ERR(ds3232->rtc); | ||
251 | dev_err(&client->dev, "unable to register the class device\n"); | ||
252 | goto out_irq; | ||
253 | } | ||
254 | |||
255 | if (client->irq >= 0) { | ||
256 | ret = request_irq(client->irq, ds3232_irq, 0, | ||
257 | "ds3232", client); | ||
258 | if (ret) { | ||
259 | dev_err(&client->dev, "unable to request IRQ\n"); | ||
260 | goto out_free; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | |||
266 | out_irq: | ||
267 | if (client->irq >= 0) | ||
268 | free_irq(client->irq, client); | ||
269 | |||
270 | out_free: | ||
271 | i2c_set_clientdata(client, NULL); | ||
272 | kfree(ds3232); | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | static int __devexit ds3232_remove(struct i2c_client *client) | ||
277 | { | ||
278 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
279 | |||
280 | if (client->irq >= 0) { | ||
281 | mutex_lock(&ds3232->mutex); | ||
282 | ds3232->exiting = 1; | ||
283 | mutex_unlock(&ds3232->mutex); | ||
284 | |||
285 | free_irq(client->irq, client); | ||
286 | flush_scheduled_work(); | ||
287 | } | ||
288 | |||
289 | rtc_device_unregister(ds3232->rtc); | ||
290 | i2c_set_clientdata(client, NULL); | ||
291 | kfree(ds3232); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct i2c_device_id ds3232_id[] = { | ||
296 | { "ds3232", 0 }, | ||
297 | { } | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(i2c, ds3232_id); | ||
300 | |||
301 | static struct i2c_driver ds3232_driver = { | ||
302 | .driver = { | ||
303 | .name = "rtc-ds3232", | ||
304 | .owner = THIS_MODULE, | ||
305 | }, | ||
306 | .probe = ds3232_probe, | ||
307 | .remove = __devexit_p(ds3232_remove), | ||
308 | .id_table = ds3232_id, | ||
309 | }; | ||
310 | |||
311 | static int __init ds3232_init(void) | ||
312 | { | ||
313 | return i2c_add_driver(&ds3232_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit ds3232_exit(void) | ||
317 | { | ||
318 | i2c_del_driver(&ds3232_driver); | ||
319 | } | ||
320 | |||
321 | module_init(ds3232_init); | ||
322 | module_exit(ds3232_exit); | ||
323 | |||
324 | MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>"); | ||
325 | MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver"); | ||
326 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index ff6fce61ea41..4cf2e70c5078 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -52,8 +52,8 @@ struct fm3130 { | |||
52 | struct i2c_msg msg[4]; | 52 | struct i2c_msg msg[4]; |
53 | struct i2c_client *client; | 53 | struct i2c_client *client; |
54 | struct rtc_device *rtc; | 54 | struct rtc_device *rtc; |
55 | int alarm_valid; | ||
55 | int data_valid; | 56 | int data_valid; |
56 | int alarm; | ||
57 | }; | 57 | }; |
58 | static const struct i2c_device_id fm3130_id[] = { | 58 | static const struct i2c_device_id fm3130_id[] = { |
59 | { "fm3130", 0 }, | 59 | { "fm3130", 0 }, |
@@ -87,11 +87,7 @@ static void fm3130_rtc_mode(struct device *dev, int mode) | |||
87 | dev_dbg(dev, "invalid mode %d\n", mode); | 87 | dev_dbg(dev, "invalid mode %d\n", mode); |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | /* Checking for alarm */ | 90 | |
91 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
92 | fm3130->alarm = 1; | ||
93 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
94 | } | ||
95 | i2c_smbus_write_byte_data(fm3130->client, | 91 | i2c_smbus_write_byte_data(fm3130->client, |
96 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); | 92 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); |
97 | } | 93 | } |
@@ -104,7 +100,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) | |||
104 | if (!fm3130->data_valid) { | 100 | if (!fm3130->data_valid) { |
105 | /* We have invalid data in RTC, probably due | 101 | /* We have invalid data in RTC, probably due |
106 | to battery faults or other problems. Return EIO | 102 | to battery faults or other problems. Return EIO |
107 | for now, it will allow us to set data later insted | 103 | for now, it will allow us to set data later instead |
108 | of error during probing which disables device */ | 104 | of error during probing which disables device */ |
109 | return -EIO; | 105 | return -EIO; |
110 | } | 106 | } |
@@ -208,6 +204,17 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
208 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | 204 | struct fm3130 *fm3130 = dev_get_drvdata(dev); |
209 | int tmp; | 205 | int tmp; |
210 | struct rtc_time *tm = &alrm->time; | 206 | struct rtc_time *tm = &alrm->time; |
207 | |||
208 | if (!fm3130->alarm_valid) { | ||
209 | /* | ||
210 | * We have invalid alarm in RTC, probably due to battery faults | ||
211 | * or other problems. Return EIO for now, it will allow us to | ||
212 | * set alarm value later instead of error during probing which | ||
213 | * disables device | ||
214 | */ | ||
215 | return -EIO; | ||
216 | } | ||
217 | |||
211 | /* read the RTC alarm registers all at once */ | 218 | /* read the RTC alarm registers all at once */ |
212 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), | 219 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), |
213 | &fm3130->msg[2], 2); | 220 | &fm3130->msg[2], 2); |
@@ -222,20 +229,31 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
222 | fm3130->regs[FM3130_ALARM_DATE], | 229 | fm3130->regs[FM3130_ALARM_DATE], |
223 | fm3130->regs[FM3130_ALARM_MONTHS]); | 230 | fm3130->regs[FM3130_ALARM_MONTHS]); |
224 | 231 | ||
225 | |||
226 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); | 232 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); |
227 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); | 233 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); |
228 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); | 234 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); |
229 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); | 235 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); |
230 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); | 236 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); |
237 | |||
231 | if (tm->tm_mon > 0) | 238 | if (tm->tm_mon > 0) |
232 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ | 239 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ |
240 | |||
233 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 241 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
234 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 242 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
235 | "read alarm", tm->tm_sec, tm->tm_min, | 243 | "read alarm", tm->tm_sec, tm->tm_min, |
236 | tm->tm_hour, tm->tm_mday, | 244 | tm->tm_hour, tm->tm_mday, |
237 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 245 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
238 | 246 | ||
247 | /* check if alarm enabled */ | ||
248 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
249 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
250 | |||
251 | if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) && | ||
252 | (~fm3130->regs[FM3130_RTC_CONTROL] & | ||
253 | FM3130_RTC_CONTROL_BIT_CAL)) { | ||
254 | alrm->enabled = 1; | ||
255 | } | ||
256 | |||
239 | return 0; | 257 | return 0; |
240 | } | 258 | } |
241 | 259 | ||
@@ -251,25 +269,20 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
251 | tm->tm_hour, tm->tm_mday, | 269 | tm->tm_hour, tm->tm_mday, |
252 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 270 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
253 | 271 | ||
254 | if (tm->tm_sec != -1) | 272 | fm3130->regs[FM3130_ALARM_SECONDS] = |
255 | fm3130->regs[FM3130_ALARM_SECONDS] = | 273 | (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80; |
256 | bin2bcd(tm->tm_sec) | 0x80; | ||
257 | 274 | ||
258 | if (tm->tm_min != -1) | 275 | fm3130->regs[FM3130_ALARM_MINUTES] = |
259 | fm3130->regs[FM3130_ALARM_MINUTES] = | 276 | (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80; |
260 | bin2bcd(tm->tm_min) | 0x80; | ||
261 | 277 | ||
262 | if (tm->tm_hour != -1) | 278 | fm3130->regs[FM3130_ALARM_HOURS] = |
263 | fm3130->regs[FM3130_ALARM_HOURS] = | 279 | (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80; |
264 | bin2bcd(tm->tm_hour) | 0x80; | ||
265 | 280 | ||
266 | if (tm->tm_mday != -1) | 281 | fm3130->regs[FM3130_ALARM_DATE] = |
267 | fm3130->regs[FM3130_ALARM_DATE] = | 282 | (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80; |
268 | bin2bcd(tm->tm_mday) | 0x80; | ||
269 | 283 | ||
270 | if (tm->tm_mon != -1) | 284 | fm3130->regs[FM3130_ALARM_MONTHS] = |
271 | fm3130->regs[FM3130_ALARM_MONTHS] = | 285 | (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80; |
272 | bin2bcd(tm->tm_mon + 1) | 0x80; | ||
273 | 286 | ||
274 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", | 287 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", |
275 | fm3130->regs[FM3130_ALARM_SECONDS], | 288 | fm3130->regs[FM3130_ALARM_SECONDS], |
@@ -285,11 +298,8 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
285 | } | 298 | } |
286 | fm3130->regs[FM3130_RTC_CONTROL] = | 299 | fm3130->regs[FM3130_RTC_CONTROL] = |
287 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | 300 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); |
288 | /* Checking for alarm */ | 301 | |
289 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | 302 | /* enable or disable alarm */ |
290 | fm3130->alarm = 1; | ||
291 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
292 | } | ||
293 | if (alrm->enabled) { | 303 | if (alrm->enabled) { |
294 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 304 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
295 | (fm3130->regs[FM3130_RTC_CONTROL] & | 305 | (fm3130->regs[FM3130_RTC_CONTROL] & |
@@ -298,16 +308,55 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
298 | } else { | 308 | } else { |
299 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 309 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
300 | fm3130->regs[FM3130_RTC_CONTROL] & | 310 | fm3130->regs[FM3130_RTC_CONTROL] & |
301 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | 311 | ~(FM3130_RTC_CONTROL_BIT_CAL) & |
312 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
302 | } | 313 | } |
314 | |||
315 | /* We assume here that data is valid once written */ | ||
316 | if (!fm3130->alarm_valid) | ||
317 | fm3130->alarm_valid = 1; | ||
318 | |||
303 | return 0; | 319 | return 0; |
304 | } | 320 | } |
305 | 321 | ||
322 | static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
323 | { | ||
324 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | ||
325 | int ret = 0; | ||
326 | |||
327 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
328 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
329 | |||
330 | dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n", | ||
331 | enabled, fm3130->regs[FM3130_RTC_CONTROL]); | ||
332 | |||
333 | switch (enabled) { | ||
334 | case 0: /* alarm off */ | ||
335 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
336 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] & | ||
337 | ~(FM3130_RTC_CONTROL_BIT_CAL) & | ||
338 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
339 | break; | ||
340 | case 1: /* alarm on */ | ||
341 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
342 | FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] & | ||
343 | ~(FM3130_RTC_CONTROL_BIT_CAL)) | | ||
344 | FM3130_RTC_CONTROL_BIT_AEN); | ||
345 | break; | ||
346 | default: | ||
347 | ret = -EINVAL; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
306 | static const struct rtc_class_ops fm3130_rtc_ops = { | 354 | static const struct rtc_class_ops fm3130_rtc_ops = { |
307 | .read_time = fm3130_get_time, | 355 | .read_time = fm3130_get_time, |
308 | .set_time = fm3130_set_time, | 356 | .set_time = fm3130_set_time, |
309 | .read_alarm = fm3130_read_alarm, | 357 | .read_alarm = fm3130_read_alarm, |
310 | .set_alarm = fm3130_set_alarm, | 358 | .set_alarm = fm3130_set_alarm, |
359 | .alarm_irq_enable = fm3130_alarm_irq_enable, | ||
311 | }; | 360 | }; |
312 | 361 | ||
313 | static struct i2c_driver fm3130_driver; | 362 | static struct i2c_driver fm3130_driver; |
@@ -356,6 +405,7 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
356 | fm3130->msg[3].len = FM3130_ALARM_REGS; | 405 | fm3130->msg[3].len = FM3130_ALARM_REGS; |
357 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; | 406 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; |
358 | 407 | ||
408 | fm3130->alarm_valid = 0; | ||
359 | fm3130->data_valid = 0; | 409 | fm3130->data_valid = 0; |
360 | 410 | ||
361 | tmp = i2c_transfer(adapter, fm3130->msg, 4); | 411 | tmp = i2c_transfer(adapter, fm3130->msg, 4); |
@@ -370,12 +420,6 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
370 | fm3130->regs[FM3130_CAL_CONTROL] = | 420 | fm3130->regs[FM3130_CAL_CONTROL] = |
371 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); | 421 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); |
372 | 422 | ||
373 | /* Checking for alarm */ | ||
374 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
375 | fm3130->alarm = 1; | ||
376 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
377 | } | ||
378 | |||
379 | /* Disabling calibration mode */ | 423 | /* Disabling calibration mode */ |
380 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { | 424 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { |
381 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 425 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
@@ -400,44 +444,79 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
400 | fm3130->regs[FM3130_CAL_CONTROL] & | 444 | fm3130->regs[FM3130_CAL_CONTROL] & |
401 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); | 445 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); |
402 | 446 | ||
403 | /* oscillator fault? clear flag, and warn */ | 447 | /* low battery? clear flag, and warn */ |
404 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) | 448 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) { |
449 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | ||
450 | fm3130->regs[FM3130_RTC_CONTROL] & | ||
451 | ~(FM3130_RTC_CONTROL_BIT_LB)); | ||
405 | dev_warn(&client->dev, "Low battery!\n"); | 452 | dev_warn(&client->dev, "Low battery!\n"); |
453 | } | ||
406 | 454 | ||
407 | /* oscillator fault? clear flag, and warn */ | 455 | /* check if Power On Reset bit is set */ |
408 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { | 456 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { |
409 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 457 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
410 | fm3130->regs[FM3130_RTC_CONTROL] & | 458 | fm3130->regs[FM3130_RTC_CONTROL] & |
411 | ~FM3130_RTC_CONTROL_BIT_POR); | 459 | ~FM3130_RTC_CONTROL_BIT_POR); |
412 | dev_warn(&client->dev, "SET TIME!\n"); | 460 | dev_dbg(&client->dev, "POR bit is set\n"); |
413 | } | 461 | } |
414 | /* ACS is controlled by alarm */ | 462 | /* ACS is controlled by alarm */ |
415 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); | 463 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); |
416 | 464 | ||
417 | /* TODO */ | 465 | /* alarm registers sanity check */ |
418 | /* TODO need to sanity check alarm */ | 466 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); |
419 | tmp = fm3130->regs[FM3130_RTC_SECONDS]; | 467 | if (tmp > 59) |
420 | tmp = bcd2bin(tmp & 0x7f); | 468 | goto bad_alarm; |
421 | if (tmp > 60) | 469 | |
422 | goto exit_bad; | ||
423 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 470 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
424 | if (tmp > 60) | 471 | if (tmp > 59) |
425 | goto exit_bad; | 472 | goto bad_alarm; |
473 | |||
474 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
475 | if (tmp > 23) | ||
476 | goto bad_alarm; | ||
426 | 477 | ||
427 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | 478 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); |
428 | if (tmp == 0 || tmp > 31) | 479 | if (tmp == 0 || tmp > 31) |
429 | goto exit_bad; | 480 | goto bad_alarm; |
430 | 481 | ||
431 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | 482 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); |
432 | if (tmp == 0 || tmp > 12) | 483 | if (tmp == 0 || tmp > 12) |
433 | goto exit_bad; | 484 | goto bad_alarm; |
434 | 485 | ||
435 | tmp = fm3130->regs[FM3130_RTC_HOURS]; | 486 | fm3130->alarm_valid = 1; |
487 | |||
488 | bad_alarm: | ||
489 | |||
490 | /* clock registers sanity chek */ | ||
491 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); | ||
492 | if (tmp > 59) | ||
493 | goto bad_clock; | ||
494 | |||
495 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | ||
496 | if (tmp > 59) | ||
497 | goto bad_clock; | ||
498 | |||
499 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
500 | if (tmp > 23) | ||
501 | goto bad_clock; | ||
502 | |||
503 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7); | ||
504 | if (tmp == 0 || tmp > 7) | ||
505 | goto bad_clock; | ||
506 | |||
507 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | ||
508 | if (tmp == 0 || tmp > 31) | ||
509 | goto bad_clock; | ||
510 | |||
511 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | ||
512 | if (tmp == 0 || tmp > 12) | ||
513 | goto bad_clock; | ||
436 | 514 | ||
437 | fm3130->data_valid = 1; | 515 | fm3130->data_valid = 1; |
438 | 516 | ||
439 | exit_bad: | 517 | bad_clock: |
440 | if (!fm3130->data_valid) | 518 | |
519 | if (!fm3130->data_valid || !fm3130->alarm_valid) | ||
441 | dev_dbg(&client->dev, | 520 | dev_dbg(&client->dev, |
442 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" | 521 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" |
443 | "%02x %02x %02x %02x %02x %02x %02x\n", | 522 | "%02x %02x %02x %02x %02x %02x %02x\n", |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c new file mode 100644 index 000000000000..2dd3c0163272 --- /dev/null +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -0,0 +1,519 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * Copyright 2010 Orex Computed Radiography | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | /* based on rtc-mc13892.c */ | ||
16 | |||
17 | /* | ||
18 | * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block | ||
19 | * to implement a Linux RTC. Times and alarms are truncated to seconds. | ||
20 | * Since the RTC framework performs API locking via rtc->ops_lock the | ||
21 | * only simultaneous accesses we need to deal with is updating DryIce | ||
22 | * registers while servicing an alarm. | ||
23 | * | ||
24 | * Note that reading the DSR (DryIce Status Register) automatically clears | ||
25 | * the WCF (Write Complete Flag). All DryIce writes are synchronized to the | ||
26 | * LP (Low Power) domain and set the WCF upon completion. Writes to the | ||
27 | * DIER (DryIce Interrupt Enable Register) are the only exception. These | ||
28 | * occur at normal bus speeds and do not set WCF. Periodic interrupts are | ||
29 | * not supported by the hardware. | ||
30 | */ | ||
31 | |||
32 | #include <linux/io.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/rtc.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | |||
40 | /* DryIce Register Definitions */ | ||
41 | |||
42 | #define DTCMR 0x00 /* Time Counter MSB Reg */ | ||
43 | #define DTCLR 0x04 /* Time Counter LSB Reg */ | ||
44 | |||
45 | #define DCAMR 0x08 /* Clock Alarm MSB Reg */ | ||
46 | #define DCALR 0x0c /* Clock Alarm LSB Reg */ | ||
47 | #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */ | ||
48 | |||
49 | #define DCR 0x10 /* Control Reg */ | ||
50 | #define DCR_TCE (1 << 3) /* Time Counter Enable */ | ||
51 | |||
52 | #define DSR 0x14 /* Status Reg */ | ||
53 | #define DSR_WBF (1 << 10) /* Write Busy Flag */ | ||
54 | #define DSR_WNF (1 << 9) /* Write Next Flag */ | ||
55 | #define DSR_WCF (1 << 8) /* Write Complete Flag */ | ||
56 | #define DSR_WEF (1 << 7) /* Write Error Flag */ | ||
57 | #define DSR_CAF (1 << 4) /* Clock Alarm Flag */ | ||
58 | #define DSR_NVF (1 << 1) /* Non-Valid Flag */ | ||
59 | #define DSR_SVF (1 << 0) /* Security Violation Flag */ | ||
60 | |||
61 | #define DIER 0x18 /* Interrupt Enable Reg */ | ||
62 | #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */ | ||
63 | #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */ | ||
64 | #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */ | ||
65 | #define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */ | ||
66 | |||
67 | /** | ||
68 | * struct imxdi_dev - private imxdi rtc data | ||
69 | * @pdev: pionter to platform dev | ||
70 | * @rtc: pointer to rtc struct | ||
71 | * @ioaddr: IO registers pointer | ||
72 | * @irq: dryice normal interrupt | ||
73 | * @clk: input reference clock | ||
74 | * @dsr: copy of the DSR register | ||
75 | * @irq_lock: interrupt enable register (DIER) lock | ||
76 | * @write_wait: registers write complete queue | ||
77 | * @write_mutex: serialize registers write | ||
78 | * @work: schedule alarm work | ||
79 | */ | ||
80 | struct imxdi_dev { | ||
81 | struct platform_device *pdev; | ||
82 | struct rtc_device *rtc; | ||
83 | void __iomem *ioaddr; | ||
84 | int irq; | ||
85 | struct clk *clk; | ||
86 | u32 dsr; | ||
87 | spinlock_t irq_lock; | ||
88 | wait_queue_head_t write_wait; | ||
89 | struct mutex write_mutex; | ||
90 | struct work_struct work; | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * enable a dryice interrupt | ||
95 | */ | ||
96 | static void di_int_enable(struct imxdi_dev *imxdi, u32 intr) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | |||
100 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
101 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr, | ||
102 | imxdi->ioaddr + DIER); | ||
103 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * disable a dryice interrupt | ||
108 | */ | ||
109 | static void di_int_disable(struct imxdi_dev *imxdi, u32 intr) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | |||
113 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
114 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr, | ||
115 | imxdi->ioaddr + DIER); | ||
116 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This function attempts to clear the dryice write-error flag. | ||
121 | * | ||
122 | * A dryice write error is similar to a bus fault and should not occur in | ||
123 | * normal operation. Clearing the flag requires another write, so the root | ||
124 | * cause of the problem may need to be fixed before the flag can be cleared. | ||
125 | */ | ||
126 | static void clear_write_error(struct imxdi_dev *imxdi) | ||
127 | { | ||
128 | int cnt; | ||
129 | |||
130 | dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); | ||
131 | |||
132 | /* clear the write error flag */ | ||
133 | __raw_writel(DSR_WEF, imxdi->ioaddr + DSR); | ||
134 | |||
135 | /* wait for it to take effect */ | ||
136 | for (cnt = 0; cnt < 1000; cnt++) { | ||
137 | if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) | ||
138 | return; | ||
139 | udelay(10); | ||
140 | } | ||
141 | dev_err(&imxdi->pdev->dev, | ||
142 | "ERROR: Cannot clear write-error flag!\n"); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Write a dryice register and wait until it completes. | ||
147 | * | ||
148 | * This function uses interrupts to determine when the | ||
149 | * write has completed. | ||
150 | */ | ||
151 | static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg) | ||
152 | { | ||
153 | int ret; | ||
154 | int rc = 0; | ||
155 | |||
156 | /* serialize register writes */ | ||
157 | mutex_lock(&imxdi->write_mutex); | ||
158 | |||
159 | /* enable the write-complete interrupt */ | ||
160 | di_int_enable(imxdi, DIER_WCIE); | ||
161 | |||
162 | imxdi->dsr = 0; | ||
163 | |||
164 | /* do the register write */ | ||
165 | __raw_writel(val, imxdi->ioaddr + reg); | ||
166 | |||
167 | /* wait for the write to finish */ | ||
168 | ret = wait_event_interruptible_timeout(imxdi->write_wait, | ||
169 | imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); | ||
170 | if (ret < 0) { | ||
171 | rc = ret; | ||
172 | goto out; | ||
173 | } else if (ret == 0) { | ||
174 | dev_warn(&imxdi->pdev->dev, | ||
175 | "Write-wait timeout " | ||
176 | "val = 0x%08x reg = 0x%08x\n", val, reg); | ||
177 | } | ||
178 | |||
179 | /* check for write error */ | ||
180 | if (imxdi->dsr & DSR_WEF) { | ||
181 | clear_write_error(imxdi); | ||
182 | rc = -EIO; | ||
183 | } | ||
184 | |||
185 | out: | ||
186 | mutex_unlock(&imxdi->write_mutex); | ||
187 | |||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * read the seconds portion of the current time from the dryice time counter | ||
193 | */ | ||
194 | static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
195 | { | ||
196 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
197 | unsigned long now; | ||
198 | |||
199 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
200 | rtc_time_to_tm(now, tm); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * set the seconds portion of dryice time counter and clear the | ||
207 | * fractional part. | ||
208 | */ | ||
209 | static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
210 | { | ||
211 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
212 | int rc; | ||
213 | |||
214 | /* zero the fractional part first */ | ||
215 | rc = di_write_wait(imxdi, 0, DTCLR); | ||
216 | if (rc == 0) | ||
217 | rc = di_write_wait(imxdi, secs, DTCMR); | ||
218 | |||
219 | return rc; | ||
220 | } | ||
221 | |||
222 | static int dryice_rtc_alarm_irq_enable(struct device *dev, | ||
223 | unsigned int enabled) | ||
224 | { | ||
225 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
226 | |||
227 | if (enabled) | ||
228 | di_int_enable(imxdi, DIER_CAIE); | ||
229 | else | ||
230 | di_int_disable(imxdi, DIER_CAIE); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * read the seconds portion of the alarm register. | ||
237 | * the fractional part of the alarm register is always zero. | ||
238 | */ | ||
239 | static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
240 | { | ||
241 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
242 | u32 dcamr; | ||
243 | |||
244 | dcamr = __raw_readl(imxdi->ioaddr + DCAMR); | ||
245 | rtc_time_to_tm(dcamr, &alarm->time); | ||
246 | |||
247 | /* alarm is enabled if the interrupt is enabled */ | ||
248 | alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; | ||
249 | |||
250 | /* don't allow the DSR read to mess up DSR_WCF */ | ||
251 | mutex_lock(&imxdi->write_mutex); | ||
252 | |||
253 | /* alarm is pending if the alarm flag is set */ | ||
254 | alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; | ||
255 | |||
256 | mutex_unlock(&imxdi->write_mutex); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * set the seconds portion of dryice alarm register | ||
263 | */ | ||
264 | static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
265 | { | ||
266 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
267 | unsigned long now; | ||
268 | unsigned long alarm_time; | ||
269 | int rc; | ||
270 | |||
271 | rc = rtc_tm_to_time(&alarm->time, &alarm_time); | ||
272 | if (rc) | ||
273 | return rc; | ||
274 | |||
275 | /* don't allow setting alarm in the past */ | ||
276 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
277 | if (alarm_time < now) | ||
278 | return -EINVAL; | ||
279 | |||
280 | /* write the new alarm time */ | ||
281 | rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR); | ||
282 | if (rc) | ||
283 | return rc; | ||
284 | |||
285 | if (alarm->enabled) | ||
286 | di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */ | ||
287 | else | ||
288 | di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */ | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static struct rtc_class_ops dryice_rtc_ops = { | ||
294 | .read_time = dryice_rtc_read_time, | ||
295 | .set_mmss = dryice_rtc_set_mmss, | ||
296 | .alarm_irq_enable = dryice_rtc_alarm_irq_enable, | ||
297 | .read_alarm = dryice_rtc_read_alarm, | ||
298 | .set_alarm = dryice_rtc_set_alarm, | ||
299 | }; | ||
300 | |||
301 | /* | ||
302 | * dryice "normal" interrupt handler | ||
303 | */ | ||
304 | static irqreturn_t dryice_norm_irq(int irq, void *dev_id) | ||
305 | { | ||
306 | struct imxdi_dev *imxdi = dev_id; | ||
307 | u32 dsr, dier; | ||
308 | irqreturn_t rc = IRQ_NONE; | ||
309 | |||
310 | dier = __raw_readl(imxdi->ioaddr + DIER); | ||
311 | |||
312 | /* handle write complete and write error cases */ | ||
313 | if ((dier & DIER_WCIE)) { | ||
314 | /*If the write wait queue is empty then there is no pending | ||
315 | operations. It means the interrupt is for DryIce -Security. | ||
316 | IRQ must be returned as none.*/ | ||
317 | if (list_empty_careful(&imxdi->write_wait.task_list)) | ||
318 | return rc; | ||
319 | |||
320 | /* DSR_WCF clears itself on DSR read */ | ||
321 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
322 | if ((dsr & (DSR_WCF | DSR_WEF))) { | ||
323 | /* mask the interrupt */ | ||
324 | di_int_disable(imxdi, DIER_WCIE); | ||
325 | |||
326 | /* save the dsr value for the wait queue */ | ||
327 | imxdi->dsr |= dsr; | ||
328 | |||
329 | wake_up_interruptible(&imxdi->write_wait); | ||
330 | rc = IRQ_HANDLED; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | /* handle the alarm case */ | ||
335 | if ((dier & DIER_CAIE)) { | ||
336 | /* DSR_WCF clears itself on DSR read */ | ||
337 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
338 | if (dsr & DSR_CAF) { | ||
339 | /* mask the interrupt */ | ||
340 | di_int_disable(imxdi, DIER_CAIE); | ||
341 | |||
342 | /* finish alarm in user context */ | ||
343 | schedule_work(&imxdi->work); | ||
344 | rc = IRQ_HANDLED; | ||
345 | } | ||
346 | } | ||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * post the alarm event from user context so it can sleep | ||
352 | * on the write completion. | ||
353 | */ | ||
354 | static void dryice_work(struct work_struct *work) | ||
355 | { | ||
356 | struct imxdi_dev *imxdi = container_of(work, | ||
357 | struct imxdi_dev, work); | ||
358 | |||
359 | /* dismiss the interrupt (ignore error) */ | ||
360 | di_write_wait(imxdi, DSR_CAF, DSR); | ||
361 | |||
362 | /* pass the alarm event to the rtc framework. */ | ||
363 | rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * probe for dryice rtc device | ||
368 | */ | ||
369 | static int dryice_rtc_probe(struct platform_device *pdev) | ||
370 | { | ||
371 | struct resource *res; | ||
372 | struct imxdi_dev *imxdi; | ||
373 | int rc; | ||
374 | |||
375 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
376 | if (!res) | ||
377 | return -ENODEV; | ||
378 | |||
379 | imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); | ||
380 | if (!imxdi) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | imxdi->pdev = pdev; | ||
384 | |||
385 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
386 | pdev->name)) | ||
387 | return -EBUSY; | ||
388 | |||
389 | imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
390 | resource_size(res)); | ||
391 | if (imxdi->ioaddr == NULL) | ||
392 | return -ENOMEM; | ||
393 | |||
394 | imxdi->irq = platform_get_irq(pdev, 0); | ||
395 | if (imxdi->irq < 0) | ||
396 | return imxdi->irq; | ||
397 | |||
398 | init_waitqueue_head(&imxdi->write_wait); | ||
399 | |||
400 | INIT_WORK(&imxdi->work, dryice_work); | ||
401 | |||
402 | mutex_init(&imxdi->write_mutex); | ||
403 | |||
404 | imxdi->clk = clk_get(&pdev->dev, NULL); | ||
405 | if (IS_ERR(imxdi->clk)) | ||
406 | return PTR_ERR(imxdi->clk); | ||
407 | clk_enable(imxdi->clk); | ||
408 | |||
409 | /* | ||
410 | * Initialize dryice hardware | ||
411 | */ | ||
412 | |||
413 | /* mask all interrupts */ | ||
414 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
415 | |||
416 | rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, | ||
417 | IRQF_SHARED, pdev->name, imxdi); | ||
418 | if (rc) { | ||
419 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
420 | goto err; | ||
421 | } | ||
422 | |||
423 | /* put dryice into valid state */ | ||
424 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { | ||
425 | rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR); | ||
426 | if (rc) | ||
427 | goto err; | ||
428 | } | ||
429 | |||
430 | /* initialize alarm */ | ||
431 | rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR); | ||
432 | if (rc) | ||
433 | goto err; | ||
434 | rc = di_write_wait(imxdi, 0, DCALR); | ||
435 | if (rc) | ||
436 | goto err; | ||
437 | |||
438 | /* clear alarm flag */ | ||
439 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { | ||
440 | rc = di_write_wait(imxdi, DSR_CAF, DSR); | ||
441 | if (rc) | ||
442 | goto err; | ||
443 | } | ||
444 | |||
445 | /* the timer won't count if it has never been written to */ | ||
446 | if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { | ||
447 | rc = di_write_wait(imxdi, 0, DTCMR); | ||
448 | if (rc) | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | /* start keeping time */ | ||
453 | if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { | ||
454 | rc = di_write_wait(imxdi, | ||
455 | __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, | ||
456 | DCR); | ||
457 | if (rc) | ||
458 | goto err; | ||
459 | } | ||
460 | |||
461 | platform_set_drvdata(pdev, imxdi); | ||
462 | imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
463 | &dryice_rtc_ops, THIS_MODULE); | ||
464 | if (IS_ERR(imxdi->rtc)) { | ||
465 | rc = PTR_ERR(imxdi->rtc); | ||
466 | goto err; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | |||
471 | err: | ||
472 | clk_disable(imxdi->clk); | ||
473 | clk_put(imxdi->clk); | ||
474 | |||
475 | return rc; | ||
476 | } | ||
477 | |||
478 | static int __devexit dryice_rtc_remove(struct platform_device *pdev) | ||
479 | { | ||
480 | struct imxdi_dev *imxdi = platform_get_drvdata(pdev); | ||
481 | |||
482 | flush_work(&imxdi->work); | ||
483 | |||
484 | /* mask all interrupts */ | ||
485 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
486 | |||
487 | rtc_device_unregister(imxdi->rtc); | ||
488 | |||
489 | clk_disable(imxdi->clk); | ||
490 | clk_put(imxdi->clk); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static struct platform_driver dryice_rtc_driver = { | ||
496 | .driver = { | ||
497 | .name = "imxdi_rtc", | ||
498 | .owner = THIS_MODULE, | ||
499 | }, | ||
500 | .remove = __devexit_p(dryice_rtc_remove), | ||
501 | }; | ||
502 | |||
503 | static int __init dryice_rtc_init(void) | ||
504 | { | ||
505 | return platform_driver_probe(&dryice_rtc_driver, dryice_rtc_probe); | ||
506 | } | ||
507 | |||
508 | static void __exit dryice_rtc_exit(void) | ||
509 | { | ||
510 | platform_driver_unregister(&dryice_rtc_driver); | ||
511 | } | ||
512 | |||
513 | module_init(dryice_rtc_init); | ||
514 | module_exit(dryice_rtc_exit); | ||
515 | |||
516 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
517 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
518 | MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)"); | ||
519 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c new file mode 100644 index 000000000000..ddbc797ea6cd --- /dev/null +++ b/drivers/rtc/rtc-isl12022.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * An I2C driver for the Intersil ISL 12022 | ||
3 | * | ||
4 | * Author: Roman Fietze <roman.fietze@telemotive.de> | ||
5 | * | ||
6 | * Based on the Philips PCF8563 RTC | ||
7 | * by Alessandro Zummo <a.zummo@towertech.it>. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/bcd.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #define DRV_VERSION "0.1" | ||
20 | |||
21 | /* ISL register offsets */ | ||
22 | #define ISL12022_REG_SC 0x00 | ||
23 | #define ISL12022_REG_MN 0x01 | ||
24 | #define ISL12022_REG_HR 0x02 | ||
25 | #define ISL12022_REG_DT 0x03 | ||
26 | #define ISL12022_REG_MO 0x04 | ||
27 | #define ISL12022_REG_YR 0x05 | ||
28 | #define ISL12022_REG_DW 0x06 | ||
29 | |||
30 | #define ISL12022_REG_SR 0x07 | ||
31 | #define ISL12022_REG_INT 0x08 | ||
32 | |||
33 | /* ISL register bits */ | ||
34 | #define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */ | ||
35 | |||
36 | #define ISL12022_SR_LBAT85 (1 << 2) | ||
37 | #define ISL12022_SR_LBAT75 (1 << 1) | ||
38 | |||
39 | #define ISL12022_INT_WRTC (1 << 6) | ||
40 | |||
41 | |||
42 | static struct i2c_driver isl12022_driver; | ||
43 | |||
44 | struct isl12022 { | ||
45 | struct rtc_device *rtc; | ||
46 | |||
47 | bool write_enabled; /* true if write enable is set */ | ||
48 | }; | ||
49 | |||
50 | |||
51 | static int isl12022_read_regs(struct i2c_client *client, uint8_t reg, | ||
52 | uint8_t *data, size_t n) | ||
53 | { | ||
54 | struct i2c_msg msgs[] = { | ||
55 | { | ||
56 | .addr = client->addr, | ||
57 | .flags = 0, | ||
58 | .len = 1, | ||
59 | .buf = data | ||
60 | }, /* setup read ptr */ | ||
61 | { | ||
62 | .addr = client->addr, | ||
63 | .flags = I2C_M_RD, | ||
64 | .len = n, | ||
65 | .buf = data | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | int ret; | ||
70 | |||
71 | data[0] = reg; | ||
72 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
73 | if (ret != ARRAY_SIZE(msgs)) { | ||
74 | dev_err(&client->dev, "%s: read error, ret=%d\n", | ||
75 | __func__, ret); | ||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | |||
83 | static int isl12022_write_reg(struct i2c_client *client, | ||
84 | uint8_t reg, uint8_t val) | ||
85 | { | ||
86 | uint8_t data[2] = { reg, val }; | ||
87 | int err; | ||
88 | |||
89 | err = i2c_master_send(client, data, sizeof(data)); | ||
90 | if (err != sizeof(data)) { | ||
91 | dev_err(&client->dev, | ||
92 | "%s: err=%d addr=%02x, data=%02x\n", | ||
93 | __func__, err, data[0], data[1]); | ||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | /* | ||
102 | * In the routines that deal directly with the isl12022 hardware, we use | ||
103 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
104 | */ | ||
105 | static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
106 | { | ||
107 | uint8_t buf[ISL12022_REG_INT + 1]; | ||
108 | int ret; | ||
109 | |||
110 | ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf)); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) { | ||
115 | dev_warn(&client->dev, | ||
116 | "voltage dropped below %u%%, " | ||
117 | "date and time is not reliable.\n", | ||
118 | buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75); | ||
119 | } | ||
120 | |||
121 | dev_dbg(&client->dev, | ||
122 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
123 | "mday=%02x, mon=%02x, year=%02x, wday=%02x, " | ||
124 | "sr=%02x, int=%02x", | ||
125 | __func__, | ||
126 | buf[ISL12022_REG_SC], | ||
127 | buf[ISL12022_REG_MN], | ||
128 | buf[ISL12022_REG_HR], | ||
129 | buf[ISL12022_REG_DT], | ||
130 | buf[ISL12022_REG_MO], | ||
131 | buf[ISL12022_REG_YR], | ||
132 | buf[ISL12022_REG_DW], | ||
133 | buf[ISL12022_REG_SR], | ||
134 | buf[ISL12022_REG_INT]); | ||
135 | |||
136 | tm->tm_sec = bcd2bin(buf[ISL12022_REG_SC] & 0x7F); | ||
137 | tm->tm_min = bcd2bin(buf[ISL12022_REG_MN] & 0x7F); | ||
138 | tm->tm_hour = bcd2bin(buf[ISL12022_REG_HR] & 0x3F); | ||
139 | tm->tm_mday = bcd2bin(buf[ISL12022_REG_DT] & 0x3F); | ||
140 | tm->tm_wday = buf[ISL12022_REG_DW] & 0x07; | ||
141 | tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1; | ||
142 | tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100; | ||
143 | |||
144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
146 | __func__, | ||
147 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
148 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
149 | |||
150 | /* The clock can give out invalid datetime, but we cannot return | ||
151 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. */ | ||
152 | if (rtc_valid_tm(tm) < 0) | ||
153 | dev_err(&client->dev, "retrieved date and time is invalid.\n"); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
159 | { | ||
160 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
161 | size_t i; | ||
162 | int ret; | ||
163 | uint8_t buf[ISL12022_REG_DW + 1]; | ||
164 | |||
165 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
166 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
167 | __func__, | ||
168 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
169 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
170 | |||
171 | if (!isl12022->write_enabled) { | ||
172 | |||
173 | ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1); | ||
174 | if (ret) | ||
175 | return ret; | ||
176 | |||
177 | /* Check if WRTC (write rtc enable) is set factory default is | ||
178 | * 0 (not set) */ | ||
179 | if (!(buf[0] & ISL12022_INT_WRTC)) { | ||
180 | dev_info(&client->dev, | ||
181 | "init write enable and 24 hour format\n"); | ||
182 | |||
183 | /* Set the write enable bit. */ | ||
184 | ret = isl12022_write_reg(client, | ||
185 | ISL12022_REG_INT, | ||
186 | buf[0] | ISL12022_INT_WRTC); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | /* Write to any RTC register to start RTC, we use the | ||
191 | * HR register, setting the MIL bit to use the 24 hour | ||
192 | * format. */ | ||
193 | ret = isl12022_read_regs(client, ISL12022_REG_HR, | ||
194 | buf, 1); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | ret = isl12022_write_reg(client, | ||
199 | ISL12022_REG_HR, | ||
200 | buf[0] | ISL12022_HR_MIL); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | isl12022->write_enabled = 1; | ||
206 | } | ||
207 | |||
208 | /* hours, minutes and seconds */ | ||
209 | buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec); | ||
210 | buf[ISL12022_REG_MN] = bin2bcd(tm->tm_min); | ||
211 | buf[ISL12022_REG_HR] = bin2bcd(tm->tm_hour) | ISL12022_HR_MIL; | ||
212 | |||
213 | buf[ISL12022_REG_DT] = bin2bcd(tm->tm_mday); | ||
214 | |||
215 | /* month, 1 - 12 */ | ||
216 | buf[ISL12022_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
217 | |||
218 | /* year and century */ | ||
219 | buf[ISL12022_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
220 | |||
221 | buf[ISL12022_REG_DW] = tm->tm_wday & 0x07; | ||
222 | |||
223 | /* write register's data */ | ||
224 | for (i = 0; i < ARRAY_SIZE(buf); i++) { | ||
225 | ret = isl12022_write_reg(client, ISL12022_REG_SC + i, | ||
226 | buf[ISL12022_REG_SC + i]); | ||
227 | if (ret) | ||
228 | return -EIO; | ||
229 | }; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
235 | { | ||
236 | return isl12022_get_datetime(to_i2c_client(dev), tm); | ||
237 | } | ||
238 | |||
239 | static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
240 | { | ||
241 | return isl12022_set_datetime(to_i2c_client(dev), tm); | ||
242 | } | ||
243 | |||
244 | static const struct rtc_class_ops isl12022_rtc_ops = { | ||
245 | .read_time = isl12022_rtc_read_time, | ||
246 | .set_time = isl12022_rtc_set_time, | ||
247 | }; | ||
248 | |||
249 | static int isl12022_probe(struct i2c_client *client, | ||
250 | const struct i2c_device_id *id) | ||
251 | { | ||
252 | struct isl12022 *isl12022; | ||
253 | |||
254 | int ret = 0; | ||
255 | |||
256 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
257 | return -ENODEV; | ||
258 | |||
259 | isl12022 = kzalloc(sizeof(struct isl12022), GFP_KERNEL); | ||
260 | if (!isl12022) | ||
261 | return -ENOMEM; | ||
262 | |||
263 | dev_dbg(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
264 | |||
265 | i2c_set_clientdata(client, isl12022); | ||
266 | |||
267 | isl12022->rtc = rtc_device_register(isl12022_driver.driver.name, | ||
268 | &client->dev, | ||
269 | &isl12022_rtc_ops, | ||
270 | THIS_MODULE); | ||
271 | |||
272 | if (IS_ERR(isl12022->rtc)) { | ||
273 | ret = PTR_ERR(isl12022->rtc); | ||
274 | goto exit_kfree; | ||
275 | } | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | exit_kfree: | ||
280 | kfree(isl12022); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int isl12022_remove(struct i2c_client *client) | ||
286 | { | ||
287 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
288 | |||
289 | rtc_device_unregister(isl12022->rtc); | ||
290 | kfree(isl12022); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct i2c_device_id isl12022_id[] = { | ||
296 | { "isl12022", 0 }, | ||
297 | { "rtc8564", 0 }, | ||
298 | { } | ||
299 | }; | ||
300 | MODULE_DEVICE_TABLE(i2c, isl12022_id); | ||
301 | |||
302 | static struct i2c_driver isl12022_driver = { | ||
303 | .driver = { | ||
304 | .name = "rtc-isl12022", | ||
305 | }, | ||
306 | .probe = isl12022_probe, | ||
307 | .remove = isl12022_remove, | ||
308 | .id_table = isl12022_id, | ||
309 | }; | ||
310 | |||
311 | static int __init isl12022_init(void) | ||
312 | { | ||
313 | return i2c_add_driver(&isl12022_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit isl12022_exit(void) | ||
317 | { | ||
318 | i2c_del_driver(&isl12022_driver); | ||
319 | } | ||
320 | |||
321 | module_init(isl12022_init); | ||
322 | module_exit(isl12022_exit); | ||
323 | |||
324 | MODULE_AUTHOR("roman.fietze@telemotive.de"); | ||
325 | MODULE_DESCRIPTION("ISL 12022 RTC driver"); | ||
326 | MODULE_LICENSE("GPL"); | ||
327 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 054e05294af8..468200c38ecb 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -462,39 +462,16 @@ isl1208_sysfs_store_usr(struct device *dev, | |||
462 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, | 462 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, |
463 | isl1208_sysfs_store_usr); | 463 | isl1208_sysfs_store_usr); |
464 | 464 | ||
465 | static int | 465 | static struct attribute *isl1208_rtc_attrs[] = { |
466 | isl1208_sysfs_register(struct device *dev) | 466 | &dev_attr_atrim.attr, |
467 | { | 467 | &dev_attr_dtrim.attr, |
468 | int err; | 468 | &dev_attr_usr.attr, |
469 | 469 | NULL | |
470 | err = device_create_file(dev, &dev_attr_atrim); | 470 | }; |
471 | if (err) | ||
472 | return err; | ||
473 | |||
474 | err = device_create_file(dev, &dev_attr_dtrim); | ||
475 | if (err) { | ||
476 | device_remove_file(dev, &dev_attr_atrim); | ||
477 | return err; | ||
478 | } | ||
479 | |||
480 | err = device_create_file(dev, &dev_attr_usr); | ||
481 | if (err) { | ||
482 | device_remove_file(dev, &dev_attr_atrim); | ||
483 | device_remove_file(dev, &dev_attr_dtrim); | ||
484 | } | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int | ||
490 | isl1208_sysfs_unregister(struct device *dev) | ||
491 | { | ||
492 | device_remove_file(dev, &dev_attr_dtrim); | ||
493 | device_remove_file(dev, &dev_attr_atrim); | ||
494 | device_remove_file(dev, &dev_attr_usr); | ||
495 | 471 | ||
496 | return 0; | 472 | static const struct attribute_group isl1208_rtc_sysfs_files = { |
497 | } | 473 | .attrs = isl1208_rtc_attrs, |
474 | }; | ||
498 | 475 | ||
499 | static int | 476 | static int |
500 | isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) | 477 | isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) |
@@ -529,7 +506,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
529 | dev_warn(&client->dev, "rtc power failure detected, " | 506 | dev_warn(&client->dev, "rtc power failure detected, " |
530 | "please set clock.\n"); | 507 | "please set clock.\n"); |
531 | 508 | ||
532 | rc = isl1208_sysfs_register(&client->dev); | 509 | rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); |
533 | if (rc) | 510 | if (rc) |
534 | goto exit_unregister; | 511 | goto exit_unregister; |
535 | 512 | ||
@@ -546,7 +523,7 @@ isl1208_remove(struct i2c_client *client) | |||
546 | { | 523 | { |
547 | struct rtc_device *rtc = i2c_get_clientdata(client); | 524 | struct rtc_device *rtc = i2c_get_clientdata(client); |
548 | 525 | ||
549 | isl1208_sysfs_unregister(&client->dev); | 526 | sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); |
550 | rtc_device_unregister(rtc); | 527 | rtc_device_unregister(rtc); |
551 | 528 | ||
552 | return 0; | 529 | return 0; |
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c new file mode 100644 index 000000000000..2619d57b91d7 --- /dev/null +++ b/drivers/rtc/rtc-jz4740.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC RTC driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | |||
23 | #define JZ_REG_RTC_CTRL 0x00 | ||
24 | #define JZ_REG_RTC_SEC 0x04 | ||
25 | #define JZ_REG_RTC_SEC_ALARM 0x08 | ||
26 | #define JZ_REG_RTC_REGULATOR 0x0C | ||
27 | #define JZ_REG_RTC_HIBERNATE 0x20 | ||
28 | #define JZ_REG_RTC_SCRATCHPAD 0x34 | ||
29 | |||
30 | #define JZ_RTC_CTRL_WRDY BIT(7) | ||
31 | #define JZ_RTC_CTRL_1HZ BIT(6) | ||
32 | #define JZ_RTC_CTRL_1HZ_IRQ BIT(5) | ||
33 | #define JZ_RTC_CTRL_AF BIT(4) | ||
34 | #define JZ_RTC_CTRL_AF_IRQ BIT(3) | ||
35 | #define JZ_RTC_CTRL_AE BIT(2) | ||
36 | #define JZ_RTC_CTRL_ENABLE BIT(0) | ||
37 | |||
38 | struct jz4740_rtc { | ||
39 | struct resource *mem; | ||
40 | void __iomem *base; | ||
41 | |||
42 | struct rtc_device *rtc; | ||
43 | |||
44 | unsigned int irq; | ||
45 | |||
46 | spinlock_t lock; | ||
47 | }; | ||
48 | |||
49 | static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) | ||
50 | { | ||
51 | return readl(rtc->base + reg); | ||
52 | } | ||
53 | |||
54 | static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | ||
55 | { | ||
56 | uint32_t ctrl; | ||
57 | int timeout = 1000; | ||
58 | |||
59 | do { | ||
60 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
61 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); | ||
62 | |||
63 | return timeout ? 0 : -EIO; | ||
64 | } | ||
65 | |||
66 | static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | ||
67 | uint32_t val) | ||
68 | { | ||
69 | int ret; | ||
70 | ret = jz4740_rtc_wait_write_ready(rtc); | ||
71 | if (ret == 0) | ||
72 | writel(val, rtc->base + reg); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | ||
78 | bool set) | ||
79 | { | ||
80 | int ret; | ||
81 | unsigned long flags; | ||
82 | uint32_t ctrl; | ||
83 | |||
84 | spin_lock_irqsave(&rtc->lock, flags); | ||
85 | |||
86 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
87 | |||
88 | /* Don't clear interrupt flags by accident */ | ||
89 | ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; | ||
90 | |||
91 | if (set) | ||
92 | ctrl |= mask; | ||
93 | else | ||
94 | ctrl &= ~mask; | ||
95 | |||
96 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | ||
97 | |||
98 | spin_unlock_irqrestore(&rtc->lock, flags); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) | ||
104 | { | ||
105 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
106 | uint32_t secs, secs2; | ||
107 | int timeout = 5; | ||
108 | |||
109 | /* If the seconds register is read while it is updated, it can contain a | ||
110 | * bogus value. This can be avoided by making sure that two consecutive | ||
111 | * reads have the same value. | ||
112 | */ | ||
113 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
114 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
115 | |||
116 | while (secs != secs2 && --timeout) { | ||
117 | secs = secs2; | ||
118 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
119 | } | ||
120 | |||
121 | if (timeout == 0) | ||
122 | return -EIO; | ||
123 | |||
124 | rtc_time_to_tm(secs, time); | ||
125 | |||
126 | return rtc_valid_tm(time); | ||
127 | } | ||
128 | |||
129 | static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
130 | { | ||
131 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
132 | |||
133 | return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | ||
134 | } | ||
135 | |||
136 | static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
137 | { | ||
138 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
139 | uint32_t secs; | ||
140 | uint32_t ctrl; | ||
141 | |||
142 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); | ||
143 | |||
144 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
145 | |||
146 | alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); | ||
147 | alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); | ||
148 | |||
149 | rtc_time_to_tm(secs, &alrm->time); | ||
150 | |||
151 | return rtc_valid_tm(&alrm->time); | ||
152 | } | ||
153 | |||
154 | static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
155 | { | ||
156 | int ret; | ||
157 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
158 | unsigned long secs; | ||
159 | |||
160 | rtc_tm_to_time(&alrm->time, &secs); | ||
161 | |||
162 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | ||
163 | if (!ret) | ||
164 | ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); | ||
165 | |||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) | ||
170 | { | ||
171 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
172 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); | ||
173 | } | ||
174 | |||
175 | static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
176 | { | ||
177 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
178 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); | ||
179 | } | ||
180 | |||
181 | static struct rtc_class_ops jz4740_rtc_ops = { | ||
182 | .read_time = jz4740_rtc_read_time, | ||
183 | .set_mmss = jz4740_rtc_set_mmss, | ||
184 | .read_alarm = jz4740_rtc_read_alarm, | ||
185 | .set_alarm = jz4740_rtc_set_alarm, | ||
186 | .update_irq_enable = jz4740_rtc_update_irq_enable, | ||
187 | .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, | ||
188 | }; | ||
189 | |||
190 | static irqreturn_t jz4740_rtc_irq(int irq, void *data) | ||
191 | { | ||
192 | struct jz4740_rtc *rtc = data; | ||
193 | uint32_t ctrl; | ||
194 | unsigned long events = 0; | ||
195 | |||
196 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
197 | |||
198 | if (ctrl & JZ_RTC_CTRL_1HZ) | ||
199 | events |= (RTC_UF | RTC_IRQF); | ||
200 | |||
201 | if (ctrl & JZ_RTC_CTRL_AF) | ||
202 | events |= (RTC_AF | RTC_IRQF); | ||
203 | |||
204 | rtc_update_irq(rtc->rtc, 1, events); | ||
205 | |||
206 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); | ||
207 | |||
208 | return IRQ_HANDLED; | ||
209 | } | ||
210 | |||
211 | void jz4740_rtc_poweroff(struct device *dev) | ||
212 | { | ||
213 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
214 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); | ||
215 | } | ||
216 | EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); | ||
217 | |||
218 | static int __devinit jz4740_rtc_probe(struct platform_device *pdev) | ||
219 | { | ||
220 | int ret; | ||
221 | struct jz4740_rtc *rtc; | ||
222 | uint32_t scratchpad; | ||
223 | |||
224 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
225 | if (!rtc) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | rtc->irq = platform_get_irq(pdev, 0); | ||
229 | if (rtc->irq < 0) { | ||
230 | ret = -ENOENT; | ||
231 | dev_err(&pdev->dev, "Failed to get platform irq\n"); | ||
232 | goto err_free; | ||
233 | } | ||
234 | |||
235 | rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
236 | if (!rtc->mem) { | ||
237 | ret = -ENOENT; | ||
238 | dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); | ||
239 | goto err_free; | ||
240 | } | ||
241 | |||
242 | rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem), | ||
243 | pdev->name); | ||
244 | if (!rtc->mem) { | ||
245 | ret = -EBUSY; | ||
246 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
247 | goto err_free; | ||
248 | } | ||
249 | |||
250 | rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem)); | ||
251 | if (!rtc->base) { | ||
252 | ret = -EBUSY; | ||
253 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
254 | goto err_release_mem_region; | ||
255 | } | ||
256 | |||
257 | spin_lock_init(&rtc->lock); | ||
258 | |||
259 | platform_set_drvdata(pdev, rtc); | ||
260 | |||
261 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, | ||
262 | THIS_MODULE); | ||
263 | if (IS_ERR(rtc->rtc)) { | ||
264 | ret = PTR_ERR(rtc->rtc); | ||
265 | dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); | ||
266 | goto err_iounmap; | ||
267 | } | ||
268 | |||
269 | ret = request_irq(rtc->irq, jz4740_rtc_irq, 0, | ||
270 | pdev->name, rtc); | ||
271 | if (ret) { | ||
272 | dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); | ||
273 | goto err_unregister_rtc; | ||
274 | } | ||
275 | |||
276 | scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); | ||
277 | if (scratchpad != 0x12345678) { | ||
278 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | ||
279 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | ||
280 | if (ret) { | ||
281 | dev_err(&pdev->dev, "Could not write write to RTC registers\n"); | ||
282 | goto err_free_irq; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | return 0; | ||
287 | |||
288 | err_free_irq: | ||
289 | free_irq(rtc->irq, rtc); | ||
290 | err_unregister_rtc: | ||
291 | rtc_device_unregister(rtc->rtc); | ||
292 | err_iounmap: | ||
293 | platform_set_drvdata(pdev, NULL); | ||
294 | iounmap(rtc->base); | ||
295 | err_release_mem_region: | ||
296 | release_mem_region(rtc->mem->start, resource_size(rtc->mem)); | ||
297 | err_free: | ||
298 | kfree(rtc); | ||
299 | |||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static int __devexit jz4740_rtc_remove(struct platform_device *pdev) | ||
304 | { | ||
305 | struct jz4740_rtc *rtc = platform_get_drvdata(pdev); | ||
306 | |||
307 | free_irq(rtc->irq, rtc); | ||
308 | |||
309 | rtc_device_unregister(rtc->rtc); | ||
310 | |||
311 | iounmap(rtc->base); | ||
312 | release_mem_region(rtc->mem->start, resource_size(rtc->mem)); | ||
313 | |||
314 | kfree(rtc); | ||
315 | |||
316 | platform_set_drvdata(pdev, NULL); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | struct platform_driver jz4740_rtc_driver = { | ||
322 | .probe = jz4740_rtc_probe, | ||
323 | .remove = __devexit_p(jz4740_rtc_remove), | ||
324 | .driver = { | ||
325 | .name = "jz4740-rtc", | ||
326 | .owner = THIS_MODULE, | ||
327 | }, | ||
328 | }; | ||
329 | |||
330 | static int __init jz4740_rtc_init(void) | ||
331 | { | ||
332 | return platform_driver_register(&jz4740_rtc_driver); | ||
333 | } | ||
334 | module_init(jz4740_rtc_init); | ||
335 | |||
336 | static void __exit jz4740_rtc_exit(void) | ||
337 | { | ||
338 | platform_driver_unregister(&jz4740_rtc_driver); | ||
339 | } | ||
340 | module_exit(jz4740_rtc_exit); | ||
341 | |||
342 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
343 | MODULE_LICENSE("GPL"); | ||
344 | MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); | ||
345 | MODULE_ALIAS("platform:jz4740-rtc"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 60fe266f0f49..66377f3e28b8 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -121,7 +121,7 @@ static int m41t80_get_datetime(struct i2c_client *client, | |||
121 | 121 | ||
122 | /* assume 20YY not 19YY, and ignore the Century Bit */ | 122 | /* assume 20YY not 19YY, and ignore the Century Bit */ |
123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; | 123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; |
124 | return 0; | 124 | return rtc_valid_tm(tm); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* Sets the given date and time to the real time clock. */ | 127 | /* Sets the given date and time to the real time clock. */ |
@@ -364,7 +364,7 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
364 | t->time.tm_isdst = -1; | 364 | t->time.tm_isdst = -1; |
365 | t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); | 365 | t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); |
366 | t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); | 366 | t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); |
367 | return 0; | 367 | return rtc_valid_tm(t); |
368 | } | 368 | } |
369 | 369 | ||
370 | static struct rtc_class_ops m41t80_rtc_ops = { | 370 | static struct rtc_class_ops m41t80_rtc_ops = { |
@@ -595,10 +595,6 @@ static void wdt_disable(void) | |||
595 | static ssize_t wdt_write(struct file *file, const char __user *buf, | 595 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
596 | size_t count, loff_t *ppos) | 596 | size_t count, loff_t *ppos) |
597 | { | 597 | { |
598 | /* Can't seek (pwrite) on this device | ||
599 | if (ppos != &file->f_pos) | ||
600 | return -ESPIPE; | ||
601 | */ | ||
602 | if (count) { | 598 | if (count) { |
603 | wdt_ping(); | 599 | wdt_ping(); |
604 | return 1; | 600 | return 1; |
@@ -623,7 +619,7 @@ static ssize_t wdt_read(struct file *file, char __user *buf, | |||
623 | * according to their available features. We only actually usefully support | 619 | * according to their available features. We only actually usefully support |
624 | * querying capabilities and current status. | 620 | * querying capabilities and current status. |
625 | */ | 621 | */ |
626 | static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 622 | static int wdt_ioctl(struct file *file, unsigned int cmd, |
627 | unsigned long arg) | 623 | unsigned long arg) |
628 | { | 624 | { |
629 | int new_margin, rv; | 625 | int new_margin, rv; |
@@ -676,6 +672,18 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
676 | return -ENOTTY; | 672 | return -ENOTTY; |
677 | } | 673 | } |
678 | 674 | ||
675 | static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
676 | unsigned long arg) | ||
677 | { | ||
678 | int ret; | ||
679 | |||
680 | lock_kernel(); | ||
681 | ret = wdt_ioctl(file, cmd, arg); | ||
682 | unlock_kernel(); | ||
683 | |||
684 | return ret; | ||
685 | } | ||
686 | |||
679 | /** | 687 | /** |
680 | * wdt_open: | 688 | * wdt_open: |
681 | * @inode: inode of device | 689 | * @inode: inode of device |
@@ -695,7 +703,7 @@ static int wdt_open(struct inode *inode, struct file *file) | |||
695 | */ | 703 | */ |
696 | wdt_is_open = 1; | 704 | wdt_is_open = 1; |
697 | unlock_kernel(); | 705 | unlock_kernel(); |
698 | return 0; | 706 | return nonseekable_open(inode, file); |
699 | } | 707 | } |
700 | return -ENODEV; | 708 | return -ENODEV; |
701 | } | 709 | } |
@@ -736,7 +744,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
736 | static const struct file_operations wdt_fops = { | 744 | static const struct file_operations wdt_fops = { |
737 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
738 | .read = wdt_read, | 746 | .read = wdt_read, |
739 | .ioctl = wdt_ioctl, | 747 | .unlocked_ioctl = wdt_unlocked_ioctl, |
740 | .write = wdt_write, | 748 | .write = wdt_write, |
741 | .open = wdt_open, | 749 | .open = wdt_open, |
742 | .release = wdt_release, | 750 | .release = wdt_release, |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 365ff3ac2348..a99a0b554eb8 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -105,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
105 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", | 105 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", |
106 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 106 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
107 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 107 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
108 | return 0; | 108 | return rtc_valid_tm(tm); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | 111 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -196,7 +196,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
196 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", | 196 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", |
197 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 197 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
198 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
199 | return 0; | 199 | return rtc_valid_tm(tm); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* | 202 | /* |
@@ -343,7 +343,7 @@ static const struct rtc_class_ops m48t02_rtc_ops = { | |||
343 | .set_time = m48t59_rtc_set_time, | 343 | .set_time = m48t59_rtc_set_time, |
344 | }; | 344 | }; |
345 | 345 | ||
346 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 346 | static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, |
347 | struct bin_attribute *bin_attr, | 347 | struct bin_attribute *bin_attr, |
348 | char *buf, loff_t pos, size_t size) | 348 | char *buf, loff_t pos, size_t size) |
349 | { | 349 | { |
@@ -363,7 +363,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
363 | return cnt; | 363 | return cnt; |
364 | } | 364 | } |
365 | 365 | ||
366 | static ssize_t m48t59_nvram_write(struct kobject *kobj, | 366 | static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, |
367 | struct bin_attribute *bin_attr, | 367 | struct bin_attribute *bin_attr, |
368 | char *buf, loff_t pos, size_t size) | 368 | char *buf, loff_t pos, size_t size) |
369 | { | 369 | { |
@@ -506,7 +506,6 @@ out: | |||
506 | free_irq(m48t59->irq, &pdev->dev); | 506 | free_irq(m48t59->irq, &pdev->dev); |
507 | if (m48t59->ioaddr) | 507 | if (m48t59->ioaddr) |
508 | iounmap(m48t59->ioaddr); | 508 | iounmap(m48t59->ioaddr); |
509 | if (m48t59) | ||
510 | kfree(m48t59); | 509 | kfree(m48t59); |
511 | return ret; | 510 | return ret; |
512 | } | 511 | } |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 7c045cffa9ff..f981287d582b 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
@@ -77,7 +77,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) | 77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) |
78 | tm->tm_hour += 12; | 78 | tm->tm_hour += 12; |
79 | 79 | ||
80 | return 0; | 80 | return rtc_valid_tm(tm); |
81 | } | 81 | } |
82 | 82 | ||
83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | 83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index a4f6665ab3c5..486142c2637a 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
@@ -159,7 +159,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); |
161 | 161 | ||
162 | return 0; | 162 | return rtc_valid_tm(tm); |
163 | } | 163 | } |
164 | 164 | ||
165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index f0dbf9cb8f9c..db5d8c416d26 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -279,7 +279,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op, | |||
279 | if (!rtc) | 279 | if (!rtc) |
280 | return -ENOMEM; | 280 | return -ENOMEM; |
281 | 281 | ||
282 | rtc->regs = of_iomap(op->node, 0); | 282 | rtc->regs = of_iomap(op->dev.of_node, 0); |
283 | if (!rtc->regs) { | 283 | if (!rtc->regs) { |
284 | dev_err(&op->dev, "%s: couldn't map io space\n", __func__); | 284 | dev_err(&op->dev, "%s: couldn't map io space\n", __func__); |
285 | err = -ENOSYS; | 285 | err = -ENOSYS; |
@@ -290,7 +290,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op, | |||
290 | 290 | ||
291 | dev_set_drvdata(&op->dev, rtc); | 291 | dev_set_drvdata(&op->dev, rtc); |
292 | 292 | ||
293 | rtc->irq = irq_of_parse_and_map(op->node, 1); | 293 | rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1); |
294 | err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, | 294 | err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, |
295 | "mpc5121-rtc", &op->dev); | 295 | "mpc5121-rtc", &op->dev); |
296 | if (err) { | 296 | if (err) { |
@@ -299,7 +299,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op, | |||
299 | goto out_dispose; | 299 | goto out_dispose; |
300 | } | 300 | } |
301 | 301 | ||
302 | rtc->irq_periodic = irq_of_parse_and_map(op->node, 0); | 302 | rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0); |
303 | err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, | 303 | err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, |
304 | IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); | 304 | IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); |
305 | if (err) { | 305 | if (err) { |
@@ -365,9 +365,11 @@ static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | |||
365 | }; | 365 | }; |
366 | 366 | ||
367 | static struct of_platform_driver mpc5121_rtc_driver = { | 367 | static struct of_platform_driver mpc5121_rtc_driver = { |
368 | .owner = THIS_MODULE, | 368 | .driver = { |
369 | .name = "mpc5121-rtc", | 369 | .name = "mpc5121-rtc", |
370 | .match_table = mpc5121_rtc_match, | 370 | .owner = THIS_MODULE, |
371 | .of_match_table = mpc5121_rtc_match, | ||
372 | }, | ||
371 | .probe = mpc5121_rtc_probe, | 373 | .probe = mpc5121_rtc_probe, |
372 | .remove = __devexit_p(mpc5121_rtc_remove), | 374 | .remove = __devexit_p(mpc5121_rtc_remove), |
373 | }; | 375 | }; |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index d71fe61db1d6..0b06c1e03fd5 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -83,12 +83,6 @@ struct rtc_plat_data { | |||
83 | void __iomem *ioaddr; | 83 | void __iomem *ioaddr; |
84 | int irq; | 84 | int irq; |
85 | struct clk *clk; | 85 | struct clk *clk; |
86 | unsigned int irqen; | ||
87 | int alrm_sec; | ||
88 | int alrm_min; | ||
89 | int alrm_hour; | ||
90 | int alrm_mday; | ||
91 | struct timespec mxc_rtc_delta; | ||
92 | struct rtc_time g_rtc_alarm; | 86 | struct rtc_time g_rtc_alarm; |
93 | }; | 87 | }; |
94 | 88 | ||
@@ -379,7 +373,6 @@ static struct rtc_class_ops mxc_rtc_ops = { | |||
379 | 373 | ||
380 | static int __init mxc_rtc_probe(struct platform_device *pdev) | 374 | static int __init mxc_rtc_probe(struct platform_device *pdev) |
381 | { | 375 | { |
382 | struct clk *clk; | ||
383 | struct resource *res; | 376 | struct resource *res; |
384 | struct rtc_device *rtc; | 377 | struct rtc_device *rtc; |
385 | struct rtc_plat_data *pdata = NULL; | 378 | struct rtc_plat_data *pdata = NULL; |
@@ -402,14 +395,15 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
402 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, | 395 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, |
403 | resource_size(res)); | 396 | resource_size(res)); |
404 | 397 | ||
405 | clk = clk_get(&pdev->dev, "ckil"); | 398 | pdata->clk = clk_get(&pdev->dev, "rtc"); |
406 | if (IS_ERR(clk)) { | 399 | if (IS_ERR(pdata->clk)) { |
407 | ret = PTR_ERR(clk); | 400 | dev_err(&pdev->dev, "unable to get clock!\n"); |
401 | ret = PTR_ERR(pdata->clk); | ||
408 | goto exit_free_pdata; | 402 | goto exit_free_pdata; |
409 | } | 403 | } |
410 | 404 | ||
411 | rate = clk_get_rate(clk); | 405 | clk_enable(pdata->clk); |
412 | clk_put(clk); | 406 | rate = clk_get_rate(pdata->clk); |
413 | 407 | ||
414 | if (rate == 32768) | 408 | if (rate == 32768) |
415 | reg = RTC_INPUT_CLK_32768HZ; | 409 | reg = RTC_INPUT_CLK_32768HZ; |
@@ -420,7 +414,7 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
420 | else { | 414 | else { |
421 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); | 415 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); |
422 | ret = -EINVAL; | 416 | ret = -EINVAL; |
423 | goto exit_free_pdata; | 417 | goto exit_put_clk; |
424 | } | 418 | } |
425 | 419 | ||
426 | reg |= RTC_ENABLE_BIT; | 420 | reg |= RTC_ENABLE_BIT; |
@@ -428,18 +422,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
428 | if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { | 422 | if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { |
429 | dev_err(&pdev->dev, "hardware module can't be enabled!\n"); | 423 | dev_err(&pdev->dev, "hardware module can't be enabled!\n"); |
430 | ret = -EIO; | 424 | ret = -EIO; |
431 | goto exit_free_pdata; | 425 | goto exit_put_clk; |
432 | } | ||
433 | |||
434 | pdata->clk = clk_get(&pdev->dev, "rtc"); | ||
435 | if (IS_ERR(pdata->clk)) { | ||
436 | dev_err(&pdev->dev, "unable to get clock!\n"); | ||
437 | ret = PTR_ERR(pdata->clk); | ||
438 | goto exit_free_pdata; | ||
439 | } | 426 | } |
440 | 427 | ||
441 | clk_enable(pdata->clk); | ||
442 | |||
443 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, | 428 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, |
444 | THIS_MODULE); | 429 | THIS_MODULE); |
445 | if (IS_ERR(rtc)) { | 430 | if (IS_ERR(rtc)) { |
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a351bd5d8176..62de66af0a68 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -85,25 +85,24 @@ static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | |||
85 | 85 | ||
86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | 86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) |
87 | { | 87 | { |
88 | unsigned int i; | 88 | unsigned int timeout = 0x1000; |
89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | 89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); |
90 | 90 | ||
91 | mdelay(10); | 91 | mdelay(10); |
92 | 92 | ||
93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | 93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); |
94 | 94 | ||
95 | for (i = 0; i < 1000; i++) { | 95 | while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) |
96 | if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | 96 | && timeout--) |
97 | return 0; | 97 | mdelay(1); |
98 | } | ||
99 | 98 | ||
100 | if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0) | 99 | if (!timeout) |
101 | return ERR_PTR(-ENODEV); | 100 | return ERR_PTR(-EPERM); |
102 | 101 | ||
103 | return ERR_PTR(-EPERM); | 102 | return 0; |
104 | } | 103 | } |
105 | 104 | ||
106 | static void nuc900_rtc_bcd2bin(unsigned int timereg, | 105 | static int nuc900_rtc_bcd2bin(unsigned int timereg, |
107 | unsigned int calreg, struct rtc_time *tm) | 106 | unsigned int calreg, struct rtc_time *tm) |
108 | { | 107 | { |
109 | tm->tm_mday = bcd2bin(calreg >> 0); | 108 | tm->tm_mday = bcd2bin(calreg >> 0); |
@@ -114,15 +113,21 @@ static void nuc900_rtc_bcd2bin(unsigned int timereg, | |||
114 | tm->tm_min = bcd2bin(timereg >> 8); | 113 | tm->tm_min = bcd2bin(timereg >> 8); |
115 | tm->tm_hour = bcd2bin(timereg >> 16); | 114 | tm->tm_hour = bcd2bin(timereg >> 16); |
116 | 115 | ||
117 | rtc_valid_tm(tm); | 116 | return rtc_valid_tm(tm); |
118 | } | 117 | } |
119 | 118 | ||
120 | static void nuc900_rtc_bin2bcd(struct rtc_time *settm, | 119 | static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, |
121 | struct nuc900_bcd_time *gettm) | 120 | struct nuc900_bcd_time *gettm) |
122 | { | 121 | { |
123 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | 122 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; |
124 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | 123 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; |
125 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | 124 | |
125 | if (settm->tm_year < 100) { | ||
126 | dev_warn(dev, "The year will be between 1970-1999, right?\n"); | ||
127 | gettm->bcd_year = bin2bcd(settm->tm_year) << 16; | ||
128 | } else { | ||
129 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
130 | } | ||
126 | 131 | ||
127 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | 132 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; |
128 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | 133 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; |
@@ -165,9 +170,7 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
165 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | 170 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); |
166 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | 171 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); |
167 | 172 | ||
168 | nuc900_rtc_bcd2bin(timeval, clrval, tm); | 173 | return nuc900_rtc_bcd2bin(timeval, clrval, tm); |
169 | |||
170 | return 0; | ||
171 | } | 174 | } |
172 | 175 | ||
173 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | 176 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -177,7 +180,7 @@ static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
177 | unsigned long val; | 180 | unsigned long val; |
178 | int *err; | 181 | int *err; |
179 | 182 | ||
180 | nuc900_rtc_bin2bcd(tm, &gettm); | 183 | nuc900_rtc_bin2bcd(dev, tm, &gettm); |
181 | 184 | ||
182 | err = check_rtc_access_enable(rtc); | 185 | err = check_rtc_access_enable(rtc); |
183 | if (IS_ERR(err)) | 186 | if (IS_ERR(err)) |
@@ -200,9 +203,7 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
200 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | 203 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); |
201 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | 204 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); |
202 | 205 | ||
203 | nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | 206 | return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); |
204 | |||
205 | return 0; | ||
206 | } | 207 | } |
207 | 208 | ||
208 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 209 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -212,7 +213,7 @@ static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
212 | unsigned long val; | 213 | unsigned long val; |
213 | int *err; | 214 | int *err; |
214 | 215 | ||
215 | nuc900_rtc_bin2bcd(&alrm->time, &tm); | 216 | nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); |
216 | 217 | ||
217 | err = check_rtc_access_enable(rtc); | 218 | err = check_rtc_access_enable(rtc); |
218 | if (IS_ERR(err)) | 219 | if (IS_ERR(err)) |
@@ -268,29 +269,30 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | |||
268 | goto fail2; | 269 | goto fail2; |
269 | } | 270 | } |
270 | 271 | ||
271 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | 272 | platform_set_drvdata(pdev, nuc900_rtc); |
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 | 273 | ||
279 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | 274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, |
280 | &nuc900_rtc_ops, THIS_MODULE); | 275 | &nuc900_rtc_ops, THIS_MODULE); |
281 | if (IS_ERR(nuc900_rtc->rtcdev)) { | 276 | if (IS_ERR(nuc900_rtc->rtcdev)) { |
282 | dev_err(&pdev->dev, "rtc device register faild\n"); | 277 | dev_err(&pdev->dev, "rtc device register faild\n"); |
283 | err = PTR_ERR(nuc900_rtc->rtcdev); | 278 | err = PTR_ERR(nuc900_rtc->rtcdev); |
284 | goto fail4; | 279 | goto fail3; |
285 | } | 280 | } |
286 | 281 | ||
287 | platform_set_drvdata(pdev, nuc900_rtc); | ||
288 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | 282 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, |
289 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | 283 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); |
290 | 284 | ||
285 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
286 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
287 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
288 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
289 | err = -EBUSY; | ||
290 | goto fail4; | ||
291 | } | ||
292 | |||
291 | return 0; | 293 | return 0; |
292 | 294 | ||
293 | fail4: free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 295 | fail4: rtc_device_unregister(nuc900_rtc->rtcdev); |
294 | fail3: iounmap(nuc900_rtc->rtc_reg); | 296 | fail3: iounmap(nuc900_rtc->rtc_reg); |
295 | fail2: release_mem_region(res->start, resource_size(res)); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
296 | fail1: kfree(nuc900_rtc); | 298 | fail1: kfree(nuc900_rtc); |
@@ -302,8 +304,8 @@ static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | |||
302 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | 304 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); |
303 | struct resource *res; | 305 | struct resource *res; |
304 | 306 | ||
305 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
306 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 307 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); |
308 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
307 | iounmap(nuc900_rtc->rtc_reg); | 309 | iounmap(nuc900_rtc->rtc_reg); |
308 | 310 | ||
309 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 311 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 1af42b4a6f59..b42c0c679266 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -172,14 +172,6 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | struct pcf8563_limit | ||
176 | { | ||
177 | unsigned char reg; | ||
178 | unsigned char mask; | ||
179 | unsigned char min; | ||
180 | unsigned char max; | ||
181 | }; | ||
182 | |||
183 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 175 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
184 | { | 176 | { |
185 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 177 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 3587d9922f28..6c418fe7f288 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/bcd.h> | 24 | #include <linux/bcd.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/version.h> | ||
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | 27 | ||
29 | /* | 28 | /* |
@@ -456,7 +455,7 @@ static struct rtc_class_ops stv2_pl031_ops = { | |||
456 | .irq_set_freq = pl031_irq_set_freq, | 455 | .irq_set_freq = pl031_irq_set_freq, |
457 | }; | 456 | }; |
458 | 457 | ||
459 | static struct amba_id pl031_ids[] __initdata = { | 458 | static struct amba_id pl031_ids[] = { |
460 | { | 459 | { |
461 | .id = 0x00041031, | 460 | .id = 0x00041031, |
462 | .mask = 0x000fffff, | 461 | .mask = 0x000fffff, |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index e9c6fa035989..29e867a1aaa8 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -87,7 +87,6 @@ struct pxa_rtc { | |||
87 | int irq_Alrm; | 87 | int irq_Alrm; |
88 | struct rtc_device *rtc; | 88 | struct rtc_device *rtc; |
89 | spinlock_t lock; /* Protects this structure */ | 89 | spinlock_t lock; /* Protects this structure */ |
90 | struct rtc_time rtc_alarm; | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | static u32 ryxr_calc(struct rtc_time *tm) | 92 | static u32 ryxr_calc(struct rtc_time *tm) |
@@ -236,32 +235,34 @@ static int pxa_periodic_irq_set_state(struct device *dev, int enabled) | |||
236 | return 0; | 235 | return 0; |
237 | } | 236 | } |
238 | 237 | ||
239 | static int pxa_rtc_ioctl(struct device *dev, unsigned int cmd, | 238 | static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled) |
240 | unsigned long arg) | ||
241 | { | 239 | { |
242 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | 240 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); |
243 | int ret = 0; | ||
244 | 241 | ||
245 | spin_lock_irq(&pxa_rtc->lock); | 242 | spin_lock_irq(&pxa_rtc->lock); |
246 | switch (cmd) { | 243 | |
247 | case RTC_AIE_OFF: | 244 | if (enabled) |
248 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); | ||
249 | break; | ||
250 | case RTC_AIE_ON: | ||
251 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); | 245 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); |
252 | break; | 246 | else |
253 | case RTC_UIE_OFF: | 247 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); |
254 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); | 248 | |
255 | break; | 249 | spin_unlock_irq(&pxa_rtc->lock); |
256 | case RTC_UIE_ON: | 250 | return 0; |
251 | } | ||
252 | |||
253 | static int pxa_update_irq_enable(struct device *dev, unsigned int enabled) | ||
254 | { | ||
255 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | ||
256 | |||
257 | spin_lock_irq(&pxa_rtc->lock); | ||
258 | |||
259 | if (enabled) | ||
257 | rtsr_set_bits(pxa_rtc, RTSR_HZE); | 260 | rtsr_set_bits(pxa_rtc, RTSR_HZE); |
258 | break; | 261 | else |
259 | default: | 262 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); |
260 | ret = -ENOIOCTLCMD; | ||
261 | } | ||
262 | 263 | ||
263 | spin_unlock_irq(&pxa_rtc->lock); | 264 | spin_unlock_irq(&pxa_rtc->lock); |
264 | return ret; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
267 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) | 268 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -340,11 +341,12 @@ static int pxa_rtc_proc(struct device *dev, struct seq_file *seq) | |||
340 | static const struct rtc_class_ops pxa_rtc_ops = { | 341 | static const struct rtc_class_ops pxa_rtc_ops = { |
341 | .open = pxa_rtc_open, | 342 | .open = pxa_rtc_open, |
342 | .release = pxa_rtc_release, | 343 | .release = pxa_rtc_release, |
343 | .ioctl = pxa_rtc_ioctl, | ||
344 | .read_time = pxa_rtc_read_time, | 344 | .read_time = pxa_rtc_read_time, |
345 | .set_time = pxa_rtc_set_time, | 345 | .set_time = pxa_rtc_set_time, |
346 | .read_alarm = pxa_rtc_read_alarm, | 346 | .read_alarm = pxa_rtc_read_alarm, |
347 | .set_alarm = pxa_rtc_set_alarm, | 347 | .set_alarm = pxa_rtc_set_alarm, |
348 | .alarm_irq_enable = pxa_alarm_irq_enable, | ||
349 | .update_irq_enable = pxa_update_irq_enable, | ||
348 | .proc = pxa_rtc_proc, | 350 | .proc = pxa_rtc_proc, |
349 | .irq_set_state = pxa_periodic_irq_set_state, | 351 | .irq_set_state = pxa_periodic_irq_set_state, |
350 | .irq_set_freq = pxa_periodic_irq_set_freq, | 352 | .irq_set_freq = pxa_periodic_irq_set_freq, |
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index a95f733bb15a..36eb66184461 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -63,6 +63,8 @@ enum { | |||
63 | struct rp5c01_priv { | 63 | struct rp5c01_priv { |
64 | u32 __iomem *regs; | 64 | u32 __iomem *regs; |
65 | struct rtc_device *rtc; | 65 | struct rtc_device *rtc; |
66 | spinlock_t lock; /* against concurrent RTC/NVRAM access */ | ||
67 | struct bin_attribute nvram_attr; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, | 70 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, |
@@ -92,6 +94,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | |||
92 | { | 94 | { |
93 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | 95 | struct rp5c01_priv *priv = dev_get_drvdata(dev); |
94 | 96 | ||
97 | spin_lock_irq(&priv->lock); | ||
95 | rp5c01_lock(priv); | 98 | rp5c01_lock(priv); |
96 | 99 | ||
97 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + | 100 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + |
@@ -111,6 +114,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | |||
111 | tm->tm_year += 100; | 114 | tm->tm_year += 100; |
112 | 115 | ||
113 | rp5c01_unlock(priv); | 116 | rp5c01_unlock(priv); |
117 | spin_unlock_irq(&priv->lock); | ||
114 | 118 | ||
115 | return rtc_valid_tm(tm); | 119 | return rtc_valid_tm(tm); |
116 | } | 120 | } |
@@ -119,6 +123,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | |||
119 | { | 123 | { |
120 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | 124 | struct rp5c01_priv *priv = dev_get_drvdata(dev); |
121 | 125 | ||
126 | spin_lock_irq(&priv->lock); | ||
122 | rp5c01_lock(priv); | 127 | rp5c01_lock(priv); |
123 | 128 | ||
124 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); | 129 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); |
@@ -139,6 +144,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | |||
139 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); | 144 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); |
140 | 145 | ||
141 | rp5c01_unlock(priv); | 146 | rp5c01_unlock(priv); |
147 | spin_unlock_irq(&priv->lock); | ||
142 | return 0; | 148 | return 0; |
143 | } | 149 | } |
144 | 150 | ||
@@ -147,6 +153,72 @@ static const struct rtc_class_ops rp5c01_rtc_ops = { | |||
147 | .set_time = rp5c01_set_time, | 153 | .set_time = rp5c01_set_time, |
148 | }; | 154 | }; |
149 | 155 | ||
156 | |||
157 | /* | ||
158 | * The NVRAM is organized as 2 blocks of 13 nibbles of 4 bits. | ||
159 | * We provide access to them like AmigaOS does: the high nibble of each 8-bit | ||
160 | * byte is stored in BLOCK10, the low nibble in BLOCK11. | ||
161 | */ | ||
162 | |||
163 | static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, | ||
164 | struct bin_attribute *bin_attr, | ||
165 | char *buf, loff_t pos, size_t size) | ||
166 | { | ||
167 | struct device *dev = container_of(kobj, struct device, kobj); | ||
168 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
169 | ssize_t count; | ||
170 | |||
171 | spin_lock_irq(&priv->lock); | ||
172 | |||
173 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
174 | u8 data; | ||
175 | |||
176 | rp5c01_write(priv, | ||
177 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
178 | RP5C01_MODE); | ||
179 | data = rp5c01_read(priv, pos) << 4; | ||
180 | rp5c01_write(priv, | ||
181 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
182 | RP5C01_MODE); | ||
183 | data |= rp5c01_read(priv, pos++); | ||
184 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
185 | RP5C01_MODE); | ||
186 | *buf++ = data; | ||
187 | } | ||
188 | |||
189 | spin_unlock_irq(&priv->lock); | ||
190 | return count; | ||
191 | } | ||
192 | |||
193 | static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, | ||
194 | struct bin_attribute *bin_attr, | ||
195 | char *buf, loff_t pos, size_t size) | ||
196 | { | ||
197 | struct device *dev = container_of(kobj, struct device, kobj); | ||
198 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
199 | ssize_t count; | ||
200 | |||
201 | spin_lock_irq(&priv->lock); | ||
202 | |||
203 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
204 | u8 data = *buf++; | ||
205 | |||
206 | rp5c01_write(priv, | ||
207 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
208 | RP5C01_MODE); | ||
209 | rp5c01_write(priv, data >> 4, pos); | ||
210 | rp5c01_write(priv, | ||
211 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
212 | RP5C01_MODE); | ||
213 | rp5c01_write(priv, data & 0xf, pos++); | ||
214 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
215 | RP5C01_MODE); | ||
216 | } | ||
217 | |||
218 | spin_unlock_irq(&priv->lock); | ||
219 | return count; | ||
220 | } | ||
221 | |||
150 | static int __init rp5c01_rtc_probe(struct platform_device *dev) | 222 | static int __init rp5c01_rtc_probe(struct platform_device *dev) |
151 | { | 223 | { |
152 | struct resource *res; | 224 | struct resource *res; |
@@ -168,6 +240,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) | |||
168 | goto out_free_priv; | 240 | goto out_free_priv; |
169 | } | 241 | } |
170 | 242 | ||
243 | sysfs_bin_attr_init(&priv->nvram_attr); | ||
244 | priv->nvram_attr.attr.name = "nvram"; | ||
245 | priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
246 | priv->nvram_attr.read = rp5c01_nvram_read; | ||
247 | priv->nvram_attr.write = rp5c01_nvram_write; | ||
248 | priv->nvram_attr.size = RP5C01_MODE; | ||
249 | |||
250 | spin_lock_init(&priv->lock); | ||
251 | |||
171 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, | 252 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, |
172 | THIS_MODULE); | 253 | THIS_MODULE); |
173 | if (IS_ERR(rtc)) { | 254 | if (IS_ERR(rtc)) { |
@@ -177,8 +258,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) | |||
177 | 258 | ||
178 | priv->rtc = rtc; | 259 | priv->rtc = rtc; |
179 | platform_set_drvdata(dev, priv); | 260 | platform_set_drvdata(dev, priv); |
261 | |||
262 | error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
263 | if (error) | ||
264 | goto out_unregister; | ||
265 | |||
180 | return 0; | 266 | return 0; |
181 | 267 | ||
268 | out_unregister: | ||
269 | rtc_device_unregister(rtc); | ||
182 | out_unmap: | 270 | out_unmap: |
183 | iounmap(priv->regs); | 271 | iounmap(priv->regs); |
184 | out_free_priv: | 272 | out_free_priv: |
@@ -190,6 +278,7 @@ static int __exit rp5c01_rtc_remove(struct platform_device *dev) | |||
190 | { | 278 | { |
191 | struct rp5c01_priv *priv = platform_get_drvdata(dev); | 279 | struct rp5c01_priv *priv = platform_get_drvdata(dev); |
192 | 280 | ||
281 | sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
193 | rtc_device_unregister(priv->rtc); | 282 | rtc_device_unregister(priv->rtc); |
194 | iounmap(priv->regs); | 283 | iounmap(priv->regs); |
195 | kfree(priv); | 284 | kfree(priv); |
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index b65c82f792d9..1146e3522d3c 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c | |||
@@ -461,7 +461,7 @@ static struct rtc_class_ops rx8025_rtc_ops = { | |||
461 | * Clock precision adjustment support | 461 | * Clock precision adjustment support |
462 | * | 462 | * |
463 | * According to the RX8025 SA/NB application manual the frequency and | 463 | * According to the RX8025 SA/NB application manual the frequency and |
464 | * temperature charateristics can be approximated using the following | 464 | * temperature characteristics can be approximated using the following |
465 | * equation: | 465 | * equation: |
466 | * | 466 | * |
467 | * df = a * (ut - t)**2 | 467 | * df = a * (ut - t)**2 |
@@ -632,7 +632,6 @@ errout_reg: | |||
632 | rtc_device_unregister(rx8025->rtc); | 632 | rtc_device_unregister(rx8025->rtc); |
633 | 633 | ||
634 | errout_free: | 634 | errout_free: |
635 | i2c_set_clientdata(client, NULL); | ||
636 | kfree(rx8025); | 635 | kfree(rx8025); |
637 | 636 | ||
638 | errout: | 637 | errout: |
@@ -656,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client) | |||
656 | 655 | ||
657 | rx8025_sysfs_unregister(&client->dev); | 656 | rx8025_sysfs_unregister(&client->dev); |
658 | rtc_device_unregister(rx8025->rtc); | 657 | rtc_device_unregister(rx8025->rtc); |
659 | i2c_set_clientdata(client, NULL); | ||
660 | kfree(rx8025); | 658 | kfree(rx8025); |
661 | return 0; | 659 | return 0; |
662 | } | 660 | } |
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index c9522f3bc21c..600b890a3c15 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for the Epson RX8581 RTC | 2 | * An I2C driver for the Epson RX8581 RTC |
3 | * | 3 | * |
4 | * Author: Martyn Welch <martyn.welch@gefanuc.com> | 4 | * Author: Martyn Welch <martyn.welch@ge.com> |
5 | * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 5 | * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. |
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 |
@@ -168,7 +168,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
168 | return -EIO; | 168 | return -EIO; |
169 | } | 169 | } |
170 | 170 | ||
171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | 171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, |
172 | (data | RX8581_CTRL_STOP)); | 172 | (data | RX8581_CTRL_STOP)); |
173 | if (err < 0) { | 173 | if (err < 0) { |
174 | dev_err(&client->dev, "Unable to write control register\n"); | 174 | dev_err(&client->dev, "Unable to write control register\n"); |
@@ -182,6 +182,20 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
182 | return -EIO; | 182 | return -EIO; |
183 | } | 183 | } |
184 | 184 | ||
185 | /* get VLF and clear it */ | ||
186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
187 | if (data < 0) { | ||
188 | dev_err(&client->dev, "Unable to read flag register\n"); | ||
189 | return -EIO; | ||
190 | } | ||
191 | |||
192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
193 | (data & ~(RX8581_FLAG_VLF))); | ||
194 | if (err != 0) { | ||
195 | dev_err(&client->dev, "Unable to write flag register\n"); | ||
196 | return -EIO; | ||
197 | } | ||
198 | |||
185 | /* Restart the clock */ | 199 | /* Restart the clock */ |
186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | 200 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); |
187 | if (data < 0) { | 201 | if (data < 0) { |
@@ -189,8 +203,8 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
189 | return -EIO; | 203 | return -EIO; |
190 | } | 204 | } |
191 | 205 | ||
192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | 206 | err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, |
193 | (data | ~(RX8581_CTRL_STOP))); | 207 | (data & ~(RX8581_CTRL_STOP))); |
194 | if (err != 0) { | 208 | if (err != 0) { |
195 | dev_err(&client->dev, "Unable to write control register\n"); | 209 | dev_err(&client->dev, "Unable to write control register\n"); |
196 | return -EIO; | 210 | return -EIO; |
@@ -272,7 +286,7 @@ static void __exit rx8581_exit(void) | |||
272 | i2c_del_driver(&rx8581_driver); | 286 | i2c_del_driver(&rx8581_driver); |
273 | } | 287 | } |
274 | 288 | ||
275 | MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); | 289 | MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); |
276 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); | 290 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); |
277 | MODULE_LICENSE("GPL"); | 291 | MODULE_LICENSE("GPL"); |
278 | MODULE_VERSION(DRV_VERSION); | 292 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index def4d396d0b0..f789e002c9b0 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c | |||
@@ -275,7 +275,6 @@ exit_dummy: | |||
275 | if (s35390a->client[i]) | 275 | if (s35390a->client[i]) |
276 | i2c_unregister_device(s35390a->client[i]); | 276 | i2c_unregister_device(s35390a->client[i]); |
277 | kfree(s35390a); | 277 | kfree(s35390a); |
278 | i2c_set_clientdata(client, NULL); | ||
279 | 278 | ||
280 | exit: | 279 | exit: |
281 | return err; | 280 | return err; |
@@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client) | |||
292 | 291 | ||
293 | rtc_device_unregister(s35390a->rtc); | 292 | rtc_device_unregister(s35390a->rtc); |
294 | kfree(s35390a); | 293 | kfree(s35390a); |
295 | i2c_set_clientdata(client, NULL); | ||
296 | 294 | ||
297 | return 0; | 295 | return 0; |
298 | } | 296 | } |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 4969b6059c89..a0d3ec89d412 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -1,5 +1,8 @@ | |||
1 | /* drivers/rtc/rtc-s3c.c | 1 | /* drivers/rtc/rtc-s3c.c |
2 | * | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
3 | * Copyright (c) 2004,2006 Simtec Electronics | 6 | * Copyright (c) 2004,2006 Simtec Electronics |
4 | * Ben Dooks, <ben@simtec.co.uk> | 7 | * Ben Dooks, <ben@simtec.co.uk> |
5 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
@@ -29,14 +32,21 @@ | |||
29 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
30 | #include <plat/regs-rtc.h> | 33 | #include <plat/regs-rtc.h> |
31 | 34 | ||
35 | enum s3c_cpu_type { | ||
36 | TYPE_S3C2410, | ||
37 | TYPE_S3C64XX, | ||
38 | }; | ||
39 | |||
32 | /* I have yet to find an S3C implementation with more than one | 40 | /* I have yet to find an S3C implementation with more than one |
33 | * of these rtc blocks in */ | 41 | * of these rtc blocks in */ |
34 | 42 | ||
35 | static struct resource *s3c_rtc_mem; | 43 | static struct resource *s3c_rtc_mem; |
36 | 44 | ||
45 | static struct clk *rtc_clk; | ||
37 | static void __iomem *s3c_rtc_base; | 46 | static void __iomem *s3c_rtc_base; |
38 | static int s3c_rtc_alarmno = NO_IRQ; | 47 | static int s3c_rtc_alarmno = NO_IRQ; |
39 | static int s3c_rtc_tickno = NO_IRQ; | 48 | static int s3c_rtc_tickno = NO_IRQ; |
49 | static enum s3c_cpu_type s3c_rtc_cpu_type; | ||
40 | 50 | ||
41 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 51 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
42 | 52 | ||
@@ -47,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
47 | struct rtc_device *rdev = id; | 57 | struct rtc_device *rdev = id; |
48 | 58 | ||
49 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 59 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
60 | |||
61 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
62 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | ||
63 | |||
50 | return IRQ_HANDLED; | 64 | return IRQ_HANDLED; |
51 | } | 65 | } |
52 | 66 | ||
@@ -55,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
55 | struct rtc_device *rdev = id; | 69 | struct rtc_device *rdev = id; |
56 | 70 | ||
57 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 71 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
72 | |||
73 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
74 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | ||
75 | |||
58 | return IRQ_HANDLED; | 76 | return IRQ_HANDLED; |
59 | } | 77 | } |
60 | 78 | ||
@@ -80,12 +98,25 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
80 | pr_debug("%s: pie=%d\n", __func__, enabled); | 98 | pr_debug("%s: pie=%d\n", __func__, enabled); |
81 | 99 | ||
82 | spin_lock_irq(&s3c_rtc_pie_lock); | 100 | spin_lock_irq(&s3c_rtc_pie_lock); |
83 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | ||
84 | 101 | ||
85 | if (enabled) | 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
86 | tmp |= S3C2410_TICNT_ENABLE; | 103 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); |
104 | tmp &= ~S3C64XX_RTCCON_TICEN; | ||
105 | |||
106 | if (enabled) | ||
107 | tmp |= S3C64XX_RTCCON_TICEN; | ||
108 | |||
109 | writew(tmp, s3c_rtc_base + S3C2410_RTCCON); | ||
110 | } else { | ||
111 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); | ||
112 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
113 | |||
114 | if (enabled) | ||
115 | tmp |= S3C2410_TICNT_ENABLE; | ||
116 | |||
117 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
118 | } | ||
87 | 119 | ||
88 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
89 | spin_unlock_irq(&s3c_rtc_pie_lock); | 120 | spin_unlock_irq(&s3c_rtc_pie_lock); |
90 | 121 | ||
91 | return 0; | 122 | return 0; |
@@ -93,17 +124,23 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
93 | 124 | ||
94 | static int s3c_rtc_setfreq(struct device *dev, int freq) | 125 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
95 | { | 126 | { |
96 | unsigned int tmp; | 127 | struct platform_device *pdev = to_platform_device(dev); |
128 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
129 | unsigned int tmp = 0; | ||
97 | 130 | ||
98 | if (!is_power_of_2(freq)) | 131 | if (!is_power_of_2(freq)) |
99 | return -EINVAL; | 132 | return -EINVAL; |
100 | 133 | ||
101 | spin_lock_irq(&s3c_rtc_pie_lock); | 134 | spin_lock_irq(&s3c_rtc_pie_lock); |
102 | 135 | ||
103 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | 136 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
104 | tmp |= (128 / freq)-1; | 137 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); |
138 | tmp &= S3C2410_TICNT_ENABLE; | ||
139 | } | ||
140 | |||
141 | tmp |= (rtc_dev->max_user_freq / freq)-1; | ||
105 | 142 | ||
106 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 143 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
107 | spin_unlock_irq(&s3c_rtc_pie_lock); | 144 | spin_unlock_irq(&s3c_rtc_pie_lock); |
108 | 145 | ||
109 | return 0; | 146 | return 0; |
@@ -283,10 +320,17 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
283 | 320 | ||
284 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 321 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
285 | { | 322 | { |
286 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 323 | unsigned int ticnt; |
287 | 324 | ||
288 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 325 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
289 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 326 | ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); |
327 | ticnt &= S3C64XX_RTCCON_TICEN; | ||
328 | } else { | ||
329 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | ||
330 | ticnt &= S3C2410_TICNT_ENABLE; | ||
331 | } | ||
332 | |||
333 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); | ||
290 | return 0; | 334 | return 0; |
291 | } | 335 | } |
292 | 336 | ||
@@ -353,10 +397,16 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
353 | 397 | ||
354 | if (!en) { | 398 | if (!en) { |
355 | tmp = readb(base + S3C2410_RTCCON); | 399 | tmp = readb(base + S3C2410_RTCCON); |
356 | writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); | 400 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
357 | 401 | tmp &= ~S3C64XX_RTCCON_TICEN; | |
358 | tmp = readb(base + S3C2410_TICNT); | 402 | tmp &= ~S3C2410_RTCCON_RTCEN; |
359 | writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); | 403 | writeb(tmp, base + S3C2410_RTCCON); |
404 | |||
405 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | ||
406 | tmp = readb(base + S3C2410_TICNT); | ||
407 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
408 | writeb(tmp, base + S3C2410_TICNT); | ||
409 | } | ||
360 | } else { | 410 | } else { |
361 | /* re-enable the device, and check it is ok */ | 411 | /* re-enable the device, and check it is ok */ |
362 | 412 | ||
@@ -393,6 +443,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
393 | s3c_rtc_setpie(&dev->dev, 0); | 443 | s3c_rtc_setpie(&dev->dev, 0); |
394 | s3c_rtc_setaie(0); | 444 | s3c_rtc_setaie(0); |
395 | 445 | ||
446 | clk_disable(rtc_clk); | ||
447 | clk_put(rtc_clk); | ||
448 | rtc_clk = NULL; | ||
449 | |||
396 | iounmap(s3c_rtc_base); | 450 | iounmap(s3c_rtc_base); |
397 | release_resource(s3c_rtc_mem); | 451 | release_resource(s3c_rtc_mem); |
398 | kfree(s3c_rtc_mem); | 452 | kfree(s3c_rtc_mem); |
@@ -404,6 +458,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
404 | { | 458 | { |
405 | struct rtc_device *rtc; | 459 | struct rtc_device *rtc; |
406 | struct resource *res; | 460 | struct resource *res; |
461 | unsigned int tmp, i; | ||
407 | int ret; | 462 | int ret; |
408 | 463 | ||
409 | pr_debug("%s: probe=%p\n", __func__, pdev); | 464 | pr_debug("%s: probe=%p\n", __func__, pdev); |
@@ -450,6 +505,16 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
450 | goto err_nomap; | 505 | goto err_nomap; |
451 | } | 506 | } |
452 | 507 | ||
508 | rtc_clk = clk_get(&pdev->dev, "rtc"); | ||
509 | if (IS_ERR(rtc_clk)) { | ||
510 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
511 | ret = PTR_ERR(rtc_clk); | ||
512 | rtc_clk = NULL; | ||
513 | goto err_clk; | ||
514 | } | ||
515 | |||
516 | clk_enable(rtc_clk); | ||
517 | |||
453 | /* check to see if everything is setup correctly */ | 518 | /* check to see if everything is setup correctly */ |
454 | 519 | ||
455 | s3c_rtc_enable(pdev, 1); | 520 | s3c_rtc_enable(pdev, 1); |
@@ -457,8 +522,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
457 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 522 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
458 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 523 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
459 | 524 | ||
460 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
461 | |||
462 | device_init_wakeup(&pdev->dev, 1); | 525 | device_init_wakeup(&pdev->dev, 1); |
463 | 526 | ||
464 | /* register RTC and exit */ | 527 | /* register RTC and exit */ |
@@ -472,13 +535,34 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
472 | goto err_nortc; | 535 | goto err_nortc; |
473 | } | 536 | } |
474 | 537 | ||
475 | rtc->max_user_freq = 128; | 538 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; |
539 | |||
540 | /* Check RTC Time */ | ||
541 | |||
542 | for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { | ||
543 | tmp = readb(s3c_rtc_base + i); | ||
544 | |||
545 | if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) | ||
546 | writeb(0, s3c_rtc_base + i); | ||
547 | } | ||
548 | |||
549 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
550 | rtc->max_user_freq = 32768; | ||
551 | else | ||
552 | rtc->max_user_freq = 128; | ||
476 | 553 | ||
477 | platform_set_drvdata(pdev, rtc); | 554 | platform_set_drvdata(pdev, rtc); |
555 | |||
556 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
557 | |||
478 | return 0; | 558 | return 0; |
479 | 559 | ||
480 | err_nortc: | 560 | err_nortc: |
481 | s3c_rtc_enable(pdev, 0); | 561 | s3c_rtc_enable(pdev, 0); |
562 | clk_disable(rtc_clk); | ||
563 | clk_put(rtc_clk); | ||
564 | |||
565 | err_clk: | ||
482 | iounmap(s3c_rtc_base); | 566 | iounmap(s3c_rtc_base); |
483 | 567 | ||
484 | err_nomap: | 568 | err_nomap: |
@@ -492,20 +576,30 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
492 | 576 | ||
493 | /* RTC Power management control */ | 577 | /* RTC Power management control */ |
494 | 578 | ||
495 | static int ticnt_save; | 579 | static int ticnt_save, ticnt_en_save; |
496 | 580 | ||
497 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 581 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
498 | { | 582 | { |
499 | /* save TICNT for anyone using periodic interrupts */ | 583 | /* save TICNT for anyone using periodic interrupts */ |
500 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 584 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
585 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | ||
586 | ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); | ||
587 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | ||
588 | } | ||
501 | s3c_rtc_enable(pdev, 0); | 589 | s3c_rtc_enable(pdev, 0); |
502 | return 0; | 590 | return 0; |
503 | } | 591 | } |
504 | 592 | ||
505 | static int s3c_rtc_resume(struct platform_device *pdev) | 593 | static int s3c_rtc_resume(struct platform_device *pdev) |
506 | { | 594 | { |
595 | unsigned int tmp; | ||
596 | |||
507 | s3c_rtc_enable(pdev, 1); | 597 | s3c_rtc_enable(pdev, 1); |
508 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 598 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
599 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | ||
600 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | ||
601 | writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | ||
602 | } | ||
509 | return 0; | 603 | return 0; |
510 | } | 604 | } |
511 | #else | 605 | #else |
@@ -513,13 +607,27 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
513 | #define s3c_rtc_resume NULL | 607 | #define s3c_rtc_resume NULL |
514 | #endif | 608 | #endif |
515 | 609 | ||
516 | static struct platform_driver s3c2410_rtc_driver = { | 610 | static struct platform_device_id s3c_rtc_driver_ids[] = { |
611 | { | ||
612 | .name = "s3c2410-rtc", | ||
613 | .driver_data = TYPE_S3C2410, | ||
614 | }, { | ||
615 | .name = "s3c64xx-rtc", | ||
616 | .driver_data = TYPE_S3C64XX, | ||
617 | }, | ||
618 | { } | ||
619 | }; | ||
620 | |||
621 | MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); | ||
622 | |||
623 | static struct platform_driver s3c_rtc_driver = { | ||
517 | .probe = s3c_rtc_probe, | 624 | .probe = s3c_rtc_probe, |
518 | .remove = __devexit_p(s3c_rtc_remove), | 625 | .remove = __devexit_p(s3c_rtc_remove), |
519 | .suspend = s3c_rtc_suspend, | 626 | .suspend = s3c_rtc_suspend, |
520 | .resume = s3c_rtc_resume, | 627 | .resume = s3c_rtc_resume, |
628 | .id_table = s3c_rtc_driver_ids, | ||
521 | .driver = { | 629 | .driver = { |
522 | .name = "s3c2410-rtc", | 630 | .name = "s3c-rtc", |
523 | .owner = THIS_MODULE, | 631 | .owner = THIS_MODULE, |
524 | }, | 632 | }, |
525 | }; | 633 | }; |
@@ -529,12 +637,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics | |||
529 | static int __init s3c_rtc_init(void) | 637 | static int __init s3c_rtc_init(void) |
530 | { | 638 | { |
531 | printk(banner); | 639 | printk(banner); |
532 | return platform_driver_register(&s3c2410_rtc_driver); | 640 | return platform_driver_register(&s3c_rtc_driver); |
533 | } | 641 | } |
534 | 642 | ||
535 | static void __exit s3c_rtc_exit(void) | 643 | static void __exit s3c_rtc_exit(void) |
536 | { | 644 | { |
537 | platform_driver_unregister(&s3c2410_rtc_driver); | 645 | platform_driver_unregister(&s3c_rtc_driver); |
538 | } | 646 | } |
539 | 647 | ||
540 | module_init(s3c_rtc_init); | 648 | module_init(s3c_rtc_init); |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 875ba099e7a5..3b943673cd3e 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * A RTC driver for the Simtek STK17TA8 | 2 | * A RTC driver for the Simtek STK17TA8 |
3 | * | 3 | * |
4 | * By Thomas Hommel <thomas.hommel@gefanuc.com> | 4 | * By Thomas Hommel <thomas.hommel@ge.com> |
5 | * | 5 | * |
6 | * Based on the DS1553 driver from | 6 | * Based on the DS1553 driver from |
7 | * Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 7 | * Atsushi Nemoto <anemo@mba.ocn.ne.jp> |
@@ -244,7 +244,7 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { | |||
244 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, | 244 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | 247 | static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, |
248 | struct bin_attribute *attr, char *buf, | 248 | struct bin_attribute *attr, char *buf, |
249 | loff_t pos, size_t size) | 249 | loff_t pos, size_t size) |
250 | { | 250 | { |
@@ -259,7 +259,7 @@ static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | |||
259 | return count; | 259 | return count; |
260 | } | 260 | } |
261 | 261 | ||
262 | static ssize_t stk17ta8_nvram_write(struct kobject *kobj, | 262 | static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, |
263 | struct bin_attribute *attr, char *buf, | 263 | struct bin_attribute *attr, char *buf, |
264 | loff_t pos, size_t size) | 264 | loff_t pos, size_t size) |
265 | { | 265 | { |
@@ -382,7 +382,7 @@ static __exit void stk17ta8_exit(void) | |||
382 | module_init(stk17ta8_init); | 382 | module_init(stk17ta8_init); |
383 | module_exit(stk17ta8_exit); | 383 | module_exit(stk17ta8_exit); |
384 | 384 | ||
385 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@gefanuc.com>"); | 385 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); |
386 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); | 386 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); |
387 | MODULE_LICENSE("GPL"); | 387 | MODULE_LICENSE("GPL"); |
388 | MODULE_VERSION(DRV_VERSION); | 388 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 20bfc64a15c8..ec6313d15359 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -188,7 +188,7 @@ static const struct rtc_class_ops tx4939_rtc_ops = { | |||
188 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, | 188 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | 191 | static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, |
192 | struct bin_attribute *bin_attr, | 192 | struct bin_attribute *bin_attr, |
193 | char *buf, loff_t pos, size_t size) | 193 | char *buf, loff_t pos, size_t size) |
194 | { | 194 | { |
@@ -207,7 +207,7 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
207 | return count; | 207 | return count; |
208 | } | 208 | } |
209 | 209 | ||
210 | static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | 210 | static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, |
211 | struct bin_attribute *bin_attr, | 211 | struct bin_attribute *bin_attr, |
212 | char *buf, loff_t pos, size_t size) | 212 | char *buf, loff_t pos, size_t size) |
213 | { | 213 | { |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index b16cfe57a484..82931dc65c0b 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -449,17 +449,17 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
449 | goto err; | 449 | goto err; |
450 | } | 450 | } |
451 | 451 | ||
452 | ret = wm831x_request_irq(wm831x, per_irq, wm831x_per_irq, | 452 | ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq, |
453 | IRQF_TRIGGER_RISING, "wm831x_rtc_per", | 453 | IRQF_TRIGGER_RISING, "RTC period", |
454 | wm831x_rtc); | 454 | wm831x_rtc); |
455 | if (ret != 0) { | 455 | if (ret != 0) { |
456 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", | 456 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", |
457 | per_irq, ret); | 457 | per_irq, ret); |
458 | } | 458 | } |
459 | 459 | ||
460 | ret = wm831x_request_irq(wm831x, alm_irq, wm831x_alm_irq, | 460 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, |
461 | IRQF_TRIGGER_RISING, "wm831x_rtc_alm", | 461 | IRQF_TRIGGER_RISING, "RTC alarm", |
462 | wm831x_rtc); | 462 | wm831x_rtc); |
463 | if (ret != 0) { | 463 | if (ret != 0) { |
464 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | 464 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", |
465 | alm_irq, ret); | 465 | alm_irq, ret); |
@@ -478,8 +478,8 @@ static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | |||
478 | int per_irq = platform_get_irq_byname(pdev, "PER"); | 478 | int per_irq = platform_get_irq_byname(pdev, "PER"); |
479 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | 479 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); |
480 | 480 | ||
481 | wm831x_free_irq(wm831x_rtc->wm831x, alm_irq, wm831x_rtc); | 481 | free_irq(alm_irq, wm831x_rtc); |
482 | wm831x_free_irq(wm831x_rtc->wm831x, per_irq, wm831x_rtc); | 482 | free_irq(per_irq, wm831x_rtc); |
483 | rtc_device_unregister(wm831x_rtc->rtc); | 483 | rtc_device_unregister(wm831x_rtc->rtc); |
484 | kfree(wm831x_rtc); | 484 | kfree(wm831x_rtc); |
485 | 485 | ||