diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:20:30 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:21:47 -0500 |
commit | d392da5207352f09030e95d9ea335a4225667ec0 (patch) | |
tree | 7d6cd1932afcad0a5619a5c504a6d93ca318187c /drivers/rtc | |
parent | e39d5ef678045d61812c1401f04fe8edb14d6359 (diff) | |
parent | 387c31c7e5c9805b0aef8833d1731a5fe7bdea14 (diff) |
Merge v2.6.37-rc8 into powerpc/next
Diffstat (limited to 'drivers/rtc')
33 files changed, 3130 insertions, 721 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4301a6c7ed3b..2883428d5ac8 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -166,6 +166,17 @@ 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. If an interrupt is associated | ||
175 | with the device, the alarm functionality is supported. | ||
176 | |||
177 | This driver can also be built as a module. If so, the module | ||
178 | will be called rtc-ds3232. | ||
179 | |||
169 | config RTC_DRV_MAX6900 | 180 | config RTC_DRV_MAX6900 |
170 | tristate "Maxim MAX6900" | 181 | tristate "Maxim MAX6900" |
171 | help | 182 | help |
@@ -185,6 +196,16 @@ config RTC_DRV_MAX8925 | |||
185 | This driver can also be built as a module. If so, the module | 196 | This driver can also be built as a module. If so, the module |
186 | will be called rtc-max8925. | 197 | will be called rtc-max8925. |
187 | 198 | ||
199 | config RTC_DRV_MAX8998 | ||
200 | tristate "Maxim MAX8998" | ||
201 | depends on MFD_MAX8998 | ||
202 | help | ||
203 | If you say yes here you will get support for the | ||
204 | RTC of Maxim MAX8998 PMIC. | ||
205 | |||
206 | This driver can also be built as a module. If so, the module | ||
207 | will be called rtc-max8998. | ||
208 | |||
188 | config RTC_DRV_RS5C372 | 209 | config RTC_DRV_RS5C372 |
189 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 210 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
190 | help | 211 | help |
@@ -203,6 +224,15 @@ config RTC_DRV_ISL1208 | |||
203 | This driver can also be built as a module. If so, the module | 224 | This driver can also be built as a module. If so, the module |
204 | will be called rtc-isl1208. | 225 | will be called rtc-isl1208. |
205 | 226 | ||
227 | config RTC_DRV_ISL12022 | ||
228 | tristate "Intersil ISL12022" | ||
229 | help | ||
230 | If you say yes here you get support for the | ||
231 | Intersil ISL12022 RTC chip. | ||
232 | |||
233 | This driver can also be built as a module. If so, the module | ||
234 | will be called rtc-isl12022. | ||
235 | |||
206 | config RTC_DRV_X1205 | 236 | config RTC_DRV_X1205 |
207 | tristate "Xicor/Intersil X1205" | 237 | tristate "Xicor/Intersil X1205" |
208 | help | 238 | help |
@@ -537,6 +567,16 @@ config RTC_DRV_MSM6242 | |||
537 | This driver can also be built as a module. If so, the module | 567 | This driver can also be built as a module. If so, the module |
538 | will be called rtc-msm6242. | 568 | will be called rtc-msm6242. |
539 | 569 | ||
570 | config RTC_DRV_IMXDI | ||
571 | tristate "Freescale IMX DryIce Real Time Clock" | ||
572 | depends on ARCH_MX25 | ||
573 | depends on RTC_CLASS | ||
574 | help | ||
575 | Support for Freescale IMX DryIce RTC | ||
576 | |||
577 | This driver can also be built as a module, if so, the module | ||
578 | will be called "rtc-imxdi". | ||
579 | |||
540 | config RTC_MXC | 580 | config RTC_MXC |
541 | tristate "Freescale MXC Real Time Clock" | 581 | tristate "Freescale MXC Real Time Clock" |
542 | depends on ARCH_MXC | 582 | depends on ARCH_MXC |
@@ -645,9 +685,16 @@ config RTC_DRV_OMAP | |||
645 | DA8xx/OMAP-L13x chips. This driver can also be built as a | 685 | DA8xx/OMAP-L13x chips. This driver can also be built as a |
646 | module called rtc-omap. | 686 | module called rtc-omap. |
647 | 687 | ||
688 | config HAVE_S3C_RTC | ||
689 | bool | ||
690 | help | ||
691 | This will include RTC support for Samsung SoCs. If | ||
692 | you want to include RTC support for any machine, kindly | ||
693 | select this in the respective mach-XXXX/Kconfig file. | ||
694 | |||
648 | config RTC_DRV_S3C | 695 | config RTC_DRV_S3C |
649 | tristate "Samsung S3C series SoC RTC" | 696 | tristate "Samsung S3C series SoC RTC" |
650 | depends on ARCH_S3C2410 || ARCH_S3C64XX | 697 | depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC |
651 | help | 698 | help |
652 | RTC (Realtime Clock) driver for the clock inbuilt into the | 699 | RTC (Realtime Clock) driver for the clock inbuilt into the |
653 | Samsung S3C24XX series of SoCs. This can provide periodic | 700 | Samsung S3C24XX series of SoCs. This can provide periodic |
@@ -729,15 +776,15 @@ config RTC_DRV_AT32AP700X | |||
729 | AT32AP700x family processors. | 776 | AT32AP700x family processors. |
730 | 777 | ||
731 | config RTC_DRV_AT91RM9200 | 778 | config RTC_DRV_AT91RM9200 |
732 | tristate "AT91RM9200 or AT91SAM9RL" | 779 | tristate "AT91RM9200 or some AT91SAM9 RTC" |
733 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL | 780 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
734 | help | 781 | help |
735 | Driver for the internal RTC (Realtime Clock) module found on | 782 | Driver for the internal RTC (Realtime Clock) module found on |
736 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | 783 | Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips |
737 | this is powered by the backup power supply. | 784 | this is powered by the backup power supply. |
738 | 785 | ||
739 | config RTC_DRV_AT91SAM9 | 786 | config RTC_DRV_AT91SAM9 |
740 | tristate "AT91SAM9x/AT91CAP9" | 787 | tristate "AT91SAM9x/AT91CAP9 RTT as RTC" |
741 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | 788 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) |
742 | help | 789 | help |
743 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT | 790 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT |
@@ -745,8 +792,8 @@ config RTC_DRV_AT91SAM9 | |||
745 | supply (such as a small coin cell battery), but do not need to | 792 | supply (such as a small coin cell battery), but do not need to |
746 | be used as RTCs. | 793 | be used as RTCs. |
747 | 794 | ||
748 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | 795 | (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the |
749 | module and leave the RTT available for other uses.) | 796 | dedicated RTC module and leave the RTT available for other uses.) |
750 | 797 | ||
751 | config RTC_DRV_AT91SAM9_RTT | 798 | config RTC_DRV_AT91SAM9_RTT |
752 | int | 799 | int |
@@ -889,11 +936,12 @@ config RTC_DRV_PCAP | |||
889 | If you say Y here you will get support for the RTC found on | 936 | If you say Y here you will get support for the RTC found on |
890 | the PCAP2 ASIC used on some Motorola phones. | 937 | the PCAP2 ASIC used on some Motorola phones. |
891 | 938 | ||
892 | config RTC_DRV_MC13783 | 939 | config RTC_DRV_MC13XXX |
893 | depends on MFD_MC13783 | 940 | depends on MFD_MC13XXX |
894 | tristate "Freescale MC13783 RTC" | 941 | tristate "Freescale MC13xxx RTC" |
895 | help | 942 | help |
896 | This enables support for the Freescale MC13783 PMIC RTC | 943 | This enables support for the RTCs found on Freescale's PMICs |
944 | MC13783 and MC13892. | ||
897 | 945 | ||
898 | config RTC_DRV_MPC5121 | 946 | config RTC_DRV_MPC5121 |
899 | tristate "Freescale MPC5121 built-in RTC" | 947 | tristate "Freescale MPC5121 built-in RTC" |
@@ -916,4 +964,13 @@ config RTC_DRV_JZ4740 | |||
916 | This driver can also be buillt as a module. If so, the module | 964 | This driver can also be buillt as a module. If so, the module |
917 | will be called rtc-jz4740. | 965 | will be called rtc-jz4740. |
918 | 966 | ||
967 | config RTC_DRV_LPC32XX | ||
968 | depends on ARCH_LPC32XX | ||
969 | tristate "NXP LPC32XX RTC" | ||
970 | help | ||
971 | This enables support for the NXP RTC in the LPC32XX | ||
972 | |||
973 | This driver can also be buillt as a module. If so, the module | ||
974 | will be called rtc-lpc32xx. | ||
975 | |||
919 | endif # RTC_CLASS | 976 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index fedf9bb36593..4c2832df4697 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -41,13 +41,17 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
41 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 41 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
42 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 42 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
43 | 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 | ||
44 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 45 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
45 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 46 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
46 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 47 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
47 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 48 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
48 | 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 | ||
49 | 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 | ||
50 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
54 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | ||
51 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 55 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
52 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 56 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
53 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 57 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
@@ -56,8 +60,9 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | |||
56 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 60 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
57 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 61 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
58 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 62 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
63 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | ||
59 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 64 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
60 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | 65 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
61 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 66 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
62 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 67 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
63 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 68 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 565562ba6ac9..e6539cbabb35 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -158,8 +158,10 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
158 | rtc_dev_prepare(rtc); | 158 | rtc_dev_prepare(rtc); |
159 | 159 | ||
160 | err = device_register(&rtc->dev); | 160 | err = device_register(&rtc->dev); |
161 | if (err) | 161 | if (err) { |
162 | put_device(&rtc->dev); | ||
162 | goto exit_kfree; | 163 | goto exit_kfree; |
164 | } | ||
163 | 165 | ||
164 | rtc_dev_add_device(rtc); | 166 | rtc_dev_add_device(rtc); |
165 | rtc_sysfs_add_device(rtc); | 167 | rtc_sysfs_add_device(rtc); |
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index d26780ea254b..261a07e0fb24 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c | |||
@@ -235,6 +235,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
235 | err = PTR_ERR(rtc); | 235 | err = PTR_ERR(rtc); |
236 | return err; | 236 | return err; |
237 | } | 237 | } |
238 | platform_set_drvdata(pdev, rtc); | ||
238 | 239 | ||
239 | return 0; | 240 | return 0; |
240 | } | 241 | } |
@@ -244,6 +245,7 @@ static int __exit ab3100_rtc_remove(struct platform_device *pdev) | |||
244 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 245 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
245 | 246 | ||
246 | rtc_device_unregister(rtc); | 247 | rtc_device_unregister(rtc); |
248 | platform_set_drvdata(pdev, NULL); | ||
247 | return 0; | 249 | return 0; |
248 | } | 250 | } |
249 | 251 | ||
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 2fda03125e55..e346705aae92 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -14,26 +14,26 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/mfd/abx500.h> | ||
17 | #include <linux/mfd/ab8500.h> | 18 | #include <linux/mfd/ab8500.h> |
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | 20 | ||
20 | #define AB8500_RTC_SOFF_STAT_REG 0x0F00 | 21 | #define AB8500_RTC_SOFF_STAT_REG 0x00 |
21 | #define AB8500_RTC_CC_CONF_REG 0x0F01 | 22 | #define AB8500_RTC_CC_CONF_REG 0x01 |
22 | #define AB8500_RTC_READ_REQ_REG 0x0F02 | 23 | #define AB8500_RTC_READ_REQ_REG 0x02 |
23 | #define AB8500_RTC_WATCH_TSECMID_REG 0x0F03 | 24 | #define AB8500_RTC_WATCH_TSECMID_REG 0x03 |
24 | #define AB8500_RTC_WATCH_TSECHI_REG 0x0F04 | 25 | #define AB8500_RTC_WATCH_TSECHI_REG 0x04 |
25 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | 26 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x05 |
26 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06 | 27 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x06 |
27 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07 | 28 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x07 |
28 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08 | 29 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x08 |
29 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09 | 30 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x09 |
30 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A | 31 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0A |
31 | #define AB8500_RTC_STAT_REG 0x0F0B | 32 | #define AB8500_RTC_STAT_REG 0x0B |
32 | #define AB8500_RTC_BKUP_CHG_REG 0x0F0C | 33 | #define AB8500_RTC_BKUP_CHG_REG 0x0C |
33 | #define AB8500_RTC_FORCE_BKUP_REG 0x0F0D | 34 | #define AB8500_RTC_FORCE_BKUP_REG 0x0D |
34 | #define AB8500_RTC_CALIB_REG 0x0F0E | 35 | #define AB8500_RTC_CALIB_REG 0x0E |
35 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F0F | 36 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F |
36 | #define AB8500_REV_REG 0x1080 | ||
37 | 37 | ||
38 | /* RtcReadRequest bits */ | 38 | /* RtcReadRequest bits */ |
39 | #define RTC_READ_REQUEST 0x01 | 39 | #define RTC_READ_REQUEST 0x01 |
@@ -46,13 +46,13 @@ | |||
46 | #define COUNTS_PER_SEC (0xF000 / 60) | 46 | #define COUNTS_PER_SEC (0xF000 / 60) |
47 | #define AB8500_RTC_EPOCH 2000 | 47 | #define AB8500_RTC_EPOCH 2000 |
48 | 48 | ||
49 | static const unsigned long ab8500_rtc_time_regs[] = { | 49 | static const u8 ab8500_rtc_time_regs[] = { |
50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, | 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, | 51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, |
52 | AB8500_RTC_WATCH_TSECMID_REG | 52 | AB8500_RTC_WATCH_TSECMID_REG |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static const unsigned long ab8500_rtc_alarm_regs[] = { | 55 | static const u8 ab8500_rtc_alarm_regs[] = { |
56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, | 56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, |
57 | AB8500_RTC_ALRM_MIN_LOW_REG | 57 | AB8500_RTC_ALRM_MIN_LOW_REG |
58 | }; | 58 | }; |
@@ -76,29 +76,30 @@ static unsigned long get_elapsed_seconds(int year) | |||
76 | 76 | ||
77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | 77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) |
78 | { | 78 | { |
79 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
80 | unsigned long timeout = jiffies + HZ; | 79 | unsigned long timeout = jiffies + HZ; |
81 | int retval, i; | 80 | int retval, i; |
82 | unsigned long mins, secs; | 81 | unsigned long mins, secs; |
83 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | 82 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; |
83 | u8 value; | ||
84 | 84 | ||
85 | /* Request a data read */ | 85 | /* Request a data read */ |
86 | retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, | 86 | retval = abx500_set_register_interruptible(dev, |
87 | RTC_READ_REQUEST); | 87 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, RTC_READ_REQUEST); |
88 | if (retval < 0) | 88 | if (retval < 0) |
89 | return retval; | 89 | return retval; |
90 | 90 | ||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | 91 | /* Early AB8500 chips will not clear the rtc read request bit */ |
92 | if (ab8500->revision == 0) { | 92 | if (abx500_get_chip_id(dev) == 0) { |
93 | msleep(1); | 93 | msleep(1); |
94 | } else { | 94 | } else { |
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | 95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ |
96 | while (time_before(jiffies, timeout)) { | 96 | while (time_before(jiffies, timeout)) { |
97 | retval = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG); | 97 | retval = abx500_get_register_interruptible(dev, |
98 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); | ||
98 | if (retval < 0) | 99 | if (retval < 0) |
99 | return retval; | 100 | return retval; |
100 | 101 | ||
101 | if (!(retval & RTC_READ_REQUEST)) | 102 | if (!(value & RTC_READ_REQUEST)) |
102 | break; | 103 | break; |
103 | 104 | ||
104 | msleep(1); | 105 | msleep(1); |
@@ -107,10 +108,11 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
107 | 108 | ||
108 | /* Read the Watchtime registers */ | 109 | /* Read the Watchtime registers */ |
109 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | 110 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { |
110 | retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]); | 111 | retval = abx500_get_register_interruptible(dev, |
112 | AB8500_RTC, ab8500_rtc_time_regs[i], &value); | ||
111 | if (retval < 0) | 113 | if (retval < 0) |
112 | return retval; | 114 | return retval; |
113 | buf[i] = retval; | 115 | buf[i] = value; |
114 | } | 116 | } |
115 | 117 | ||
116 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | 118 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; |
@@ -128,7 +130,6 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
128 | 130 | ||
129 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | 131 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) |
130 | { | 132 | { |
131 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
132 | int retval, i; | 133 | int retval, i; |
133 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | 134 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; |
134 | unsigned long no_secs, no_mins, secs = 0; | 135 | unsigned long no_secs, no_mins, secs = 0; |
@@ -162,27 +163,29 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
162 | buf[0] = (no_mins >> 16) & 0xFF; | 163 | buf[0] = (no_mins >> 16) & 0xFF; |
163 | 164 | ||
164 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | 165 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { |
165 | retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]); | 166 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, |
167 | ab8500_rtc_time_regs[i], buf[i]); | ||
166 | if (retval < 0) | 168 | if (retval < 0) |
167 | return retval; | 169 | return retval; |
168 | } | 170 | } |
169 | 171 | ||
170 | /* Request a data write */ | 172 | /* Request a data write */ |
171 | return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | 173 | return abx500_set_register_interruptible(dev, AB8500_RTC, |
174 | AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
172 | } | 175 | } |
173 | 176 | ||
174 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 177 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
175 | { | 178 | { |
176 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
177 | int retval, i; | 179 | int retval, i; |
178 | int rtc_ctrl; | 180 | u8 rtc_ctrl, value; |
179 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | 181 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; |
180 | unsigned long secs, mins; | 182 | unsigned long secs, mins; |
181 | 183 | ||
182 | /* Check if the alarm is enabled or not */ | 184 | /* Check if the alarm is enabled or not */ |
183 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | 185 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, |
184 | if (rtc_ctrl < 0) | 186 | AB8500_RTC_STAT_REG, &rtc_ctrl); |
185 | return rtc_ctrl; | 187 | if (retval < 0) |
188 | return retval; | ||
186 | 189 | ||
187 | if (rtc_ctrl & RTC_ALARM_ENA) | 190 | if (rtc_ctrl & RTC_ALARM_ENA) |
188 | alarm->enabled = 1; | 191 | alarm->enabled = 1; |
@@ -192,10 +195,11 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
192 | alarm->pending = 0; | 195 | alarm->pending = 0; |
193 | 196 | ||
194 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | 197 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { |
195 | retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]); | 198 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, |
199 | ab8500_rtc_alarm_regs[i], &value); | ||
196 | if (retval < 0) | 200 | if (retval < 0) |
197 | return retval; | 201 | return retval; |
198 | buf[i] = retval; | 202 | buf[i] = value; |
199 | } | 203 | } |
200 | 204 | ||
201 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | 205 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); |
@@ -211,15 +215,13 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
211 | 215 | ||
212 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | 216 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) |
213 | { | 217 | { |
214 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | 218 | return abx500_mask_and_set_register_interruptible(dev, AB8500_RTC, |
215 | 219 | AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | |
216 | return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | 220 | enabled ? RTC_ALARM_ENA : 0); |
217 | enabled ? RTC_ALARM_ENA : 0); | ||
218 | } | 221 | } |
219 | 222 | ||
220 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 223 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
221 | { | 224 | { |
222 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
223 | int retval, i; | 225 | int retval, i; |
224 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | 226 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; |
225 | unsigned long mins, secs = 0; | 227 | unsigned long mins, secs = 0; |
@@ -247,7 +249,8 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
247 | 249 | ||
248 | /* Set the alarm time */ | 250 | /* Set the alarm time */ |
249 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | 251 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { |
250 | retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]); | 252 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, |
253 | ab8500_rtc_alarm_regs[i], buf[i]); | ||
251 | if (retval < 0) | 254 | if (retval < 0) |
252 | return retval; | 255 | return retval; |
253 | } | 256 | } |
@@ -276,10 +279,9 @@ static const struct rtc_class_ops ab8500_rtc_ops = { | |||
276 | 279 | ||
277 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | 280 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) |
278 | { | 281 | { |
279 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
280 | int err; | 282 | int err; |
281 | struct rtc_device *rtc; | 283 | struct rtc_device *rtc; |
282 | int rtc_ctrl; | 284 | u8 rtc_ctrl; |
283 | int irq; | 285 | int irq; |
284 | 286 | ||
285 | irq = platform_get_irq_byname(pdev, "ALARM"); | 287 | irq = platform_get_irq_byname(pdev, "ALARM"); |
@@ -287,17 +289,18 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
287 | return irq; | 289 | return irq; |
288 | 290 | ||
289 | /* For RTC supply test */ | 291 | /* For RTC supply test */ |
290 | err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA, | 292 | err = abx500_mask_and_set_register_interruptible(&pdev->dev, AB8500_RTC, |
291 | RTC_STATUS_DATA); | 293 | AB8500_RTC_STAT_REG, RTC_STATUS_DATA, RTC_STATUS_DATA); |
292 | if (err < 0) | 294 | if (err < 0) |
293 | return err; | 295 | return err; |
294 | 296 | ||
295 | /* Wait for reset by the PorRtc */ | 297 | /* Wait for reset by the PorRtc */ |
296 | msleep(1); | 298 | msleep(1); |
297 | 299 | ||
298 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | 300 | err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, |
299 | if (rtc_ctrl < 0) | 301 | AB8500_RTC_STAT_REG, &rtc_ctrl); |
300 | return rtc_ctrl; | 302 | if (err < 0) |
303 | return err; | ||
301 | 304 | ||
302 | /* Check if the RTC Supply fails */ | 305 | /* Check if the RTC Supply fails */ |
303 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | 306 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 72b2bcc2c224..b4b6087f2234 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
4 | * | 4 | * |
5 | * Copyright 2004-2009 Analog Devices Inc. | 5 | * Copyright 2004-2010 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -183,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
184 | unsigned long events = 0; | 184 | unsigned long events = 0; |
185 | bool write_complete = false; | 185 | bool write_complete = false; |
186 | u16 rtc_istat, rtc_ictl; | 186 | u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; |
187 | 187 | ||
188 | dev_dbg_stamp(dev); | 188 | dev_dbg_stamp(dev); |
189 | 189 | ||
190 | rtc_istat = bfin_read_RTC_ISTAT(); | 190 | rtc_istat = bfin_read_RTC_ISTAT(); |
191 | rtc_ictl = bfin_read_RTC_ICTL(); | 191 | rtc_ictl = bfin_read_RTC_ICTL(); |
192 | rtc_istat_clear = 0; | ||
192 | 193 | ||
193 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { | 194 | bits = RTC_ISTAT_WRITE_COMPLETE; |
194 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 195 | if (rtc_istat & bits) { |
196 | rtc_istat_clear |= bits; | ||
195 | write_complete = true; | 197 | write_complete = true; |
196 | complete(&bfin_write_complete); | 198 | complete(&bfin_write_complete); |
197 | } | 199 | } |
198 | 200 | ||
199 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 201 | bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
200 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 202 | if (rtc_ictl & bits) { |
201 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 203 | if (rtc_istat & bits) { |
204 | rtc_istat_clear |= bits; | ||
202 | events |= RTC_AF | RTC_IRQF; | 205 | events |= RTC_AF | RTC_IRQF; |
203 | } | 206 | } |
204 | } | 207 | } |
205 | 208 | ||
206 | if (rtc_ictl & RTC_ISTAT_SEC) { | 209 | bits = RTC_ISTAT_SEC; |
207 | if (rtc_istat & RTC_ISTAT_SEC) { | 210 | if (rtc_ictl & bits) { |
208 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 211 | if (rtc_istat & bits) { |
212 | rtc_istat_clear |= bits; | ||
209 | events |= RTC_UF | RTC_IRQF; | 213 | events |= RTC_UF | RTC_IRQF; |
210 | } | 214 | } |
211 | } | 215 | } |
@@ -213,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
213 | if (events) | 217 | if (events) |
214 | rtc_update_irq(rtc->rtc_dev, 1, events); | 218 | rtc_update_irq(rtc->rtc_dev, 1, events); |
215 | 219 | ||
216 | if (write_complete || events) | 220 | if (write_complete || events) { |
221 | bfin_write_RTC_ISTAT(rtc_istat_clear); | ||
217 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
218 | else | 223 | } else |
219 | return IRQ_NONE; | 224 | return IRQ_NONE; |
220 | } | 225 | } |
221 | 226 | ||
@@ -422,21 +427,38 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
422 | #ifdef CONFIG_PM | 427 | #ifdef CONFIG_PM |
423 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 428 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
424 | { | 429 | { |
425 | if (device_may_wakeup(&pdev->dev)) { | 430 | struct device *dev = &pdev->dev; |
431 | |||
432 | dev_dbg_stamp(dev); | ||
433 | |||
434 | if (device_may_wakeup(dev)) { | ||
426 | enable_irq_wake(IRQ_RTC); | 435 | enable_irq_wake(IRQ_RTC); |
427 | bfin_rtc_sync_pending(&pdev->dev); | 436 | bfin_rtc_sync_pending(dev); |
428 | } else | 437 | } else |
429 | bfin_rtc_int_clear(-1); | 438 | bfin_rtc_int_clear(0); |
430 | 439 | ||
431 | return 0; | 440 | return 0; |
432 | } | 441 | } |
433 | 442 | ||
434 | static int bfin_rtc_resume(struct platform_device *pdev) | 443 | static int bfin_rtc_resume(struct platform_device *pdev) |
435 | { | 444 | { |
436 | if (device_may_wakeup(&pdev->dev)) | 445 | struct device *dev = &pdev->dev; |
446 | |||
447 | dev_dbg_stamp(dev); | ||
448 | |||
449 | if (device_may_wakeup(dev)) | ||
437 | disable_irq_wake(IRQ_RTC); | 450 | disable_irq_wake(IRQ_RTC); |
438 | else | 451 | |
439 | bfin_write_RTC_ISTAT(-1); | 452 | /* |
453 | * Since only some of the RTC bits are maintained externally in the | ||
454 | * Vbat domain, we need to wait for the RTC MMRs to be synced into | ||
455 | * the core after waking up. This happens every RTC 1HZ. Once that | ||
456 | * has happened, we can go ahead and re-enable the important write | ||
457 | * complete interrupt event. | ||
458 | */ | ||
459 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) | ||
460 | continue; | ||
461 | bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); | ||
440 | 462 | ||
441 | return 0; | 463 | return 0; |
442 | } | 464 | } |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 11b8ea29d2b7..5856167a0c90 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -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-ds1302.c b/drivers/rtc/rtc-ds1302.c index 359d1e04626c..f0d638922644 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #ifdef CONFIG_SH_SECUREEDGE5410 | 36 | #ifdef CONFIG_SH_SECUREEDGE5410 |
37 | #include <asm/rtc.h> | 37 | #include <asm/rtc.h> |
38 | #include <mach/snapgear.h> | 38 | #include <mach/secureedge5410.h> |
39 | 39 | ||
40 | #define RTC_RESET 0x1000 | 40 | #define RTC_RESET 0x1000 |
41 | #define RTC_IODATA 0x0800 | 41 | #define RTC_IODATA 0x0800 |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c new file mode 100644 index 000000000000..57063552d3b7 --- /dev/null +++ b/drivers/rtc/rtc-ds3232.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | ||
5 | * Author: Jack Lan <jack.lan@freescale.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | /* | ||
13 | * It would be more efficient to use i2c msgs/i2c_transfer directly but, as | ||
14 | * recommened in .../Documentation/i2c/writing-clients section | ||
15 | * "Sending and receiving", using SMBus level communication is preferred. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #define DS3232_REG_SECONDS 0x00 | ||
28 | #define DS3232_REG_MINUTES 0x01 | ||
29 | #define DS3232_REG_HOURS 0x02 | ||
30 | #define DS3232_REG_AMPM 0x02 | ||
31 | #define DS3232_REG_DAY 0x03 | ||
32 | #define DS3232_REG_DATE 0x04 | ||
33 | #define DS3232_REG_MONTH 0x05 | ||
34 | #define DS3232_REG_CENTURY 0x05 | ||
35 | #define DS3232_REG_YEAR 0x06 | ||
36 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ | ||
37 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ | ||
38 | #define DS3232_REG_CR 0x0E /* Control register */ | ||
39 | # define DS3232_REG_CR_nEOSC 0x80 | ||
40 | # define DS3232_REG_CR_INTCN 0x04 | ||
41 | # define DS3232_REG_CR_A2IE 0x02 | ||
42 | # define DS3232_REG_CR_A1IE 0x01 | ||
43 | |||
44 | #define DS3232_REG_SR 0x0F /* control/status register */ | ||
45 | # define DS3232_REG_SR_OSF 0x80 | ||
46 | # define DS3232_REG_SR_BSY 0x04 | ||
47 | # define DS3232_REG_SR_A2F 0x02 | ||
48 | # define DS3232_REG_SR_A1F 0x01 | ||
49 | |||
50 | struct ds3232 { | ||
51 | struct i2c_client *client; | ||
52 | struct rtc_device *rtc; | ||
53 | struct work_struct work; | ||
54 | |||
55 | /* The mutex protects alarm operations, and prevents a race | ||
56 | * between the enable_irq() in the workqueue and the free_irq() | ||
57 | * in the remove function. | ||
58 | */ | ||
59 | struct mutex mutex; | ||
60 | int exiting; | ||
61 | }; | ||
62 | |||
63 | static struct i2c_driver ds3232_driver; | ||
64 | |||
65 | static int ds3232_check_rtc_status(struct i2c_client *client) | ||
66 | { | ||
67 | int ret = 0; | ||
68 | int control, stat; | ||
69 | |||
70 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
71 | if (stat < 0) | ||
72 | return stat; | ||
73 | |||
74 | if (stat & DS3232_REG_SR_OSF) | ||
75 | dev_warn(&client->dev, | ||
76 | "oscillator discontinuity flagged, " | ||
77 | "time unreliable\n"); | ||
78 | |||
79 | stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
80 | |||
81 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | /* If the alarm is pending, clear it before requesting | ||
86 | * the interrupt, so an interrupt event isn't reported | ||
87 | * before everything is initialized. | ||
88 | */ | ||
89 | |||
90 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
91 | if (control < 0) | ||
92 | return control; | ||
93 | |||
94 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
95 | control |= DS3232_REG_CR_INTCN; | ||
96 | |||
97 | return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
98 | } | ||
99 | |||
100 | static int ds3232_read_time(struct device *dev, struct rtc_time *time) | ||
101 | { | ||
102 | struct i2c_client *client = to_i2c_client(dev); | ||
103 | int ret; | ||
104 | u8 buf[7]; | ||
105 | unsigned int year, month, day, hour, minute, second; | ||
106 | unsigned int week, twelve_hr, am_pm; | ||
107 | unsigned int century, add_century = 0; | ||
108 | |||
109 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf); | ||
110 | |||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | if (ret < 7) | ||
114 | return -EIO; | ||
115 | |||
116 | second = buf[0]; | ||
117 | minute = buf[1]; | ||
118 | hour = buf[2]; | ||
119 | week = buf[3]; | ||
120 | day = buf[4]; | ||
121 | month = buf[5]; | ||
122 | year = buf[6]; | ||
123 | |||
124 | /* Extract additional information for AM/PM and century */ | ||
125 | |||
126 | twelve_hr = hour & 0x40; | ||
127 | am_pm = hour & 0x20; | ||
128 | century = month & 0x80; | ||
129 | |||
130 | /* Write to rtc_time structure */ | ||
131 | |||
132 | time->tm_sec = bcd2bin(second); | ||
133 | time->tm_min = bcd2bin(minute); | ||
134 | if (twelve_hr) { | ||
135 | /* Convert to 24 hr */ | ||
136 | if (am_pm) | ||
137 | time->tm_hour = bcd2bin(hour & 0x1F) + 12; | ||
138 | else | ||
139 | time->tm_hour = bcd2bin(hour & 0x1F); | ||
140 | } else { | ||
141 | time->tm_hour = bcd2bin(hour); | ||
142 | } | ||
143 | |||
144 | time->tm_wday = bcd2bin(week); | ||
145 | time->tm_mday = bcd2bin(day); | ||
146 | time->tm_mon = bcd2bin(month & 0x7F); | ||
147 | if (century) | ||
148 | add_century = 100; | ||
149 | |||
150 | time->tm_year = bcd2bin(year) + add_century; | ||
151 | |||
152 | return rtc_valid_tm(time); | ||
153 | } | ||
154 | |||
155 | static int ds3232_set_time(struct device *dev, struct rtc_time *time) | ||
156 | { | ||
157 | struct i2c_client *client = to_i2c_client(dev); | ||
158 | u8 buf[7]; | ||
159 | |||
160 | /* Extract time from rtc_time and load into ds3232*/ | ||
161 | |||
162 | buf[0] = bin2bcd(time->tm_sec); | ||
163 | buf[1] = bin2bcd(time->tm_min); | ||
164 | buf[2] = bin2bcd(time->tm_hour); | ||
165 | buf[3] = bin2bcd(time->tm_wday); /* Day of the week */ | ||
166 | buf[4] = bin2bcd(time->tm_mday); /* Date */ | ||
167 | buf[5] = bin2bcd(time->tm_mon); | ||
168 | if (time->tm_year >= 100) { | ||
169 | buf[5] |= 0x80; | ||
170 | buf[6] = bin2bcd(time->tm_year - 100); | ||
171 | } else { | ||
172 | buf[6] = bin2bcd(time->tm_year); | ||
173 | } | ||
174 | |||
175 | return i2c_smbus_write_i2c_block_data(client, | ||
176 | DS3232_REG_SECONDS, 7, buf); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * DS3232 has two alarm, we only use alarm1 | ||
181 | * According to linux specification, only support one-shot alarm | ||
182 | * no periodic alarm mode | ||
183 | */ | ||
184 | static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
185 | { | ||
186 | struct i2c_client *client = to_i2c_client(dev); | ||
187 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
188 | int control, stat; | ||
189 | int ret; | ||
190 | u8 buf[4]; | ||
191 | |||
192 | mutex_lock(&ds3232->mutex); | ||
193 | |||
194 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
195 | if (ret < 0) | ||
196 | goto out; | ||
197 | stat = ret; | ||
198 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
199 | if (ret < 0) | ||
200 | goto out; | ||
201 | control = ret; | ||
202 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
203 | if (ret < 0) | ||
204 | goto out; | ||
205 | |||
206 | alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F); | ||
207 | alarm->time.tm_min = bcd2bin(buf[1] & 0x7F); | ||
208 | alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); | ||
209 | alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); | ||
210 | |||
211 | alarm->time.tm_mon = -1; | ||
212 | alarm->time.tm_year = -1; | ||
213 | alarm->time.tm_wday = -1; | ||
214 | alarm->time.tm_yday = -1; | ||
215 | alarm->time.tm_isdst = -1; | ||
216 | |||
217 | alarm->enabled = !!(control & DS3232_REG_CR_A1IE); | ||
218 | alarm->pending = !!(stat & DS3232_REG_SR_A1F); | ||
219 | |||
220 | ret = 0; | ||
221 | out: | ||
222 | mutex_unlock(&ds3232->mutex); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * linux rtc-module does not support wday alarm | ||
228 | * and only 24h time mode supported indeed | ||
229 | */ | ||
230 | static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
231 | { | ||
232 | struct i2c_client *client = to_i2c_client(dev); | ||
233 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
234 | int control, stat; | ||
235 | int ret; | ||
236 | u8 buf[4]; | ||
237 | |||
238 | if (client->irq <= 0) | ||
239 | return -EINVAL; | ||
240 | |||
241 | mutex_lock(&ds3232->mutex); | ||
242 | |||
243 | buf[0] = bin2bcd(alarm->time.tm_sec); | ||
244 | buf[1] = bin2bcd(alarm->time.tm_min); | ||
245 | buf[2] = bin2bcd(alarm->time.tm_hour); | ||
246 | buf[3] = bin2bcd(alarm->time.tm_mday); | ||
247 | |||
248 | /* clear alarm interrupt enable bit */ | ||
249 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
250 | if (ret < 0) | ||
251 | goto out; | ||
252 | control = ret; | ||
253 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
254 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
255 | if (ret < 0) | ||
256 | goto out; | ||
257 | |||
258 | /* clear any pending alarm flag */ | ||
259 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
260 | if (ret < 0) | ||
261 | goto out; | ||
262 | stat = ret; | ||
263 | stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
264 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
265 | if (ret < 0) | ||
266 | goto out; | ||
267 | |||
268 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
269 | |||
270 | if (alarm->enabled) { | ||
271 | control |= DS3232_REG_CR_A1IE; | ||
272 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
273 | } | ||
274 | out: | ||
275 | mutex_unlock(&ds3232->mutex); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static void ds3232_update_alarm(struct i2c_client *client) | ||
280 | { | ||
281 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
282 | int control; | ||
283 | int ret; | ||
284 | u8 buf[4]; | ||
285 | |||
286 | mutex_lock(&ds3232->mutex); | ||
287 | |||
288 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
289 | if (ret < 0) | ||
290 | goto unlock; | ||
291 | |||
292 | buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
293 | 0x80 : buf[0]; | ||
294 | buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
295 | 0x80 : buf[1]; | ||
296 | buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
297 | 0x80 : buf[2]; | ||
298 | buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
299 | 0x80 : buf[3]; | ||
300 | |||
301 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
302 | if (ret < 0) | ||
303 | goto unlock; | ||
304 | |||
305 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
306 | if (control < 0) | ||
307 | goto unlock; | ||
308 | |||
309 | if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF)) | ||
310 | /* enable alarm1 interrupt */ | ||
311 | control |= DS3232_REG_CR_A1IE; | ||
312 | else | ||
313 | /* disable alarm1 interrupt */ | ||
314 | control &= ~(DS3232_REG_CR_A1IE); | ||
315 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
316 | |||
317 | unlock: | ||
318 | mutex_unlock(&ds3232->mutex); | ||
319 | } | ||
320 | |||
321 | static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
322 | { | ||
323 | struct i2c_client *client = to_i2c_client(dev); | ||
324 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
325 | |||
326 | if (client->irq <= 0) | ||
327 | return -EINVAL; | ||
328 | |||
329 | if (enabled) | ||
330 | ds3232->rtc->irq_data |= RTC_AF; | ||
331 | else | ||
332 | ds3232->rtc->irq_data &= ~RTC_AF; | ||
333 | |||
334 | ds3232_update_alarm(client); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled) | ||
339 | { | ||
340 | struct i2c_client *client = to_i2c_client(dev); | ||
341 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
342 | |||
343 | if (client->irq <= 0) | ||
344 | return -EINVAL; | ||
345 | |||
346 | if (enabled) | ||
347 | ds3232->rtc->irq_data |= RTC_UF; | ||
348 | else | ||
349 | ds3232->rtc->irq_data &= ~RTC_UF; | ||
350 | |||
351 | ds3232_update_alarm(client); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | ||
356 | { | ||
357 | struct i2c_client *client = dev_id; | ||
358 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
359 | |||
360 | disable_irq_nosync(irq); | ||
361 | schedule_work(&ds3232->work); | ||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | static void ds3232_work(struct work_struct *work) | ||
366 | { | ||
367 | struct ds3232 *ds3232 = container_of(work, struct ds3232, work); | ||
368 | struct i2c_client *client = ds3232->client; | ||
369 | int stat, control; | ||
370 | |||
371 | mutex_lock(&ds3232->mutex); | ||
372 | |||
373 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
374 | if (stat < 0) | ||
375 | goto unlock; | ||
376 | |||
377 | if (stat & DS3232_REG_SR_A1F) { | ||
378 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
379 | if (control < 0) | ||
380 | goto out; | ||
381 | /* disable alarm1 interrupt */ | ||
382 | control &= ~(DS3232_REG_CR_A1IE); | ||
383 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
384 | |||
385 | /* clear the alarm pend flag */ | ||
386 | stat &= ~DS3232_REG_SR_A1F; | ||
387 | i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
388 | |||
389 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); | ||
390 | } | ||
391 | |||
392 | out: | ||
393 | if (!ds3232->exiting) | ||
394 | enable_irq(client->irq); | ||
395 | unlock: | ||
396 | mutex_unlock(&ds3232->mutex); | ||
397 | } | ||
398 | |||
399 | static const struct rtc_class_ops ds3232_rtc_ops = { | ||
400 | .read_time = ds3232_read_time, | ||
401 | .set_time = ds3232_set_time, | ||
402 | .read_alarm = ds3232_read_alarm, | ||
403 | .set_alarm = ds3232_set_alarm, | ||
404 | .alarm_irq_enable = ds3232_alarm_irq_enable, | ||
405 | .update_irq_enable = ds3232_update_irq_enable, | ||
406 | }; | ||
407 | |||
408 | static int __devinit ds3232_probe(struct i2c_client *client, | ||
409 | const struct i2c_device_id *id) | ||
410 | { | ||
411 | struct ds3232 *ds3232; | ||
412 | int ret; | ||
413 | |||
414 | ds3232 = kzalloc(sizeof(struct ds3232), GFP_KERNEL); | ||
415 | if (!ds3232) | ||
416 | return -ENOMEM; | ||
417 | |||
418 | ds3232->client = client; | ||
419 | i2c_set_clientdata(client, ds3232); | ||
420 | |||
421 | INIT_WORK(&ds3232->work, ds3232_work); | ||
422 | mutex_init(&ds3232->mutex); | ||
423 | |||
424 | ret = ds3232_check_rtc_status(client); | ||
425 | if (ret) | ||
426 | goto out_free; | ||
427 | |||
428 | ds3232->rtc = rtc_device_register(client->name, &client->dev, | ||
429 | &ds3232_rtc_ops, THIS_MODULE); | ||
430 | if (IS_ERR(ds3232->rtc)) { | ||
431 | ret = PTR_ERR(ds3232->rtc); | ||
432 | dev_err(&client->dev, "unable to register the class device\n"); | ||
433 | goto out_irq; | ||
434 | } | ||
435 | |||
436 | if (client->irq >= 0) { | ||
437 | ret = request_irq(client->irq, ds3232_irq, 0, | ||
438 | "ds3232", client); | ||
439 | if (ret) { | ||
440 | dev_err(&client->dev, "unable to request IRQ\n"); | ||
441 | goto out_free; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | |||
447 | out_irq: | ||
448 | if (client->irq >= 0) | ||
449 | free_irq(client->irq, client); | ||
450 | |||
451 | out_free: | ||
452 | kfree(ds3232); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | static int __devexit ds3232_remove(struct i2c_client *client) | ||
457 | { | ||
458 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
459 | |||
460 | if (client->irq >= 0) { | ||
461 | mutex_lock(&ds3232->mutex); | ||
462 | ds3232->exiting = 1; | ||
463 | mutex_unlock(&ds3232->mutex); | ||
464 | |||
465 | free_irq(client->irq, client); | ||
466 | flush_scheduled_work(); | ||
467 | } | ||
468 | |||
469 | rtc_device_unregister(ds3232->rtc); | ||
470 | kfree(ds3232); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static const struct i2c_device_id ds3232_id[] = { | ||
475 | { "ds3232", 0 }, | ||
476 | { } | ||
477 | }; | ||
478 | MODULE_DEVICE_TABLE(i2c, ds3232_id); | ||
479 | |||
480 | static struct i2c_driver ds3232_driver = { | ||
481 | .driver = { | ||
482 | .name = "rtc-ds3232", | ||
483 | .owner = THIS_MODULE, | ||
484 | }, | ||
485 | .probe = ds3232_probe, | ||
486 | .remove = __devexit_p(ds3232_remove), | ||
487 | .id_table = ds3232_id, | ||
488 | }; | ||
489 | |||
490 | static int __init ds3232_init(void) | ||
491 | { | ||
492 | return i2c_add_driver(&ds3232_driver); | ||
493 | } | ||
494 | |||
495 | static void __exit ds3232_exit(void) | ||
496 | { | ||
497 | i2c_del_driver(&ds3232_driver); | ||
498 | } | ||
499 | |||
500 | module_init(ds3232_init); | ||
501 | module_exit(ds3232_exit); | ||
502 | |||
503 | MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>"); | ||
504 | MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver"); | ||
505 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index e4de8f37ae4a..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 | } |
@@ -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-jz4740.c b/drivers/rtc/rtc-jz4740.c index 2619d57b91d7..2e16f72c9056 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
3 | * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net> | ||
3 | * JZ4740 SoC RTC driver | 4 | * JZ4740 SoC RTC driver |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
@@ -161,7 +162,8 @@ static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
161 | 162 | ||
162 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | 163 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); |
163 | if (!ret) | 164 | if (!ret) |
164 | ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); | 165 | ret = jz4740_rtc_ctrl_set_bits(rtc, |
166 | JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled); | ||
165 | 167 | ||
166 | return ret; | 168 | return ret; |
167 | } | 169 | } |
@@ -258,6 +260,8 @@ static int __devinit jz4740_rtc_probe(struct platform_device *pdev) | |||
258 | 260 | ||
259 | platform_set_drvdata(pdev, rtc); | 261 | platform_set_drvdata(pdev, rtc); |
260 | 262 | ||
263 | device_init_wakeup(&pdev->dev, 1); | ||
264 | |||
261 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, | 265 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, |
262 | THIS_MODULE); | 266 | THIS_MODULE); |
263 | if (IS_ERR(rtc->rtc)) { | 267 | if (IS_ERR(rtc->rtc)) { |
@@ -318,12 +322,43 @@ static int __devexit jz4740_rtc_remove(struct platform_device *pdev) | |||
318 | return 0; | 322 | return 0; |
319 | } | 323 | } |
320 | 324 | ||
325 | |||
326 | #ifdef CONFIG_PM | ||
327 | static int jz4740_rtc_suspend(struct device *dev) | ||
328 | { | ||
329 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
330 | |||
331 | if (device_may_wakeup(dev)) | ||
332 | enable_irq_wake(rtc->irq); | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int jz4740_rtc_resume(struct device *dev) | ||
337 | { | ||
338 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
339 | |||
340 | if (device_may_wakeup(dev)) | ||
341 | disable_irq_wake(rtc->irq); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static const struct dev_pm_ops jz4740_pm_ops = { | ||
346 | .suspend = jz4740_rtc_suspend, | ||
347 | .resume = jz4740_rtc_resume, | ||
348 | }; | ||
349 | #define JZ4740_RTC_PM_OPS (&jz4740_pm_ops) | ||
350 | |||
351 | #else | ||
352 | #define JZ4740_RTC_PM_OPS NULL | ||
353 | #endif /* CONFIG_PM */ | ||
354 | |||
321 | struct platform_driver jz4740_rtc_driver = { | 355 | struct platform_driver jz4740_rtc_driver = { |
322 | .probe = jz4740_rtc_probe, | 356 | .probe = jz4740_rtc_probe, |
323 | .remove = __devexit_p(jz4740_rtc_remove), | 357 | .remove = __devexit_p(jz4740_rtc_remove), |
324 | .driver = { | 358 | .driver = { |
325 | .name = "jz4740-rtc", | 359 | .name = "jz4740-rtc", |
326 | .owner = THIS_MODULE, | 360 | .owner = THIS_MODULE, |
361 | .pm = JZ4740_RTC_PM_OPS, | ||
327 | }, | 362 | }, |
328 | }; | 363 | }; |
329 | 364 | ||
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c new file mode 100644 index 000000000000..ec8701ce99f9 --- /dev/null +++ b/drivers/rtc/rtc-lpc32xx.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 NXP Semiconductors | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * You should have received a copy of the GNU General Public License along | ||
10 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
11 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | /* | ||
24 | * Clock and Power control register offsets | ||
25 | */ | ||
26 | #define LPC32XX_RTC_UCOUNT 0x00 | ||
27 | #define LPC32XX_RTC_DCOUNT 0x04 | ||
28 | #define LPC32XX_RTC_MATCH0 0x08 | ||
29 | #define LPC32XX_RTC_MATCH1 0x0C | ||
30 | #define LPC32XX_RTC_CTRL 0x10 | ||
31 | #define LPC32XX_RTC_INTSTAT 0x14 | ||
32 | #define LPC32XX_RTC_KEY 0x18 | ||
33 | #define LPC32XX_RTC_SRAM 0x80 | ||
34 | |||
35 | #define LPC32XX_RTC_CTRL_MATCH0 (1 << 0) | ||
36 | #define LPC32XX_RTC_CTRL_MATCH1 (1 << 1) | ||
37 | #define LPC32XX_RTC_CTRL_ONSW_MATCH0 (1 << 2) | ||
38 | #define LPC32XX_RTC_CTRL_ONSW_MATCH1 (1 << 3) | ||
39 | #define LPC32XX_RTC_CTRL_SW_RESET (1 << 4) | ||
40 | #define LPC32XX_RTC_CTRL_CNTR_DIS (1 << 6) | ||
41 | #define LPC32XX_RTC_CTRL_ONSW_FORCE_HI (1 << 7) | ||
42 | |||
43 | #define LPC32XX_RTC_INTSTAT_MATCH0 (1 << 0) | ||
44 | #define LPC32XX_RTC_INTSTAT_MATCH1 (1 << 1) | ||
45 | #define LPC32XX_RTC_INTSTAT_ONSW (1 << 2) | ||
46 | |||
47 | #define LPC32XX_RTC_KEY_ONSW_LOADVAL 0xB5C13F27 | ||
48 | |||
49 | #define RTC_NAME "rtc-lpc32xx" | ||
50 | |||
51 | #define rtc_readl(dev, reg) \ | ||
52 | __raw_readl((dev)->rtc_base + (reg)) | ||
53 | #define rtc_writel(dev, reg, val) \ | ||
54 | __raw_writel((val), (dev)->rtc_base + (reg)) | ||
55 | |||
56 | struct lpc32xx_rtc { | ||
57 | void __iomem *rtc_base; | ||
58 | int irq; | ||
59 | unsigned char alarm_enabled; | ||
60 | struct rtc_device *rtc; | ||
61 | spinlock_t lock; | ||
62 | }; | ||
63 | |||
64 | static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) | ||
65 | { | ||
66 | unsigned long elapsed_sec; | ||
67 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
68 | |||
69 | elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); | ||
70 | rtc_time_to_tm(elapsed_sec, time); | ||
71 | |||
72 | return rtc_valid_tm(time); | ||
73 | } | ||
74 | |||
75 | static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
76 | { | ||
77 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
78 | u32 tmp; | ||
79 | |||
80 | spin_lock_irq(&rtc->lock); | ||
81 | |||
82 | /* RTC must be disabled during count update */ | ||
83 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
84 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); | ||
85 | rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); | ||
86 | rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); | ||
87 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); | ||
88 | |||
89 | spin_unlock_irq(&rtc->lock); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int lpc32xx_rtc_read_alarm(struct device *dev, | ||
95 | struct rtc_wkalrm *wkalrm) | ||
96 | { | ||
97 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
98 | |||
99 | rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); | ||
100 | wkalrm->enabled = rtc->alarm_enabled; | ||
101 | wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & | ||
102 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
103 | |||
104 | return rtc_valid_tm(&wkalrm->time); | ||
105 | } | ||
106 | |||
107 | static int lpc32xx_rtc_set_alarm(struct device *dev, | ||
108 | struct rtc_wkalrm *wkalrm) | ||
109 | { | ||
110 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
111 | unsigned long alarmsecs; | ||
112 | u32 tmp; | ||
113 | int ret; | ||
114 | |||
115 | ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs); | ||
116 | if (ret < 0) { | ||
117 | dev_warn(dev, "Failed to convert time: %d\n", ret); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | spin_lock_irq(&rtc->lock); | ||
122 | |||
123 | /* Disable alarm during update */ | ||
124 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
125 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
126 | |||
127 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); | ||
128 | |||
129 | rtc->alarm_enabled = wkalrm->enabled; | ||
130 | if (wkalrm->enabled) { | ||
131 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
132 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
133 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | | ||
134 | LPC32XX_RTC_CTRL_MATCH0); | ||
135 | } | ||
136 | |||
137 | spin_unlock_irq(&rtc->lock); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, | ||
143 | unsigned int enabled) | ||
144 | { | ||
145 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
146 | u32 tmp; | ||
147 | |||
148 | spin_lock_irq(&rtc->lock); | ||
149 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
150 | |||
151 | if (enabled) { | ||
152 | rtc->alarm_enabled = 1; | ||
153 | tmp |= LPC32XX_RTC_CTRL_MATCH0; | ||
154 | } else { | ||
155 | rtc->alarm_enabled = 0; | ||
156 | tmp &= ~LPC32XX_RTC_CTRL_MATCH0; | ||
157 | } | ||
158 | |||
159 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
160 | spin_unlock_irq(&rtc->lock); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) | ||
166 | { | ||
167 | struct lpc32xx_rtc *rtc = dev; | ||
168 | |||
169 | spin_lock(&rtc->lock); | ||
170 | |||
171 | /* Disable alarm interrupt */ | ||
172 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
173 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
174 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
175 | rtc->alarm_enabled = 0; | ||
176 | |||
177 | /* | ||
178 | * Write a large value to the match value so the RTC won't | ||
179 | * keep firing the match status | ||
180 | */ | ||
181 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
182 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); | ||
183 | |||
184 | spin_unlock(&rtc->lock); | ||
185 | |||
186 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
187 | |||
188 | return IRQ_HANDLED; | ||
189 | } | ||
190 | |||
191 | static const struct rtc_class_ops lpc32xx_rtc_ops = { | ||
192 | .read_time = lpc32xx_rtc_read_time, | ||
193 | .set_mmss = lpc32xx_rtc_set_mmss, | ||
194 | .read_alarm = lpc32xx_rtc_read_alarm, | ||
195 | .set_alarm = lpc32xx_rtc_set_alarm, | ||
196 | .alarm_irq_enable = lpc32xx_rtc_alarm_irq_enable, | ||
197 | }; | ||
198 | |||
199 | static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) | ||
200 | { | ||
201 | struct resource *res; | ||
202 | struct lpc32xx_rtc *rtc; | ||
203 | resource_size_t size; | ||
204 | int rtcirq; | ||
205 | u32 tmp; | ||
206 | |||
207 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
208 | if (!res) { | ||
209 | dev_err(&pdev->dev, "Can't get memory resource\n"); | ||
210 | return -ENOENT; | ||
211 | } | ||
212 | |||
213 | rtcirq = platform_get_irq(pdev, 0); | ||
214 | if (rtcirq < 0 || rtcirq >= NR_IRQS) { | ||
215 | dev_warn(&pdev->dev, "Can't get interrupt resource\n"); | ||
216 | rtcirq = -1; | ||
217 | } | ||
218 | |||
219 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
220 | if (unlikely(!rtc)) { | ||
221 | dev_err(&pdev->dev, "Can't allocate memory\n"); | ||
222 | return -ENOMEM; | ||
223 | } | ||
224 | rtc->irq = rtcirq; | ||
225 | |||
226 | size = resource_size(res); | ||
227 | |||
228 | if (!devm_request_mem_region(&pdev->dev, res->start, size, | ||
229 | pdev->name)) { | ||
230 | dev_err(&pdev->dev, "RTC registers are not free\n"); | ||
231 | return -EBUSY; | ||
232 | } | ||
233 | |||
234 | rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size); | ||
235 | if (!rtc->rtc_base) { | ||
236 | dev_err(&pdev->dev, "Can't map memory\n"); | ||
237 | return -ENOMEM; | ||
238 | } | ||
239 | |||
240 | spin_lock_init(&rtc->lock); | ||
241 | |||
242 | /* | ||
243 | * The RTC is on a seperate power domain and can keep it's state | ||
244 | * across a chip power cycle. If the RTC has never been previously | ||
245 | * setup, then set it up now for the first time. | ||
246 | */ | ||
247 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
248 | if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { | ||
249 | tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | | ||
250 | LPC32XX_RTC_CTRL_CNTR_DIS | | ||
251 | LPC32XX_RTC_CTRL_MATCH0 | | ||
252 | LPC32XX_RTC_CTRL_MATCH1 | | ||
253 | LPC32XX_RTC_CTRL_ONSW_MATCH0 | | ||
254 | LPC32XX_RTC_CTRL_ONSW_MATCH1 | | ||
255 | LPC32XX_RTC_CTRL_ONSW_FORCE_HI); | ||
256 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
257 | |||
258 | /* Clear latched interrupt states */ | ||
259 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
260 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
261 | LPC32XX_RTC_INTSTAT_MATCH0 | | ||
262 | LPC32XX_RTC_INTSTAT_MATCH1 | | ||
263 | LPC32XX_RTC_INTSTAT_ONSW); | ||
264 | |||
265 | /* Write key value to RTC so it won't reload on reset */ | ||
266 | rtc_writel(rtc, LPC32XX_RTC_KEY, | ||
267 | LPC32XX_RTC_KEY_ONSW_LOADVAL); | ||
268 | } else { | ||
269 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
270 | tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
271 | } | ||
272 | |||
273 | platform_set_drvdata(pdev, rtc); | ||
274 | |||
275 | rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, | ||
276 | THIS_MODULE); | ||
277 | if (IS_ERR(rtc->rtc)) { | ||
278 | dev_err(&pdev->dev, "Can't get RTC\n"); | ||
279 | platform_set_drvdata(pdev, NULL); | ||
280 | return PTR_ERR(rtc->rtc); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * IRQ is enabled after device registration in case alarm IRQ | ||
285 | * is pending upon suspend exit. | ||
286 | */ | ||
287 | if (rtc->irq >= 0) { | ||
288 | if (devm_request_irq(&pdev->dev, rtc->irq, | ||
289 | lpc32xx_rtc_alarm_interrupt, | ||
290 | IRQF_DISABLED, pdev->name, rtc) < 0) { | ||
291 | dev_warn(&pdev->dev, "Can't request interrupt.\n"); | ||
292 | rtc->irq = -1; | ||
293 | } else { | ||
294 | device_init_wakeup(&pdev->dev, 1); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev) | ||
302 | { | ||
303 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
304 | |||
305 | if (rtc->irq >= 0) | ||
306 | device_init_wakeup(&pdev->dev, 0); | ||
307 | |||
308 | platform_set_drvdata(pdev, NULL); | ||
309 | rtc_device_unregister(rtc->rtc); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #ifdef CONFIG_PM | ||
315 | static int lpc32xx_rtc_suspend(struct device *dev) | ||
316 | { | ||
317 | struct platform_device *pdev = to_platform_device(dev); | ||
318 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
319 | |||
320 | if (rtc->irq >= 0) { | ||
321 | if (device_may_wakeup(&pdev->dev)) | ||
322 | enable_irq_wake(rtc->irq); | ||
323 | else | ||
324 | disable_irq_wake(rtc->irq); | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int lpc32xx_rtc_resume(struct device *dev) | ||
331 | { | ||
332 | struct platform_device *pdev = to_platform_device(dev); | ||
333 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
334 | |||
335 | if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev)) | ||
336 | disable_irq_wake(rtc->irq); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | /* Unconditionally disable the alarm */ | ||
342 | static int lpc32xx_rtc_freeze(struct device *dev) | ||
343 | { | ||
344 | struct platform_device *pdev = to_platform_device(dev); | ||
345 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
346 | |||
347 | spin_lock_irq(&rtc->lock); | ||
348 | |||
349 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
350 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
351 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
352 | |||
353 | spin_unlock_irq(&rtc->lock); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int lpc32xx_rtc_thaw(struct device *dev) | ||
359 | { | ||
360 | struct platform_device *pdev = to_platform_device(dev); | ||
361 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
362 | |||
363 | if (rtc->alarm_enabled) { | ||
364 | spin_lock_irq(&rtc->lock); | ||
365 | |||
366 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
367 | rtc_readl(rtc, LPC32XX_RTC_CTRL) | | ||
368 | LPC32XX_RTC_CTRL_MATCH0); | ||
369 | |||
370 | spin_unlock_irq(&rtc->lock); | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static const struct dev_pm_ops lpc32xx_rtc_pm_ops = { | ||
377 | .suspend = lpc32xx_rtc_suspend, | ||
378 | .resume = lpc32xx_rtc_resume, | ||
379 | .freeze = lpc32xx_rtc_freeze, | ||
380 | .thaw = lpc32xx_rtc_thaw, | ||
381 | .restore = lpc32xx_rtc_resume | ||
382 | }; | ||
383 | |||
384 | #define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops) | ||
385 | #else | ||
386 | #define LPC32XX_RTC_PM_OPS NULL | ||
387 | #endif | ||
388 | |||
389 | static struct platform_driver lpc32xx_rtc_driver = { | ||
390 | .probe = lpc32xx_rtc_probe, | ||
391 | .remove = __devexit_p(lpc32xx_rtc_remove), | ||
392 | .driver = { | ||
393 | .name = RTC_NAME, | ||
394 | .owner = THIS_MODULE, | ||
395 | .pm = LPC32XX_RTC_PM_OPS | ||
396 | }, | ||
397 | }; | ||
398 | |||
399 | static int __init lpc32xx_rtc_init(void) | ||
400 | { | ||
401 | return platform_driver_register(&lpc32xx_rtc_driver); | ||
402 | } | ||
403 | module_init(lpc32xx_rtc_init); | ||
404 | |||
405 | static void __exit lpc32xx_rtc_exit(void) | ||
406 | { | ||
407 | platform_driver_unregister(&lpc32xx_rtc_driver); | ||
408 | } | ||
409 | module_exit(lpc32xx_rtc_exit); | ||
410 | |||
411 | MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); | ||
412 | MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); | ||
413 | MODULE_LICENSE("GPL"); | ||
414 | MODULE_ALIAS("platform:rtc-lpc32xx"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 6dc4e6241418..5a8daa358066 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/smp_lock.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
@@ -68,6 +68,7 @@ | |||
68 | 68 | ||
69 | #define DRV_VERSION "0.05" | 69 | #define DRV_VERSION "0.05" |
70 | 70 | ||
71 | static DEFINE_MUTEX(m41t80_rtc_mutex); | ||
71 | static const struct i2c_device_id m41t80_id[] = { | 72 | static const struct i2c_device_id m41t80_id[] = { |
72 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, | 73 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, |
73 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, | 74 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, |
@@ -121,7 +122,7 @@ static int m41t80_get_datetime(struct i2c_client *client, | |||
121 | 122 | ||
122 | /* assume 20YY not 19YY, and ignore the Century Bit */ | 123 | /* assume 20YY not 19YY, and ignore the Century Bit */ |
123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; | 124 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; |
124 | return 0; | 125 | return rtc_valid_tm(tm); |
125 | } | 126 | } |
126 | 127 | ||
127 | /* Sets the given date and time to the real time clock. */ | 128 | /* Sets the given date and time to the real time clock. */ |
@@ -677,9 +678,9 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
677 | { | 678 | { |
678 | int ret; | 679 | int ret; |
679 | 680 | ||
680 | lock_kernel(); | 681 | mutex_lock(&m41t80_rtc_mutex); |
681 | ret = wdt_ioctl(file, cmd, arg); | 682 | ret = wdt_ioctl(file, cmd, arg); |
682 | unlock_kernel(); | 683 | mutex_unlock(&m41t80_rtc_mutex); |
683 | 684 | ||
684 | return ret; | 685 | return ret; |
685 | } | 686 | } |
@@ -693,16 +694,16 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
693 | static int wdt_open(struct inode *inode, struct file *file) | 694 | static int wdt_open(struct inode *inode, struct file *file) |
694 | { | 695 | { |
695 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { | 696 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { |
696 | lock_kernel(); | 697 | mutex_lock(&m41t80_rtc_mutex); |
697 | if (test_and_set_bit(0, &wdt_is_open)) { | 698 | if (test_and_set_bit(0, &wdt_is_open)) { |
698 | unlock_kernel(); | 699 | mutex_unlock(&m41t80_rtc_mutex); |
699 | return -EBUSY; | 700 | return -EBUSY; |
700 | } | 701 | } |
701 | /* | 702 | /* |
702 | * Activate | 703 | * Activate |
703 | */ | 704 | */ |
704 | wdt_is_open = 1; | 705 | wdt_is_open = 1; |
705 | unlock_kernel(); | 706 | mutex_unlock(&m41t80_rtc_mutex); |
706 | return nonseekable_open(inode, file); | 707 | return nonseekable_open(inode, file); |
707 | } | 708 | } |
708 | return -ENODEV; | 709 | return -ENODEV; |
@@ -748,6 +749,7 @@ static const struct file_operations wdt_fops = { | |||
748 | .write = wdt_write, | 749 | .write = wdt_write, |
749 | .open = wdt_open, | 750 | .open = wdt_open, |
750 | .release = wdt_release, | 751 | .release = wdt_release, |
752 | .llseek = no_llseek, | ||
751 | }; | 753 | }; |
752 | 754 | ||
753 | static struct miscdevice wdt_dev = { | 755 | static struct miscdevice wdt_dev = { |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index be8359fdb65a..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 | /* |
@@ -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-max8998.c b/drivers/rtc/rtc-max8998.c new file mode 100644 index 000000000000..f22dee35f330 --- /dev/null +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8998 | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Minkyu Kang <mk7.kang@samsung.com> | ||
6 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/bcd.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/max8998.h> | ||
22 | #include <linux/mfd/max8998-private.h> | ||
23 | |||
24 | #define MAX8998_RTC_SEC 0x00 | ||
25 | #define MAX8998_RTC_MIN 0x01 | ||
26 | #define MAX8998_RTC_HOUR 0x02 | ||
27 | #define MAX8998_RTC_WEEKDAY 0x03 | ||
28 | #define MAX8998_RTC_DATE 0x04 | ||
29 | #define MAX8998_RTC_MONTH 0x05 | ||
30 | #define MAX8998_RTC_YEAR1 0x06 | ||
31 | #define MAX8998_RTC_YEAR2 0x07 | ||
32 | #define MAX8998_ALARM0_SEC 0x08 | ||
33 | #define MAX8998_ALARM0_MIN 0x09 | ||
34 | #define MAX8998_ALARM0_HOUR 0x0a | ||
35 | #define MAX8998_ALARM0_WEEKDAY 0x0b | ||
36 | #define MAX8998_ALARM0_DATE 0x0c | ||
37 | #define MAX8998_ALARM0_MONTH 0x0d | ||
38 | #define MAX8998_ALARM0_YEAR1 0x0e | ||
39 | #define MAX8998_ALARM0_YEAR2 0x0f | ||
40 | #define MAX8998_ALARM1_SEC 0x10 | ||
41 | #define MAX8998_ALARM1_MIN 0x11 | ||
42 | #define MAX8998_ALARM1_HOUR 0x12 | ||
43 | #define MAX8998_ALARM1_WEEKDAY 0x13 | ||
44 | #define MAX8998_ALARM1_DATE 0x14 | ||
45 | #define MAX8998_ALARM1_MONTH 0x15 | ||
46 | #define MAX8998_ALARM1_YEAR1 0x16 | ||
47 | #define MAX8998_ALARM1_YEAR2 0x17 | ||
48 | #define MAX8998_ALARM0_CONF 0x18 | ||
49 | #define MAX8998_ALARM1_CONF 0x19 | ||
50 | #define MAX8998_RTC_STATUS 0x1a | ||
51 | #define MAX8998_WTSR_SMPL_CNTL 0x1b | ||
52 | #define MAX8998_TEST 0x1f | ||
53 | |||
54 | #define HOUR_12 (1 << 7) | ||
55 | #define HOUR_PM (1 << 5) | ||
56 | #define ALARM0_STATUS (1 << 1) | ||
57 | #define ALARM1_STATUS (1 << 2) | ||
58 | |||
59 | enum { | ||
60 | RTC_SEC = 0, | ||
61 | RTC_MIN, | ||
62 | RTC_HOUR, | ||
63 | RTC_WEEKDAY, | ||
64 | RTC_DATE, | ||
65 | RTC_MONTH, | ||
66 | RTC_YEAR1, | ||
67 | RTC_YEAR2, | ||
68 | }; | ||
69 | |||
70 | struct max8998_rtc_info { | ||
71 | struct device *dev; | ||
72 | struct max8998_dev *max8998; | ||
73 | struct i2c_client *rtc; | ||
74 | struct rtc_device *rtc_dev; | ||
75 | int irq; | ||
76 | }; | ||
77 | |||
78 | static void max8998_data_to_tm(u8 *data, struct rtc_time *tm) | ||
79 | { | ||
80 | tm->tm_sec = bcd2bin(data[RTC_SEC]); | ||
81 | tm->tm_min = bcd2bin(data[RTC_MIN]); | ||
82 | if (data[RTC_HOUR] & HOUR_12) { | ||
83 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); | ||
84 | if (data[RTC_HOUR] & HOUR_PM) | ||
85 | tm->tm_hour += 12; | ||
86 | } else | ||
87 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); | ||
88 | |||
89 | tm->tm_wday = data[RTC_WEEKDAY] & 0x07; | ||
90 | tm->tm_mday = bcd2bin(data[RTC_DATE]); | ||
91 | tm->tm_mon = bcd2bin(data[RTC_MONTH]); | ||
92 | tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; | ||
93 | tm->tm_year -= 1900; | ||
94 | } | ||
95 | |||
96 | static void max8998_tm_to_data(struct rtc_time *tm, u8 *data) | ||
97 | { | ||
98 | data[RTC_SEC] = bin2bcd(tm->tm_sec); | ||
99 | data[RTC_MIN] = bin2bcd(tm->tm_min); | ||
100 | data[RTC_HOUR] = bin2bcd(tm->tm_hour); | ||
101 | data[RTC_WEEKDAY] = tm->tm_wday; | ||
102 | data[RTC_DATE] = bin2bcd(tm->tm_mday); | ||
103 | data[RTC_MONTH] = bin2bcd(tm->tm_mon); | ||
104 | data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); | ||
105 | data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); | ||
106 | } | ||
107 | |||
108 | static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
109 | { | ||
110 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
111 | u8 data[8]; | ||
112 | int ret; | ||
113 | |||
114 | ret = max8998_bulk_read(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | |||
118 | max8998_data_to_tm(data, tm); | ||
119 | |||
120 | return rtc_valid_tm(tm); | ||
121 | } | ||
122 | |||
123 | static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
124 | { | ||
125 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
126 | u8 data[8]; | ||
127 | |||
128 | max8998_tm_to_data(tm, data); | ||
129 | |||
130 | return max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
131 | } | ||
132 | |||
133 | static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
134 | { | ||
135 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
136 | u8 data[8]; | ||
137 | u8 val; | ||
138 | int ret; | ||
139 | |||
140 | ret = max8998_bulk_read(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | max8998_data_to_tm(data, &alrm->time); | ||
145 | |||
146 | ret = max8998_read_reg(info->rtc, MAX8998_ALARM0_CONF, &val); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | alrm->enabled = !!val; | ||
151 | |||
152 | ret = max8998_read_reg(info->rtc, MAX8998_RTC_STATUS, &val); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | if (val & ALARM0_STATUS) | ||
157 | alrm->pending = 1; | ||
158 | else | ||
159 | alrm->pending = 0; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info) | ||
165 | { | ||
166 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0); | ||
167 | } | ||
168 | |||
169 | static int max8998_rtc_start_alarm(struct max8998_rtc_info *info) | ||
170 | { | ||
171 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0x77); | ||
172 | } | ||
173 | |||
174 | static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
175 | { | ||
176 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
177 | u8 data[8]; | ||
178 | int ret; | ||
179 | |||
180 | max8998_tm_to_data(&alrm->time, data); | ||
181 | |||
182 | ret = max8998_rtc_stop_alarm(info); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | ret = max8998_bulk_write(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | if (alrm->enabled) | ||
191 | return max8998_rtc_start_alarm(info); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int max8998_rtc_alarm_irq_enable(struct device *dev, | ||
197 | unsigned int enabled) | ||
198 | { | ||
199 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
200 | |||
201 | if (enabled) | ||
202 | return max8998_rtc_start_alarm(info); | ||
203 | else | ||
204 | return max8998_rtc_stop_alarm(info); | ||
205 | } | ||
206 | |||
207 | static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data) | ||
208 | { | ||
209 | struct max8998_rtc_info *info = data; | ||
210 | |||
211 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
212 | |||
213 | return IRQ_HANDLED; | ||
214 | } | ||
215 | |||
216 | static const struct rtc_class_ops max8998_rtc_ops = { | ||
217 | .read_time = max8998_rtc_read_time, | ||
218 | .set_time = max8998_rtc_set_time, | ||
219 | .read_alarm = max8998_rtc_read_alarm, | ||
220 | .set_alarm = max8998_rtc_set_alarm, | ||
221 | .alarm_irq_enable = max8998_rtc_alarm_irq_enable, | ||
222 | }; | ||
223 | |||
224 | static int __devinit max8998_rtc_probe(struct platform_device *pdev) | ||
225 | { | ||
226 | struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); | ||
227 | struct max8998_rtc_info *info; | ||
228 | int ret; | ||
229 | |||
230 | info = kzalloc(sizeof(struct max8998_rtc_info), GFP_KERNEL); | ||
231 | if (!info) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | info->dev = &pdev->dev; | ||
235 | info->max8998 = max8998; | ||
236 | info->rtc = max8998->rtc; | ||
237 | info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; | ||
238 | |||
239 | info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev, | ||
240 | &max8998_rtc_ops, THIS_MODULE); | ||
241 | |||
242 | if (IS_ERR(info->rtc_dev)) { | ||
243 | ret = PTR_ERR(info->rtc_dev); | ||
244 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
245 | goto out_rtc; | ||
246 | } | ||
247 | |||
248 | platform_set_drvdata(pdev, info); | ||
249 | |||
250 | ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0, | ||
251 | "rtc-alarm0", info); | ||
252 | if (ret < 0) | ||
253 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
254 | info->irq, ret); | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | out_rtc: | ||
259 | kfree(info); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static int __devexit max8998_rtc_remove(struct platform_device *pdev) | ||
264 | { | ||
265 | struct max8998_rtc_info *info = platform_get_drvdata(pdev); | ||
266 | |||
267 | if (info) { | ||
268 | free_irq(info->irq, info); | ||
269 | rtc_device_unregister(info->rtc_dev); | ||
270 | kfree(info); | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static struct platform_driver max8998_rtc_driver = { | ||
277 | .driver = { | ||
278 | .name = "max8998-rtc", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | .probe = max8998_rtc_probe, | ||
282 | .remove = __devexit_p(max8998_rtc_remove), | ||
283 | }; | ||
284 | |||
285 | static int __init max8998_rtc_init(void) | ||
286 | { | ||
287 | return platform_driver_register(&max8998_rtc_driver); | ||
288 | } | ||
289 | module_init(max8998_rtc_init); | ||
290 | |||
291 | static void __exit max8998_rtc_exit(void) | ||
292 | { | ||
293 | platform_driver_unregister(&max8998_rtc_driver); | ||
294 | } | ||
295 | module_exit(max8998_rtc_exit); | ||
296 | |||
297 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
298 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
299 | MODULE_DESCRIPTION("Maxim MAX8998 RTC driver"); | ||
300 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c deleted file mode 100644 index 675bfb515367..000000000000 --- a/drivers/rtc/rtc-mc13783.c +++ /dev/null | |||
@@ -1,428 +0,0 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13783 PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13783.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13783-rtc" | ||
20 | |||
21 | #define MC13783_RTCTOD 20 | ||
22 | #define MC13783_RTCTODA 21 | ||
23 | #define MC13783_RTCDAY 22 | ||
24 | #define MC13783_RTCDAYA 23 | ||
25 | |||
26 | struct mc13783_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13783 *mc13783; | ||
29 | int valid; | ||
30 | }; | ||
31 | |||
32 | static int mc13783_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13783 *mc13783, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; | ||
42 | return func(priv->mc13783, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13783_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13783_lock(priv->mc13783); | ||
52 | |||
53 | ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13783_unlock(priv->mc13783); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13783_lock(priv->mc13783); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13783_unlock(priv->mc13783); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13783_lock(priv->mc13783); | ||
117 | |||
118 | /* | ||
119 | * temporarily invalidate alarm to prevent triggering it when the day is | ||
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13783_reg_write(priv->mc13783, | ||
128 | MC13783_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
149 | /* restore alarm */ | ||
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13783_reg_write(priv->mc13783, | ||
152 | MC13783_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13783_unlock(priv->mc13783); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13783_lock(priv->mc13783); | ||
179 | |||
180 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); | ||
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
191 | |||
192 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
195 | out: | ||
196 | mc13783_unlock(priv->mc13783); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13783_lock(priv->mc13783); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); | ||
227 | if (unlikely(ret)) | ||
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13783_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); | ||
250 | |||
251 | out: | ||
252 | mc13783_unlock(priv->mc13783); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13783_rtc *priv = dev; | ||
260 | struct mc13783 *mc13783 = priv->mc13783; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13783_irq_ack(mc13783, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13783_rtc *priv = dev; | ||
274 | struct mc13783 *mc13783 = priv->mc13783; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13783_irq_ack(mc13783, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13783_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops mc13783_rtc_ops = { | ||
298 | .read_time = mc13783_rtc_read_time, | ||
299 | .set_mmss = mc13783_rtc_set_mmss, | ||
300 | .read_alarm = mc13783_rtc_read_alarm, | ||
301 | .set_alarm = mc13783_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, | ||
303 | .update_irq_enable = mc13783_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13783_rtc *priv = dev; | ||
309 | struct mc13783 *mc13783 = priv->mc13783; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13783_irq_mask(mc13783, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13783_rtc *priv; | ||
323 | struct mc13783 *mc13783; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13783 = mc13783; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13783_lock(mc13783); | ||
336 | |||
337 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, | ||
338 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
342 | ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST, | ||
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ, | ||
350 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
354 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA, | ||
355 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13783_unlock(mc13783); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13783_lock(priv->mc13783); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
393 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | ||
394 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13783_unlock(priv->mc13783); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static struct platform_driver mc13783_rtc_driver = { | ||
406 | .remove = __devexit_p(mc13783_rtc_remove), | ||
407 | .driver = { | ||
408 | .name = DRIVER_NAME, | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static int __init mc13783_rtc_init(void) | ||
414 | { | ||
415 | return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe); | ||
416 | } | ||
417 | module_init(mc13783_rtc_init); | ||
418 | |||
419 | static void __exit mc13783_rtc_exit(void) | ||
420 | { | ||
421 | platform_driver_unregister(&mc13783_rtc_driver); | ||
422 | } | ||
423 | module_exit(mc13783_rtc_exit); | ||
424 | |||
425 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
426 | MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC"); | ||
427 | MODULE_LICENSE("GPL v2"); | ||
428 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c new file mode 100644 index 000000000000..5314b153bfba --- /dev/null +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13XXX PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13xxx.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13xxx-rtc" | ||
20 | |||
21 | #define MC13XXX_RTCTOD 20 | ||
22 | #define MC13XXX_RTCTODA 21 | ||
23 | #define MC13XXX_RTCDAY 22 | ||
24 | #define MC13XXX_RTCDAYA 23 | ||
25 | |||
26 | struct mc13xxx_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13xxx *mc13xxx; | ||
29 | int valid; | ||
30 | }; | ||
31 | |||
32 | static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13xxx *mc13xxx, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask; | ||
42 | return func(priv->mc13xxx, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13xxx_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13xxx_lock(priv->mc13xxx); | ||
52 | |||
53 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13xxx_unlock(priv->mc13xxx); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13xxx_lock(priv->mc13xxx); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13xxx_unlock(priv->mc13xxx); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13xxx_lock(priv->mc13xxx); | ||
117 | |||
118 | /* | ||
119 | * temporarily invalidate alarm to prevent triggering it when the day is | ||
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
128 | MC13XXX_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
149 | /* restore alarm */ | ||
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
152 | MC13XXX_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13xxx_unlock(priv->mc13xxx); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13xxx_lock(priv->mc13xxx); | ||
179 | |||
180 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds); | ||
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
191 | |||
192 | ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
195 | out: | ||
196 | mc13xxx_unlock(priv->mc13xxx); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13xxx_lock(priv->mc13xxx); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); | ||
227 | if (unlikely(ret)) | ||
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13XXX_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); | ||
250 | |||
251 | out: | ||
252 | mc13xxx_unlock(priv->mc13xxx); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13xxx_rtc *priv = dev; | ||
260 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13xxx_irq_ack(mc13xxx, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13xxx_rtc *priv = dev; | ||
274 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13xxx_irq_ack(mc13xxx, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13xxx_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13xxx_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA); | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops mc13xxx_rtc_ops = { | ||
298 | .read_time = mc13xxx_rtc_read_time, | ||
299 | .set_mmss = mc13xxx_rtc_set_mmss, | ||
300 | .read_alarm = mc13xxx_rtc_read_alarm, | ||
301 | .set_alarm = mc13xxx_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, | ||
303 | .update_irq_enable = mc13xxx_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13xxx_rtc *priv = dev; | ||
309 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13xxx_irq_mask(mc13xxx, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13xxx_rtc *priv; | ||
323 | struct mc13xxx *mc13xxx; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13xxx = mc13xxx; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13xxx_lock(mc13xxx); | ||
336 | |||
337 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
338 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
342 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ, | ||
350 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
354 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, | ||
355 | mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13xxx_unlock(mc13xxx); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13xxx_lock(priv->mc13xxx); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
393 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
394 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13xxx_unlock(priv->mc13xxx); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | const struct platform_device_id mc13xxx_rtc_idtable[] = { | ||
406 | { | ||
407 | .name = "mc13783-rtc", | ||
408 | }, { | ||
409 | .name = "mc13892-rtc", | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static struct platform_driver mc13xxx_rtc_driver = { | ||
414 | .id_table = mc13xxx_rtc_idtable, | ||
415 | .remove = __devexit_p(mc13xxx_rtc_remove), | ||
416 | .driver = { | ||
417 | .name = DRIVER_NAME, | ||
418 | .owner = THIS_MODULE, | ||
419 | }, | ||
420 | }; | ||
421 | |||
422 | static int __init mc13xxx_rtc_init(void) | ||
423 | { | ||
424 | return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); | ||
425 | } | ||
426 | module_init(mc13xxx_rtc_init); | ||
427 | |||
428 | static void __exit mc13xxx_rtc_exit(void) | ||
429 | { | ||
430 | platform_driver_unregister(&mc13xxx_rtc_driver); | ||
431 | } | ||
432 | module_exit(mc13xxx_rtc_exit); | ||
433 | |||
434 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
435 | MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); | ||
436 | MODULE_LICENSE("GPL v2"); | ||
437 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index db5d8c416d26..dfcdf0901d21 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -268,7 +268,7 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, | 268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static int __devinit mpc5121_rtc_probe(struct of_device *op, | 271 | static int __devinit mpc5121_rtc_probe(struct platform_device *op, |
272 | const struct of_device_id *match) | 272 | const struct of_device_id *match) |
273 | { | 273 | { |
274 | struct mpc5121_rtc_data *rtc; | 274 | struct mpc5121_rtc_data *rtc; |
@@ -338,7 +338,7 @@ out_free: | |||
338 | return err; | 338 | return err; |
339 | } | 339 | } |
340 | 340 | ||
341 | static int __devexit mpc5121_rtc_remove(struct of_device *op) | 341 | static int __devexit mpc5121_rtc_remove(struct platform_device *op) |
342 | { | 342 | { |
343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); | 343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); |
344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | 344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 25ec921db07c..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 | ||
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a351bd5d8176..ddb0857e15a4 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 failed\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-omap.c b/drivers/rtc/rtc-omap.c index 64d9727b7229..73377b0d65da 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -34,7 +34,8 @@ | |||
34 | * Board-specific wiring options include using split power mode with | 34 | * Board-specific wiring options include using split power mode with |
35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), | 35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), |
36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from | 36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from |
37 | * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. | 37 | * low power modes) for OMAP1 boards (OMAP-L138 has this built into |
38 | * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. | ||
38 | */ | 39 | */ |
39 | 40 | ||
40 | #define OMAP_RTC_BASE 0xfffb4800 | 41 | #define OMAP_RTC_BASE 0xfffb4800 |
@@ -401,16 +402,17 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
401 | 402 | ||
402 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 403 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
403 | * | 404 | * |
404 | * - Boards wired so that RTC_WAKE_INT does something, and muxed | 405 | * - Device wake-up capability setting should come through chip |
405 | * right (W13_1610_RTC_WAKE_INT is the default after chip reset), | 406 | * init logic. OMAP1 boards should initialize the "wakeup capable" |
406 | * should initialize the device wakeup flag appropriately. | 407 | * flag in the platform device if the board is wired right for |
408 | * being woken up by RTC alarm. For OMAP-L138, this capability | ||
409 | * is built into the SoC by the "Deep Sleep" capability. | ||
407 | * | 410 | * |
408 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, | 411 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, |
409 | * rather than nPWRON_RESET, should forcibly enable split | 412 | * rather than nPWRON_RESET, should forcibly enable split |
410 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT | 413 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT |
411 | * is write-only, and always reads as zero...) | 414 | * is write-only, and always reads as zero...) |
412 | */ | 415 | */ |
413 | device_init_wakeup(&pdev->dev, 0); | ||
414 | 416 | ||
415 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) | 417 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) |
416 | pr_info("%s: split power mode\n", pdev->name); | 418 | pr_info("%s: split power mode\n", pdev->name); |
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 71bbefc3544e..b7a6690e5b35 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 | /* |
@@ -404,7 +403,7 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
404 | } | 403 | } |
405 | 404 | ||
406 | if (request_irq(adev->irq[0], pl031_interrupt, | 405 | if (request_irq(adev->irq[0], pl031_interrupt, |
407 | IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) { | 406 | IRQF_DISABLED, "rtc-pl031", ldata)) { |
408 | ret = -EIO; | 407 | ret = -EIO; |
409 | goto out_no_irq; | 408 | goto out_no_irq; |
410 | } | 409 | } |
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-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index e6ea3f5ee1eb..e3ff179b99ca 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c | |||
@@ -80,21 +80,21 @@ | |||
80 | /* SCSPTR1 data */ | 80 | /* SCSPTR1 data */ |
81 | unsigned char scsptr1_data; | 81 | unsigned char scsptr1_data; |
82 | 82 | ||
83 | #define RS5C313_CEENABLE ctrl_outb(RS5C313_CE_RTCCE, RS5C313_CE); | 83 | #define RS5C313_CEENABLE __raw_writeb(RS5C313_CE_RTCCE, RS5C313_CE); |
84 | #define RS5C313_CEDISABLE ctrl_outb(0x00, RS5C313_CE) | 84 | #define RS5C313_CEDISABLE __raw_writeb(0x00, RS5C313_CE) |
85 | #define RS5C313_MISCOP ctrl_outb(0x02, 0xB0000008) | 85 | #define RS5C313_MISCOP __raw_writeb(0x02, 0xB0000008) |
86 | 86 | ||
87 | static void rs5c313_init_port(void) | 87 | static void rs5c313_init_port(void) |
88 | { | 88 | { |
89 | /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ | 89 | /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ |
90 | ctrl_outb(ctrl_inb(SCSMR1) & ~SCSMR1_CA, SCSMR1); | 90 | __raw_writeb(__raw_readb(SCSMR1) & ~SCSMR1_CA, SCSMR1); |
91 | ctrl_outb(ctrl_inb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); | 91 | __raw_writeb(__raw_readb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); |
92 | 92 | ||
93 | /* And Initialize SCL for RS5C313 clock */ | 93 | /* And Initialize SCL for RS5C313 clock */ |
94 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL; /* SCL:H */ | 94 | scsptr1_data = __raw_readb(SCSPTR1) | SCL; /* SCL:H */ |
95 | ctrl_outb(scsptr1_data, SCSPTR1); | 95 | __raw_writeb(scsptr1_data, SCSPTR1); |
96 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL_OEN; /* SCL output enable */ | 96 | scsptr1_data = __raw_readb(SCSPTR1) | SCL_OEN; /* SCL output enable */ |
97 | ctrl_outb(scsptr1_data, SCSPTR1); | 97 | __raw_writeb(scsptr1_data, SCSPTR1); |
98 | RS5C313_CEDISABLE; /* CE:L */ | 98 | RS5C313_CEDISABLE; /* CE:L */ |
99 | } | 99 | } |
100 | 100 | ||
@@ -106,21 +106,21 @@ static void rs5c313_write_data(unsigned char data) | |||
106 | /* SDA:Write Data */ | 106 | /* SDA:Write Data */ |
107 | scsptr1_data = (scsptr1_data & ~SDA) | | 107 | scsptr1_data = (scsptr1_data & ~SDA) | |
108 | ((((0x80 >> i) & data) >> (7 - i)) << 2); | 108 | ((((0x80 >> i) & data) >> (7 - i)) << 2); |
109 | ctrl_outb(scsptr1_data, SCSPTR1); | 109 | __raw_writeb(scsptr1_data, SCSPTR1); |
110 | if (i == 0) { | 110 | if (i == 0) { |
111 | scsptr1_data |= SDA_OEN; /* SDA:output enable */ | 111 | scsptr1_data |= SDA_OEN; /* SDA:output enable */ |
112 | ctrl_outb(scsptr1_data, SCSPTR1); | 112 | __raw_writeb(scsptr1_data, SCSPTR1); |
113 | } | 113 | } |
114 | ndelay(700); | 114 | ndelay(700); |
115 | scsptr1_data &= ~SCL; /* SCL:L */ | 115 | scsptr1_data &= ~SCL; /* SCL:L */ |
116 | ctrl_outb(scsptr1_data, SCSPTR1); | 116 | __raw_writeb(scsptr1_data, SCSPTR1); |
117 | ndelay(700); | 117 | ndelay(700); |
118 | scsptr1_data |= SCL; /* SCL:H */ | 118 | scsptr1_data |= SCL; /* SCL:H */ |
119 | ctrl_outb(scsptr1_data, SCSPTR1); | 119 | __raw_writeb(scsptr1_data, SCSPTR1); |
120 | } | 120 | } |
121 | 121 | ||
122 | scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ | 122 | scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ |
123 | ctrl_outb(scsptr1_data, SCSPTR1); | 123 | __raw_writeb(scsptr1_data, SCSPTR1); |
124 | } | 124 | } |
125 | 125 | ||
126 | static unsigned char rs5c313_read_data(void) | 126 | static unsigned char rs5c313_read_data(void) |
@@ -131,12 +131,12 @@ static unsigned char rs5c313_read_data(void) | |||
131 | for (i = 0; i < 8; i++) { | 131 | for (i = 0; i < 8; i++) { |
132 | ndelay(700); | 132 | ndelay(700); |
133 | /* SDA:Read Data */ | 133 | /* SDA:Read Data */ |
134 | data |= ((ctrl_inb(SCSPTR1) & SDA) >> 2) << (7 - i); | 134 | data |= ((__raw_readb(SCSPTR1) & SDA) >> 2) << (7 - i); |
135 | scsptr1_data &= ~SCL; /* SCL:L */ | 135 | scsptr1_data &= ~SCL; /* SCL:L */ |
136 | ctrl_outb(scsptr1_data, SCSPTR1); | 136 | __raw_writeb(scsptr1_data, SCSPTR1); |
137 | ndelay(700); | 137 | ndelay(700); |
138 | scsptr1_data |= SCL; /* SCL:H */ | 138 | scsptr1_data |= SCL; /* SCL:H */ |
139 | ctrl_outb(scsptr1_data, SCSPTR1); | 139 | __raw_writeb(scsptr1_data, SCSPTR1); |
140 | } | 140 | } |
141 | return data & 0x0F; | 141 | return data & 0x0F; |
142 | } | 142 | } |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 90cf0a6ff23e..dd14e202c2c8 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -207,7 +207,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
207 | static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | 207 | static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) |
208 | { | 208 | { |
209 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 209 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
210 | unsigned char buf[8]; | 210 | unsigned char buf[7]; |
211 | int addr; | 211 | int addr; |
212 | 212 | ||
213 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 213 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 70b68d35f969..cf953ecbfca9 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/ |
@@ -39,6 +42,7 @@ enum s3c_cpu_type { | |||
39 | 42 | ||
40 | static struct resource *s3c_rtc_mem; | 43 | static struct resource *s3c_rtc_mem; |
41 | 44 | ||
45 | static struct clk *rtc_clk; | ||
42 | static void __iomem *s3c_rtc_base; | 46 | static void __iomem *s3c_rtc_base; |
43 | static int s3c_rtc_alarmno = NO_IRQ; | 47 | static int s3c_rtc_alarmno = NO_IRQ; |
44 | static int s3c_rtc_tickno = NO_IRQ; | 48 | static int s3c_rtc_tickno = NO_IRQ; |
@@ -53,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
53 | struct rtc_device *rdev = id; | 57 | struct rtc_device *rdev = id; |
54 | 58 | ||
55 | 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 | |||
56 | return IRQ_HANDLED; | 64 | return IRQ_HANDLED; |
57 | } | 65 | } |
58 | 66 | ||
@@ -61,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
61 | struct rtc_device *rdev = id; | 69 | struct rtc_device *rdev = id; |
62 | 70 | ||
63 | 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 | |||
64 | return IRQ_HANDLED; | 76 | return IRQ_HANDLED; |
65 | } | 77 | } |
66 | 78 | ||
@@ -88,13 +100,13 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
88 | spin_lock_irq(&s3c_rtc_pie_lock); | 100 | spin_lock_irq(&s3c_rtc_pie_lock); |
89 | 101 | ||
90 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
91 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 103 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
92 | tmp &= ~S3C64XX_RTCCON_TICEN; | 104 | tmp &= ~S3C64XX_RTCCON_TICEN; |
93 | 105 | ||
94 | if (enabled) | 106 | if (enabled) |
95 | tmp |= S3C64XX_RTCCON_TICEN; | 107 | tmp |= S3C64XX_RTCCON_TICEN; |
96 | 108 | ||
97 | writeb(tmp, s3c_rtc_base + S3C2410_RTCCON); | 109 | writew(tmp, s3c_rtc_base + S3C2410_RTCCON); |
98 | } else { | 110 | } else { |
99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); | 111 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); |
100 | tmp &= ~S3C2410_TICNT_ENABLE; | 112 | tmp &= ~S3C2410_TICNT_ENABLE; |
@@ -128,7 +140,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
128 | 140 | ||
129 | tmp |= (rtc_dev->max_user_freq / freq)-1; | 141 | tmp |= (rtc_dev->max_user_freq / freq)-1; |
130 | 142 | ||
131 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 143 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
132 | spin_unlock_irq(&s3c_rtc_pie_lock); | 144 | spin_unlock_irq(&s3c_rtc_pie_lock); |
133 | 145 | ||
134 | return 0; | 146 | return 0; |
@@ -159,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
159 | goto retry_get_time; | 171 | goto retry_get_time; |
160 | } | 172 | } |
161 | 173 | ||
162 | pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", | 174 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", |
163 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | 175 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, |
164 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | 176 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); |
165 | 177 | ||
166 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
@@ -173,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
173 | rtc_tm->tm_year += 100; | 185 | rtc_tm->tm_year += 100; |
174 | rtc_tm->tm_mon -= 1; | 186 | rtc_tm->tm_mon -= 1; |
175 | 187 | ||
176 | return 0; | 188 | return rtc_valid_tm(rtc_tm); |
177 | } | 189 | } |
178 | 190 | ||
179 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | 191 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) |
@@ -181,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
181 | void __iomem *base = s3c_rtc_base; | 193 | void __iomem *base = s3c_rtc_base; |
182 | int year = tm->tm_year - 100; | 194 | int year = tm->tm_year - 100; |
183 | 195 | ||
184 | pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", | 196 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
185 | tm->tm_year, tm->tm_mon, tm->tm_mday, | 197 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
186 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
187 | 199 | ||
188 | /* we get around y2k by simply not supporting it */ | 200 | /* we get around y2k by simply not supporting it */ |
@@ -219,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
219 | 231 | ||
220 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; | 232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; |
221 | 233 | ||
222 | pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", | 234 | pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
223 | alm_en, | 235 | alm_en, |
224 | alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, | 236 | 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, |
225 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); | 237 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); |
226 | 238 | ||
227 | 239 | ||
@@ -230,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
230 | if (alm_en & S3C2410_RTCALM_SECEN) | 242 | if (alm_en & S3C2410_RTCALM_SECEN) |
231 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); | 243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
232 | else | 244 | else |
233 | alm_tm->tm_sec = 0xff; | 245 | alm_tm->tm_sec = -1; |
234 | 246 | ||
235 | if (alm_en & S3C2410_RTCALM_MINEN) | 247 | if (alm_en & S3C2410_RTCALM_MINEN) |
236 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); | 248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
237 | else | 249 | else |
238 | alm_tm->tm_min = 0xff; | 250 | alm_tm->tm_min = -1; |
239 | 251 | ||
240 | if (alm_en & S3C2410_RTCALM_HOUREN) | 252 | if (alm_en & S3C2410_RTCALM_HOUREN) |
241 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); | 253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
242 | else | 254 | else |
243 | alm_tm->tm_hour = 0xff; | 255 | alm_tm->tm_hour = -1; |
244 | 256 | ||
245 | if (alm_en & S3C2410_RTCALM_DAYEN) | 257 | if (alm_en & S3C2410_RTCALM_DAYEN) |
246 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); | 258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
247 | else | 259 | else |
248 | alm_tm->tm_mday = 0xff; | 260 | alm_tm->tm_mday = -1; |
249 | 261 | ||
250 | if (alm_en & S3C2410_RTCALM_MONEN) { | 262 | if (alm_en & S3C2410_RTCALM_MONEN) { |
251 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); | 263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
252 | alm_tm->tm_mon -= 1; | 264 | alm_tm->tm_mon -= 1; |
253 | } else { | 265 | } else { |
254 | alm_tm->tm_mon = 0xff; | 266 | alm_tm->tm_mon = -1; |
255 | } | 267 | } |
256 | 268 | ||
257 | if (alm_en & S3C2410_RTCALM_YEAREN) | 269 | if (alm_en & S3C2410_RTCALM_YEAREN) |
258 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); | 270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
259 | else | 271 | else |
260 | alm_tm->tm_year = 0xffff; | 272 | alm_tm->tm_year = -1; |
261 | 273 | ||
262 | return 0; | 274 | return 0; |
263 | } | 275 | } |
@@ -268,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
268 | void __iomem *base = s3c_rtc_base; | 280 | void __iomem *base = s3c_rtc_base; |
269 | unsigned int alrm_en; | 281 | unsigned int alrm_en; |
270 | 282 | ||
271 | pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", | 283 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
272 | alrm->enabled, | 284 | alrm->enabled, |
273 | tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, | 285 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
274 | tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); | 286 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
275 | 287 | ||
276 | 288 | ||
277 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
@@ -298,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
298 | 310 | ||
299 | s3c_rtc_setaie(alrm->enabled); | 311 | s3c_rtc_setaie(alrm->enabled); |
300 | 312 | ||
301 | if (alrm->enabled) | ||
302 | enable_irq_wake(s3c_rtc_alarmno); | ||
303 | else | ||
304 | disable_irq_wake(s3c_rtc_alarmno); | ||
305 | |||
306 | return 0; | 313 | return 0; |
307 | } | 314 | } |
308 | 315 | ||
@@ -311,7 +318,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
311 | unsigned int ticnt; | 318 | unsigned int ticnt; |
312 | 319 | ||
313 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
314 | ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); | 321 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
315 | ticnt &= S3C64XX_RTCCON_TICEN; | 322 | ticnt &= S3C64XX_RTCCON_TICEN; |
316 | } else { | 323 | } else { |
317 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
@@ -372,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = { | |||
372 | .set_alarm = s3c_rtc_setalarm, | 379 | .set_alarm = s3c_rtc_setalarm, |
373 | .irq_set_freq = s3c_rtc_setfreq, | 380 | .irq_set_freq = s3c_rtc_setfreq, |
374 | .irq_set_state = s3c_rtc_setpie, | 381 | .irq_set_state = s3c_rtc_setpie, |
375 | .proc = s3c_rtc_proc, | 382 | .proc = s3c_rtc_proc, |
383 | .alarm_irq_enable = s3c_rtc_setaie, | ||
376 | }; | 384 | }; |
377 | 385 | ||
378 | static void s3c_rtc_enable(struct platform_device *pdev, int en) | 386 | static void s3c_rtc_enable(struct platform_device *pdev, int en) |
@@ -384,11 +392,11 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
384 | return; | 392 | return; |
385 | 393 | ||
386 | if (!en) { | 394 | if (!en) { |
387 | tmp = readb(base + S3C2410_RTCCON); | 395 | tmp = readw(base + S3C2410_RTCCON); |
388 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 396 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
389 | tmp &= ~S3C64XX_RTCCON_TICEN; | 397 | tmp &= ~S3C64XX_RTCCON_TICEN; |
390 | tmp &= ~S3C2410_RTCCON_RTCEN; | 398 | tmp &= ~S3C2410_RTCCON_RTCEN; |
391 | writeb(tmp, base + S3C2410_RTCCON); | 399 | writew(tmp, base + S3C2410_RTCCON); |
392 | 400 | ||
393 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 401 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
394 | tmp = readb(base + S3C2410_TICNT); | 402 | tmp = readb(base + S3C2410_TICNT); |
@@ -398,25 +406,28 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
398 | } else { | 406 | } else { |
399 | /* re-enable the device, and check it is ok */ | 407 | /* re-enable the device, and check it is ok */ |
400 | 408 | ||
401 | if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ | 409 | if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { |
402 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); | 410 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); |
403 | 411 | ||
404 | tmp = readb(base + S3C2410_RTCCON); | 412 | tmp = readw(base + S3C2410_RTCCON); |
405 | writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); | 413 | writew(tmp | S3C2410_RTCCON_RTCEN, |
414 | base + S3C2410_RTCCON); | ||
406 | } | 415 | } |
407 | 416 | ||
408 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ | 417 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { |
409 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); | 418 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); |
410 | 419 | ||
411 | tmp = readb(base + S3C2410_RTCCON); | 420 | tmp = readw(base + S3C2410_RTCCON); |
412 | writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); | 421 | writew(tmp & ~S3C2410_RTCCON_CNTSEL, |
422 | base + S3C2410_RTCCON); | ||
413 | } | 423 | } |
414 | 424 | ||
415 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ | 425 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { |
416 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); | 426 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); |
417 | 427 | ||
418 | tmp = readb(base + S3C2410_RTCCON); | 428 | tmp = readw(base + S3C2410_RTCCON); |
419 | writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); | 429 | writew(tmp & ~S3C2410_RTCCON_CLKRST, |
430 | base + S3C2410_RTCCON); | ||
420 | } | 431 | } |
421 | } | 432 | } |
422 | } | 433 | } |
@@ -431,6 +442,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
431 | s3c_rtc_setpie(&dev->dev, 0); | 442 | s3c_rtc_setpie(&dev->dev, 0); |
432 | s3c_rtc_setaie(0); | 443 | s3c_rtc_setaie(0); |
433 | 444 | ||
445 | clk_disable(rtc_clk); | ||
446 | clk_put(rtc_clk); | ||
447 | rtc_clk = NULL; | ||
448 | |||
434 | iounmap(s3c_rtc_base); | 449 | iounmap(s3c_rtc_base); |
435 | release_resource(s3c_rtc_mem); | 450 | release_resource(s3c_rtc_mem); |
436 | kfree(s3c_rtc_mem); | 451 | kfree(s3c_rtc_mem); |
@@ -441,6 +456,7 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
441 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) | 456 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
442 | { | 457 | { |
443 | struct rtc_device *rtc; | 458 | struct rtc_device *rtc; |
459 | struct rtc_time rtc_tm; | ||
444 | struct resource *res; | 460 | struct resource *res; |
445 | int ret; | 461 | int ret; |
446 | 462 | ||
@@ -488,12 +504,22 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
488 | goto err_nomap; | 504 | goto err_nomap; |
489 | } | 505 | } |
490 | 506 | ||
507 | rtc_clk = clk_get(&pdev->dev, "rtc"); | ||
508 | if (IS_ERR(rtc_clk)) { | ||
509 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
510 | ret = PTR_ERR(rtc_clk); | ||
511 | rtc_clk = NULL; | ||
512 | goto err_clk; | ||
513 | } | ||
514 | |||
515 | clk_enable(rtc_clk); | ||
516 | |||
491 | /* check to see if everything is setup correctly */ | 517 | /* check to see if everything is setup correctly */ |
492 | 518 | ||
493 | s3c_rtc_enable(pdev, 1); | 519 | s3c_rtc_enable(pdev, 1); |
494 | 520 | ||
495 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 521 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
496 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 522 | readw(s3c_rtc_base + S3C2410_RTCCON)); |
497 | 523 | ||
498 | device_init_wakeup(&pdev->dev, 1); | 524 | device_init_wakeup(&pdev->dev, 1); |
499 | 525 | ||
@@ -510,6 +536,23 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
510 | 536 | ||
511 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; | 537 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; |
512 | 538 | ||
539 | /* Check RTC Time */ | ||
540 | |||
541 | s3c_rtc_gettime(NULL, &rtc_tm); | ||
542 | |||
543 | if (rtc_valid_tm(&rtc_tm)) { | ||
544 | rtc_tm.tm_year = 100; | ||
545 | rtc_tm.tm_mon = 0; | ||
546 | rtc_tm.tm_mday = 1; | ||
547 | rtc_tm.tm_hour = 0; | ||
548 | rtc_tm.tm_min = 0; | ||
549 | rtc_tm.tm_sec = 0; | ||
550 | |||
551 | s3c_rtc_settime(NULL, &rtc_tm); | ||
552 | |||
553 | dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); | ||
554 | } | ||
555 | |||
513 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 556 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
514 | rtc->max_user_freq = 32768; | 557 | rtc->max_user_freq = 32768; |
515 | else | 558 | else |
@@ -523,6 +566,10 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
523 | 566 | ||
524 | err_nortc: | 567 | err_nortc: |
525 | s3c_rtc_enable(pdev, 0); | 568 | s3c_rtc_enable(pdev, 0); |
569 | clk_disable(rtc_clk); | ||
570 | clk_put(rtc_clk); | ||
571 | |||
572 | err_clk: | ||
526 | iounmap(s3c_rtc_base); | 573 | iounmap(s3c_rtc_base); |
527 | 574 | ||
528 | err_nomap: | 575 | err_nomap: |
@@ -543,10 +590,14 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
543 | /* save TICNT for anyone using periodic interrupts */ | 590 | /* save TICNT for anyone using periodic interrupts */ |
544 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 591 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
545 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 592 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
546 | ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); | 593 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); |
547 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | 594 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; |
548 | } | 595 | } |
549 | s3c_rtc_enable(pdev, 0); | 596 | s3c_rtc_enable(pdev, 0); |
597 | |||
598 | if (device_may_wakeup(&pdev->dev)) | ||
599 | enable_irq_wake(s3c_rtc_alarmno); | ||
600 | |||
550 | return 0; | 601 | return 0; |
551 | } | 602 | } |
552 | 603 | ||
@@ -557,9 +608,13 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
557 | s3c_rtc_enable(pdev, 1); | 608 | s3c_rtc_enable(pdev, 1); |
558 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 609 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
559 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 610 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
560 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 611 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
561 | writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | 612 | writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); |
562 | } | 613 | } |
614 | |||
615 | if (device_may_wakeup(&pdev->dev)) | ||
616 | disable_irq_wake(s3c_rtc_alarmno); | ||
617 | |||
563 | return 0; | 618 | return 0; |
564 | } | 619 | } |
565 | #else | 620 | #else |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 5efbd5990ff8..06e41ed93230 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -761,7 +761,7 @@ err_unmap: | |||
761 | clk_put(rtc->clk); | 761 | clk_put(rtc->clk); |
762 | iounmap(rtc->regbase); | 762 | iounmap(rtc->regbase); |
763 | err_badmap: | 763 | err_badmap: |
764 | release_resource(rtc->res); | 764 | release_mem_region(rtc->res->start, rtc->regsize); |
765 | err_badres: | 765 | err_badres: |
766 | kfree(rtc); | 766 | kfree(rtc); |
767 | 767 | ||
@@ -786,7 +786,7 @@ static int __exit sh_rtc_remove(struct platform_device *pdev) | |||
786 | } | 786 | } |
787 | 787 | ||
788 | iounmap(rtc->regbase); | 788 | iounmap(rtc->regbase); |
789 | release_resource(rtc->res); | 789 | release_mem_region(rtc->res->start, rtc->regsize); |
790 | 790 | ||
791 | clk_disable(rtc->clk); | 791 | clk_disable(rtc->clk); |
792 | clk_put(rtc->clk); | 792 | clk_put(rtc->clk); |