diff options
Diffstat (limited to 'drivers/rtc')
41 files changed, 2983 insertions, 1129 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 48ca7132cc05..4941cade319f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -171,7 +171,8 @@ config RTC_DRV_DS3232 | |||
171 | depends on RTC_CLASS && I2C | 171 | depends on RTC_CLASS && I2C |
172 | help | 172 | help |
173 | If you say yes here you get support for Dallas Semiconductor | 173 | If you say yes here you get support for Dallas Semiconductor |
174 | DS3232 real-time clock chips. | 174 | DS3232 real-time clock chips. If an interrupt is associated |
175 | with the device, the alarm functionality is supported. | ||
175 | 176 | ||
176 | This driver can also be built as a module. If so, the module | 177 | This driver can also be built as a module. If so, the module |
177 | will be called rtc-ds3232. | 178 | will be called rtc-ds3232. |
@@ -195,6 +196,16 @@ config RTC_DRV_MAX8925 | |||
195 | 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 |
196 | will be called rtc-max8925. | 197 | will be called rtc-max8925. |
197 | 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 | |||
198 | config RTC_DRV_RS5C372 | 209 | config RTC_DRV_RS5C372 |
199 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 210 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
200 | help | 211 | help |
@@ -452,6 +463,18 @@ config RTC_DRV_CMOS | |||
452 | This driver can also be built as a module. If so, the module | 463 | This driver can also be built as a module. If so, the module |
453 | will be called rtc-cmos. | 464 | will be called rtc-cmos. |
454 | 465 | ||
466 | config RTC_DRV_VRTC | ||
467 | tristate "Virtual RTC for Moorestown platforms" | ||
468 | depends on X86_MRST | ||
469 | default y if X86_MRST | ||
470 | |||
471 | help | ||
472 | Say "yes" here to get direct support for the real time clock | ||
473 | found on Moorestown platforms. The VRTC is a emulated RTC that | ||
474 | derives its clock source from a real RTC in the PMIC. The MC146818 | ||
475 | style programming interface is mostly conserved, but any | ||
476 | updates are done via IPC calls to the system controller FW. | ||
477 | |||
455 | config RTC_DRV_DS1216 | 478 | config RTC_DRV_DS1216 |
456 | tristate "Dallas DS1216" | 479 | tristate "Dallas DS1216" |
457 | depends on SNI_RM | 480 | depends on SNI_RM |
@@ -765,15 +788,15 @@ config RTC_DRV_AT32AP700X | |||
765 | AT32AP700x family processors. | 788 | AT32AP700x family processors. |
766 | 789 | ||
767 | config RTC_DRV_AT91RM9200 | 790 | config RTC_DRV_AT91RM9200 |
768 | tristate "AT91RM9200 or AT91SAM9RL" | 791 | tristate "AT91RM9200 or some AT91SAM9 RTC" |
769 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL | 792 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
770 | help | 793 | help |
771 | Driver for the internal RTC (Realtime Clock) module found on | 794 | Driver for the internal RTC (Realtime Clock) module found on |
772 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | 795 | Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips |
773 | this is powered by the backup power supply. | 796 | this is powered by the backup power supply. |
774 | 797 | ||
775 | config RTC_DRV_AT91SAM9 | 798 | config RTC_DRV_AT91SAM9 |
776 | tristate "AT91SAM9x/AT91CAP9" | 799 | tristate "AT91SAM9x/AT91CAP9 RTT as RTC" |
777 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | 800 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) |
778 | help | 801 | help |
779 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT | 802 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT |
@@ -781,8 +804,8 @@ config RTC_DRV_AT91SAM9 | |||
781 | supply (such as a small coin cell battery), but do not need to | 804 | supply (such as a small coin cell battery), but do not need to |
782 | be used as RTCs. | 805 | be used as RTCs. |
783 | 806 | ||
784 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | 807 | (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the |
785 | module and leave the RTT available for other uses.) | 808 | dedicated RTC module and leave the RTT available for other uses.) |
786 | 809 | ||
787 | config RTC_DRV_AT91SAM9_RTT | 810 | config RTC_DRV_AT91SAM9_RTT |
788 | int | 811 | int |
@@ -925,11 +948,12 @@ config RTC_DRV_PCAP | |||
925 | If you say Y here you will get support for the RTC found on | 948 | If you say Y here you will get support for the RTC found on |
926 | the PCAP2 ASIC used on some Motorola phones. | 949 | the PCAP2 ASIC used on some Motorola phones. |
927 | 950 | ||
928 | config RTC_DRV_MC13783 | 951 | config RTC_DRV_MC13XXX |
929 | depends on MFD_MC13783 | 952 | depends on MFD_MC13XXX |
930 | tristate "Freescale MC13783 RTC" | 953 | tristate "Freescale MC13xxx RTC" |
931 | help | 954 | help |
932 | This enables support for the Freescale MC13783 PMIC RTC | 955 | This enables support for the RTCs found on Freescale's PMICs |
956 | MC13783 and MC13892. | ||
933 | 957 | ||
934 | config RTC_DRV_MPC5121 | 958 | config RTC_DRV_MPC5121 |
935 | tristate "Freescale MPC5121 built-in RTC" | 959 | tristate "Freescale MPC5121 built-in RTC" |
@@ -952,4 +976,13 @@ config RTC_DRV_JZ4740 | |||
952 | This driver can also be buillt as a module. If so, the module | 976 | This driver can also be buillt as a module. If so, the module |
953 | will be called rtc-jz4740. | 977 | will be called rtc-jz4740. |
954 | 978 | ||
979 | config RTC_DRV_LPC32XX | ||
980 | depends on ARCH_LPC32XX | ||
981 | tristate "NXP LPC32XX RTC" | ||
982 | help | ||
983 | This enables support for the NXP RTC in the LPC32XX | ||
984 | |||
985 | This driver can also be buillt as a module. If so, the module | ||
986 | will be called rtc-lpc32xx. | ||
987 | |||
955 | endif # RTC_CLASS | 988 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0f207b3b5833..2afdaf3ff986 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -30,6 +30,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | |||
30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
31 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | 31 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o |
32 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 32 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
33 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o | ||
33 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 34 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
34 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | 35 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o |
35 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 36 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
@@ -51,6 +52,7 @@ obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | |||
51 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 52 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
52 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | 53 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o |
53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 54 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
55 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | ||
54 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 56 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
55 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 57 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
56 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 58 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
@@ -59,8 +61,9 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | |||
59 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 61 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
60 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 62 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
61 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 63 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
64 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | ||
62 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 65 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
63 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | 66 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
64 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 67 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
65 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 68 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
66 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 69 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 565562ba6ac9..c404b61386bf 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kdev_t.h> | 16 | #include <linux/kdev_t.h> |
17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/workqueue.h> | ||
19 | 20 | ||
20 | #include "rtc-core.h" | 21 | #include "rtc-core.h" |
21 | 22 | ||
@@ -142,6 +143,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
142 | rtc->id = id; | 143 | rtc->id = id; |
143 | rtc->ops = ops; | 144 | rtc->ops = ops; |
144 | rtc->owner = owner; | 145 | rtc->owner = owner; |
146 | rtc->irq_freq = 1; | ||
145 | rtc->max_user_freq = 64; | 147 | rtc->max_user_freq = 64; |
146 | rtc->dev.parent = dev; | 148 | rtc->dev.parent = dev; |
147 | rtc->dev.class = rtc_class; | 149 | rtc->dev.class = rtc_class; |
@@ -152,14 +154,28 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
152 | spin_lock_init(&rtc->irq_task_lock); | 154 | spin_lock_init(&rtc->irq_task_lock); |
153 | init_waitqueue_head(&rtc->irq_queue); | 155 | init_waitqueue_head(&rtc->irq_queue); |
154 | 156 | ||
157 | /* Init timerqueue */ | ||
158 | timerqueue_init_head(&rtc->timerqueue); | ||
159 | INIT_WORK(&rtc->irqwork, rtc_timer_do_work); | ||
160 | /* Init aie timer */ | ||
161 | rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc); | ||
162 | /* Init uie timer */ | ||
163 | rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc); | ||
164 | /* Init pie timer */ | ||
165 | hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
166 | rtc->pie_timer.function = rtc_pie_update_irq; | ||
167 | rtc->pie_enabled = 0; | ||
168 | |||
155 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | 169 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); |
156 | dev_set_name(&rtc->dev, "rtc%d", id); | 170 | dev_set_name(&rtc->dev, "rtc%d", id); |
157 | 171 | ||
158 | rtc_dev_prepare(rtc); | 172 | rtc_dev_prepare(rtc); |
159 | 173 | ||
160 | err = device_register(&rtc->dev); | 174 | err = device_register(&rtc->dev); |
161 | if (err) | 175 | if (err) { |
176 | put_device(&rtc->dev); | ||
162 | goto exit_kfree; | 177 | goto exit_kfree; |
178 | } | ||
163 | 179 | ||
164 | rtc_dev_add_device(rtc); | 180 | rtc_dev_add_device(rtc); |
165 | rtc_sysfs_add_device(rtc); | 181 | rtc_sysfs_add_device(rtc); |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index a0c816238aa9..cb2f0728fd70 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -14,15 +14,14 @@ | |||
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
17 | #include <linux/workqueue.h> | ||
17 | 18 | ||
18 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 19 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); |
20 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); | ||
21 | |||
22 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | ||
19 | { | 23 | { |
20 | int err; | 24 | int err; |
21 | |||
22 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
23 | if (err) | ||
24 | return err; | ||
25 | |||
26 | if (!rtc->ops) | 25 | if (!rtc->ops) |
27 | err = -ENODEV; | 26 | err = -ENODEV; |
28 | else if (!rtc->ops->read_time) | 27 | else if (!rtc->ops->read_time) |
@@ -31,7 +30,18 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
31 | memset(tm, 0, sizeof(struct rtc_time)); | 30 | memset(tm, 0, sizeof(struct rtc_time)); |
32 | err = rtc->ops->read_time(rtc->dev.parent, tm); | 31 | err = rtc->ops->read_time(rtc->dev.parent, tm); |
33 | } | 32 | } |
33 | return err; | ||
34 | } | ||
34 | 35 | ||
36 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | ||
37 | { | ||
38 | int err; | ||
39 | |||
40 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
41 | if (err) | ||
42 | return err; | ||
43 | |||
44 | err = __rtc_read_time(rtc, tm); | ||
35 | mutex_unlock(&rtc->ops_lock); | 45 | mutex_unlock(&rtc->ops_lock); |
36 | return err; | 46 | return err; |
37 | } | 47 | } |
@@ -106,188 +116,60 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
106 | } | 116 | } |
107 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | 117 | EXPORT_SYMBOL_GPL(rtc_set_mmss); |
108 | 118 | ||
109 | static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 119 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
110 | { | 120 | { |
111 | int err; | 121 | int err; |
112 | 122 | ||
113 | err = mutex_lock_interruptible(&rtc->ops_lock); | 123 | err = mutex_lock_interruptible(&rtc->ops_lock); |
114 | if (err) | 124 | if (err) |
115 | return err; | 125 | return err; |
116 | |||
117 | if (rtc->ops == NULL) | 126 | if (rtc->ops == NULL) |
118 | err = -ENODEV; | 127 | err = -ENODEV; |
119 | else if (!rtc->ops->read_alarm) | 128 | else if (!rtc->ops->read_alarm) |
120 | err = -EINVAL; | 129 | err = -EINVAL; |
121 | else { | 130 | else { |
122 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | 131 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); |
123 | err = rtc->ops->read_alarm(rtc->dev.parent, alarm); | 132 | alarm->enabled = rtc->aie_timer.enabled; |
133 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); | ||
124 | } | 134 | } |
125 | |||
126 | mutex_unlock(&rtc->ops_lock); | 135 | mutex_unlock(&rtc->ops_lock); |
136 | |||
127 | return err; | 137 | return err; |
128 | } | 138 | } |
139 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | ||
129 | 140 | ||
130 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 141 | int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
131 | { | 142 | { |
143 | struct rtc_time tm; | ||
144 | long now, scheduled; | ||
132 | int err; | 145 | int err; |
133 | struct rtc_time before, now; | ||
134 | int first_time = 1; | ||
135 | unsigned long t_now, t_alm; | ||
136 | enum { none, day, month, year } missing = none; | ||
137 | unsigned days; | ||
138 | |||
139 | /* The lower level RTC driver may return -1 in some fields, | ||
140 | * creating invalid alarm->time values, for reasons like: | ||
141 | * | ||
142 | * - The hardware may not be capable of filling them in; | ||
143 | * many alarms match only on time-of-day fields, not | ||
144 | * day/month/year calendar data. | ||
145 | * | ||
146 | * - Some hardware uses illegal values as "wildcard" match | ||
147 | * values, which non-Linux firmware (like a BIOS) may try | ||
148 | * to set up as e.g. "alarm 15 minutes after each hour". | ||
149 | * Linux uses only oneshot alarms. | ||
150 | * | ||
151 | * When we see that here, we deal with it by using values from | ||
152 | * a current RTC timestamp for any missing (-1) values. The | ||
153 | * RTC driver prevents "periodic alarm" modes. | ||
154 | * | ||
155 | * But this can be racey, because some fields of the RTC timestamp | ||
156 | * may have wrapped in the interval since we read the RTC alarm, | ||
157 | * which would lead to us inserting inconsistent values in place | ||
158 | * of the -1 fields. | ||
159 | * | ||
160 | * Reading the alarm and timestamp in the reverse sequence | ||
161 | * would have the same race condition, and not solve the issue. | ||
162 | * | ||
163 | * So, we must first read the RTC timestamp, | ||
164 | * then read the RTC alarm value, | ||
165 | * and then read a second RTC timestamp. | ||
166 | * | ||
167 | * If any fields of the second timestamp have changed | ||
168 | * when compared with the first timestamp, then we know | ||
169 | * our timestamp may be inconsistent with that used by | ||
170 | * the low-level rtc_read_alarm_internal() function. | ||
171 | * | ||
172 | * So, when the two timestamps disagree, we just loop and do | ||
173 | * the process again to get a fully consistent set of values. | ||
174 | * | ||
175 | * This could all instead be done in the lower level driver, | ||
176 | * but since more than one lower level RTC implementation needs it, | ||
177 | * then it's probably best best to do it here instead of there.. | ||
178 | */ | ||
179 | 146 | ||
180 | /* Get the "before" timestamp */ | 147 | err = rtc_valid_tm(&alarm->time); |
181 | err = rtc_read_time(rtc, &before); | 148 | if (err) |
182 | if (err < 0) | ||
183 | return err; | 149 | return err; |
184 | do { | 150 | rtc_tm_to_time(&alarm->time, &scheduled); |
185 | if (!first_time) | ||
186 | memcpy(&before, &now, sizeof(struct rtc_time)); | ||
187 | first_time = 0; | ||
188 | |||
189 | /* get the RTC alarm values, which may be incomplete */ | ||
190 | err = rtc_read_alarm_internal(rtc, alarm); | ||
191 | if (err) | ||
192 | return err; | ||
193 | if (!alarm->enabled) | ||
194 | return 0; | ||
195 | |||
196 | /* full-function RTCs won't have such missing fields */ | ||
197 | if (rtc_valid_tm(&alarm->time) == 0) | ||
198 | return 0; | ||
199 | |||
200 | /* get the "after" timestamp, to detect wrapped fields */ | ||
201 | err = rtc_read_time(rtc, &now); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | |||
205 | /* note that tm_sec is a "don't care" value here: */ | ||
206 | } while ( before.tm_min != now.tm_min | ||
207 | || before.tm_hour != now.tm_hour | ||
208 | || before.tm_mon != now.tm_mon | ||
209 | || before.tm_year != now.tm_year); | ||
210 | 151 | ||
211 | /* Fill in the missing alarm fields using the timestamp; we | 152 | /* Make sure we're not setting alarms in the past */ |
212 | * know there's at least one since alarm->time is invalid. | 153 | err = __rtc_read_time(rtc, &tm); |
154 | rtc_tm_to_time(&tm, &now); | ||
155 | if (scheduled <= now) | ||
156 | return -ETIME; | ||
157 | /* | ||
158 | * XXX - We just checked to make sure the alarm time is not | ||
159 | * in the past, but there is still a race window where if | ||
160 | * the is alarm set for the next second and the second ticks | ||
161 | * over right here, before we set the alarm. | ||
213 | */ | 162 | */ |
214 | if (alarm->time.tm_sec == -1) | ||
215 | alarm->time.tm_sec = now.tm_sec; | ||
216 | if (alarm->time.tm_min == -1) | ||
217 | alarm->time.tm_min = now.tm_min; | ||
218 | if (alarm->time.tm_hour == -1) | ||
219 | alarm->time.tm_hour = now.tm_hour; | ||
220 | |||
221 | /* For simplicity, only support date rollover for now */ | ||
222 | if (alarm->time.tm_mday == -1) { | ||
223 | alarm->time.tm_mday = now.tm_mday; | ||
224 | missing = day; | ||
225 | } | ||
226 | if (alarm->time.tm_mon == -1) { | ||
227 | alarm->time.tm_mon = now.tm_mon; | ||
228 | if (missing == none) | ||
229 | missing = month; | ||
230 | } | ||
231 | if (alarm->time.tm_year == -1) { | ||
232 | alarm->time.tm_year = now.tm_year; | ||
233 | if (missing == none) | ||
234 | missing = year; | ||
235 | } | ||
236 | 163 | ||
237 | /* with luck, no rollover is needed */ | 164 | if (!rtc->ops) |
238 | rtc_tm_to_time(&now, &t_now); | 165 | err = -ENODEV; |
239 | rtc_tm_to_time(&alarm->time, &t_alm); | 166 | else if (!rtc->ops->set_alarm) |
240 | if (t_now < t_alm) | 167 | err = -EINVAL; |
241 | goto done; | 168 | else |
242 | 169 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | |
243 | switch (missing) { | ||
244 | |||
245 | /* 24 hour rollover ... if it's now 10am Monday, an alarm that | ||
246 | * that will trigger at 5am will do so at 5am Tuesday, which | ||
247 | * could also be in the next month or year. This is a common | ||
248 | * case, especially for PCs. | ||
249 | */ | ||
250 | case day: | ||
251 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day"); | ||
252 | t_alm += 24 * 60 * 60; | ||
253 | rtc_time_to_tm(t_alm, &alarm->time); | ||
254 | break; | ||
255 | |||
256 | /* Month rollover ... if it's the 31th, an alarm on the 3rd will | ||
257 | * be next month. An alarm matching on the 30th, 29th, or 28th | ||
258 | * may end up in the month after that! Many newer PCs support | ||
259 | * this type of alarm. | ||
260 | */ | ||
261 | case month: | ||
262 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); | ||
263 | do { | ||
264 | if (alarm->time.tm_mon < 11) | ||
265 | alarm->time.tm_mon++; | ||
266 | else { | ||
267 | alarm->time.tm_mon = 0; | ||
268 | alarm->time.tm_year++; | ||
269 | } | ||
270 | days = rtc_month_days(alarm->time.tm_mon, | ||
271 | alarm->time.tm_year); | ||
272 | } while (days < alarm->time.tm_mday); | ||
273 | break; | ||
274 | |||
275 | /* Year rollover ... easy except for leap years! */ | ||
276 | case year: | ||
277 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | ||
278 | do { | ||
279 | alarm->time.tm_year++; | ||
280 | } while (rtc_valid_tm(&alarm->time) != 0); | ||
281 | break; | ||
282 | |||
283 | default: | ||
284 | dev_warn(&rtc->dev, "alarm rollover not handled\n"); | ||
285 | } | ||
286 | 170 | ||
287 | done: | 171 | return err; |
288 | return 0; | ||
289 | } | 172 | } |
290 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | ||
291 | 173 | ||
292 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 174 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
293 | { | 175 | { |
@@ -300,14 +182,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
300 | err = mutex_lock_interruptible(&rtc->ops_lock); | 182 | err = mutex_lock_interruptible(&rtc->ops_lock); |
301 | if (err) | 183 | if (err) |
302 | return err; | 184 | return err; |
303 | 185 | if (rtc->aie_timer.enabled) { | |
304 | if (!rtc->ops) | 186 | rtc_timer_remove(rtc, &rtc->aie_timer); |
305 | err = -ENODEV; | 187 | } |
306 | else if (!rtc->ops->set_alarm) | 188 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
307 | err = -EINVAL; | 189 | rtc->aie_timer.period = ktime_set(0, 0); |
308 | else | 190 | if (alarm->enabled) { |
309 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | 191 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); |
310 | 192 | } | |
311 | mutex_unlock(&rtc->ops_lock); | 193 | mutex_unlock(&rtc->ops_lock); |
312 | return err; | 194 | return err; |
313 | } | 195 | } |
@@ -319,7 +201,16 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
319 | if (err) | 201 | if (err) |
320 | return err; | 202 | return err; |
321 | 203 | ||
322 | if (!rtc->ops) | 204 | if (rtc->aie_timer.enabled != enabled) { |
205 | if (enabled) | ||
206 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); | ||
207 | else | ||
208 | rtc_timer_remove(rtc, &rtc->aie_timer); | ||
209 | } | ||
210 | |||
211 | if (err) | ||
212 | /* nothing */; | ||
213 | else if (!rtc->ops) | ||
323 | err = -ENODEV; | 214 | err = -ENODEV; |
324 | else if (!rtc->ops->alarm_irq_enable) | 215 | else if (!rtc->ops->alarm_irq_enable) |
325 | err = -EINVAL; | 216 | err = -EINVAL; |
@@ -340,19 +231,28 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
340 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 231 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
341 | if (enabled == 0 && rtc->uie_irq_active) { | 232 | if (enabled == 0 && rtc->uie_irq_active) { |
342 | mutex_unlock(&rtc->ops_lock); | 233 | mutex_unlock(&rtc->ops_lock); |
343 | return rtc_dev_update_irq_enable_emul(rtc, enabled); | 234 | return rtc_dev_update_irq_enable_emul(rtc, 0); |
344 | } | 235 | } |
345 | #endif | 236 | #endif |
237 | /* make sure we're changing state */ | ||
238 | if (rtc->uie_rtctimer.enabled == enabled) | ||
239 | goto out; | ||
240 | |||
241 | if (enabled) { | ||
242 | struct rtc_time tm; | ||
243 | ktime_t now, onesec; | ||
244 | |||
245 | __rtc_read_time(rtc, &tm); | ||
246 | onesec = ktime_set(1, 0); | ||
247 | now = rtc_tm_to_ktime(tm); | ||
248 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); | ||
249 | rtc->uie_rtctimer.period = ktime_set(1, 0); | ||
250 | err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); | ||
251 | } else | ||
252 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); | ||
346 | 253 | ||
347 | if (!rtc->ops) | 254 | out: |
348 | err = -ENODEV; | ||
349 | else if (!rtc->ops->update_irq_enable) | ||
350 | err = -EINVAL; | ||
351 | else | ||
352 | err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled); | ||
353 | |||
354 | mutex_unlock(&rtc->ops_lock); | 255 | mutex_unlock(&rtc->ops_lock); |
355 | |||
356 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 256 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
357 | /* | 257 | /* |
358 | * Enable emulation if the driver did not provide | 258 | * Enable emulation if the driver did not provide |
@@ -364,25 +264,30 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
364 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); | 264 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); |
365 | #endif | 265 | #endif |
366 | return err; | 266 | return err; |
267 | |||
367 | } | 268 | } |
368 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); | 269 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); |
369 | 270 | ||
271 | |||
370 | /** | 272 | /** |
371 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs | 273 | * rtc_handle_legacy_irq - AIE, UIE and PIE event hook |
372 | * @rtc: the rtc device | 274 | * @rtc: pointer to the rtc device |
373 | * @num: how many irqs are being reported (usually one) | 275 | * |
374 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF | 276 | * This function is called when an AIE, UIE or PIE mode interrupt |
375 | * Context: any | 277 | * has occured (or been emulated). |
278 | * | ||
279 | * Triggers the registered irq_task function callback. | ||
376 | */ | 280 | */ |
377 | void rtc_update_irq(struct rtc_device *rtc, | 281 | void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) |
378 | unsigned long num, unsigned long events) | ||
379 | { | 282 | { |
380 | unsigned long flags; | 283 | unsigned long flags; |
381 | 284 | ||
285 | /* mark one irq of the appropriate mode */ | ||
382 | spin_lock_irqsave(&rtc->irq_lock, flags); | 286 | spin_lock_irqsave(&rtc->irq_lock, flags); |
383 | rtc->irq_data = (rtc->irq_data + (num << 8)) | events; | 287 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); |
384 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | 288 | spin_unlock_irqrestore(&rtc->irq_lock, flags); |
385 | 289 | ||
290 | /* call the task func */ | ||
386 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 291 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
387 | if (rtc->irq_task) | 292 | if (rtc->irq_task) |
388 | rtc->irq_task->func(rtc->irq_task->private_data); | 293 | rtc->irq_task->func(rtc->irq_task->private_data); |
@@ -391,6 +296,69 @@ void rtc_update_irq(struct rtc_device *rtc, | |||
391 | wake_up_interruptible(&rtc->irq_queue); | 296 | wake_up_interruptible(&rtc->irq_queue); |
392 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); | 297 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); |
393 | } | 298 | } |
299 | |||
300 | |||
301 | /** | ||
302 | * rtc_aie_update_irq - AIE mode rtctimer hook | ||
303 | * @private: pointer to the rtc_device | ||
304 | * | ||
305 | * This functions is called when the aie_timer expires. | ||
306 | */ | ||
307 | void rtc_aie_update_irq(void *private) | ||
308 | { | ||
309 | struct rtc_device *rtc = (struct rtc_device *)private; | ||
310 | rtc_handle_legacy_irq(rtc, 1, RTC_AF); | ||
311 | } | ||
312 | |||
313 | |||
314 | /** | ||
315 | * rtc_uie_update_irq - UIE mode rtctimer hook | ||
316 | * @private: pointer to the rtc_device | ||
317 | * | ||
318 | * This functions is called when the uie_timer expires. | ||
319 | */ | ||
320 | void rtc_uie_update_irq(void *private) | ||
321 | { | ||
322 | struct rtc_device *rtc = (struct rtc_device *)private; | ||
323 | rtc_handle_legacy_irq(rtc, 1, RTC_UF); | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * rtc_pie_update_irq - PIE mode hrtimer hook | ||
329 | * @timer: pointer to the pie mode hrtimer | ||
330 | * | ||
331 | * This function is used to emulate PIE mode interrupts | ||
332 | * using an hrtimer. This function is called when the periodic | ||
333 | * hrtimer expires. | ||
334 | */ | ||
335 | enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) | ||
336 | { | ||
337 | struct rtc_device *rtc; | ||
338 | ktime_t period; | ||
339 | int count; | ||
340 | rtc = container_of(timer, struct rtc_device, pie_timer); | ||
341 | |||
342 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | ||
343 | count = hrtimer_forward_now(timer, period); | ||
344 | |||
345 | rtc_handle_legacy_irq(rtc, count, RTC_PF); | ||
346 | |||
347 | return HRTIMER_RESTART; | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * rtc_update_irq - Triggered when a RTC interrupt occurs. | ||
352 | * @rtc: the rtc device | ||
353 | * @num: how many irqs are being reported (usually one) | ||
354 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF | ||
355 | * Context: any | ||
356 | */ | ||
357 | void rtc_update_irq(struct rtc_device *rtc, | ||
358 | unsigned long num, unsigned long events) | ||
359 | { | ||
360 | schedule_work(&rtc->irqwork); | ||
361 | } | ||
394 | EXPORT_SYMBOL_GPL(rtc_update_irq); | 362 | EXPORT_SYMBOL_GPL(rtc_update_irq); |
395 | 363 | ||
396 | static int __rtc_match(struct device *dev, void *data) | 364 | static int __rtc_match(struct device *dev, void *data) |
@@ -477,18 +445,20 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
477 | int err = 0; | 445 | int err = 0; |
478 | unsigned long flags; | 446 | unsigned long flags; |
479 | 447 | ||
480 | if (rtc->ops->irq_set_state == NULL) | ||
481 | return -ENXIO; | ||
482 | |||
483 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 448 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
484 | if (rtc->irq_task != NULL && task == NULL) | 449 | if (rtc->irq_task != NULL && task == NULL) |
485 | err = -EBUSY; | 450 | err = -EBUSY; |
486 | if (rtc->irq_task != task) | 451 | if (rtc->irq_task != task) |
487 | err = -EACCES; | 452 | err = -EACCES; |
488 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
489 | 453 | ||
490 | if (err == 0) | 454 | if (enabled) { |
491 | err = rtc->ops->irq_set_state(rtc->dev.parent, enabled); | 455 | ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); |
456 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | ||
457 | } else { | ||
458 | hrtimer_cancel(&rtc->pie_timer); | ||
459 | } | ||
460 | rtc->pie_enabled = enabled; | ||
461 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
492 | 462 | ||
493 | return err; | 463 | return err; |
494 | } | 464 | } |
@@ -509,21 +479,206 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
509 | int err = 0; | 479 | int err = 0; |
510 | unsigned long flags; | 480 | unsigned long flags; |
511 | 481 | ||
512 | if (rtc->ops->irq_set_freq == NULL) | 482 | if (freq <= 0) |
513 | return -ENXIO; | 483 | return -EINVAL; |
514 | 484 | ||
515 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 485 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
516 | if (rtc->irq_task != NULL && task == NULL) | 486 | if (rtc->irq_task != NULL && task == NULL) |
517 | err = -EBUSY; | 487 | err = -EBUSY; |
518 | if (rtc->irq_task != task) | 488 | if (rtc->irq_task != task) |
519 | err = -EACCES; | 489 | err = -EACCES; |
520 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
521 | |||
522 | if (err == 0) { | 490 | if (err == 0) { |
523 | err = rtc->ops->irq_set_freq(rtc->dev.parent, freq); | 491 | rtc->irq_freq = freq; |
524 | if (err == 0) | 492 | if (rtc->pie_enabled) { |
525 | rtc->irq_freq = freq; | 493 | ktime_t period; |
494 | hrtimer_cancel(&rtc->pie_timer); | ||
495 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | ||
496 | hrtimer_start(&rtc->pie_timer, period, | ||
497 | HRTIMER_MODE_REL); | ||
498 | } | ||
526 | } | 499 | } |
500 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
527 | return err; | 501 | return err; |
528 | } | 502 | } |
529 | EXPORT_SYMBOL_GPL(rtc_irq_set_freq); | 503 | EXPORT_SYMBOL_GPL(rtc_irq_set_freq); |
504 | |||
505 | /** | ||
506 | * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue | ||
507 | * @rtc rtc device | ||
508 | * @timer timer being added. | ||
509 | * | ||
510 | * Enqueues a timer onto the rtc devices timerqueue and sets | ||
511 | * the next alarm event appropriately. | ||
512 | * | ||
513 | * Sets the enabled bit on the added timer. | ||
514 | * | ||
515 | * Must hold ops_lock for proper serialization of timerqueue | ||
516 | */ | ||
517 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | ||
518 | { | ||
519 | timer->enabled = 1; | ||
520 | timerqueue_add(&rtc->timerqueue, &timer->node); | ||
521 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { | ||
522 | struct rtc_wkalrm alarm; | ||
523 | int err; | ||
524 | alarm.time = rtc_ktime_to_tm(timer->node.expires); | ||
525 | alarm.enabled = 1; | ||
526 | err = __rtc_set_alarm(rtc, &alarm); | ||
527 | if (err == -ETIME) | ||
528 | schedule_work(&rtc->irqwork); | ||
529 | else if (err) { | ||
530 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
531 | timer->enabled = 0; | ||
532 | return err; | ||
533 | } | ||
534 | } | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | ||
540 | * @rtc rtc device | ||
541 | * @timer timer being removed. | ||
542 | * | ||
543 | * Removes a timer onto the rtc devices timerqueue and sets | ||
544 | * the next alarm event appropriately. | ||
545 | * | ||
546 | * Clears the enabled bit on the removed timer. | ||
547 | * | ||
548 | * Must hold ops_lock for proper serialization of timerqueue | ||
549 | */ | ||
550 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | ||
551 | { | ||
552 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | ||
553 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
554 | timer->enabled = 0; | ||
555 | if (next == &timer->node) { | ||
556 | struct rtc_wkalrm alarm; | ||
557 | int err; | ||
558 | next = timerqueue_getnext(&rtc->timerqueue); | ||
559 | if (!next) | ||
560 | return; | ||
561 | alarm.time = rtc_ktime_to_tm(next->expires); | ||
562 | alarm.enabled = 1; | ||
563 | err = __rtc_set_alarm(rtc, &alarm); | ||
564 | if (err == -ETIME) | ||
565 | schedule_work(&rtc->irqwork); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | /** | ||
570 | * rtc_timer_do_work - Expires rtc timers | ||
571 | * @rtc rtc device | ||
572 | * @timer timer being removed. | ||
573 | * | ||
574 | * Expires rtc timers. Reprograms next alarm event if needed. | ||
575 | * Called via worktask. | ||
576 | * | ||
577 | * Serializes access to timerqueue via ops_lock mutex | ||
578 | */ | ||
579 | void rtc_timer_do_work(struct work_struct *work) | ||
580 | { | ||
581 | struct rtc_timer *timer; | ||
582 | struct timerqueue_node *next; | ||
583 | ktime_t now; | ||
584 | struct rtc_time tm; | ||
585 | |||
586 | struct rtc_device *rtc = | ||
587 | container_of(work, struct rtc_device, irqwork); | ||
588 | |||
589 | mutex_lock(&rtc->ops_lock); | ||
590 | again: | ||
591 | __rtc_read_time(rtc, &tm); | ||
592 | now = rtc_tm_to_ktime(tm); | ||
593 | while ((next = timerqueue_getnext(&rtc->timerqueue))) { | ||
594 | if (next->expires.tv64 > now.tv64) | ||
595 | break; | ||
596 | |||
597 | /* expire timer */ | ||
598 | timer = container_of(next, struct rtc_timer, node); | ||
599 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
600 | timer->enabled = 0; | ||
601 | if (timer->task.func) | ||
602 | timer->task.func(timer->task.private_data); | ||
603 | |||
604 | /* Re-add/fwd periodic timers */ | ||
605 | if (ktime_to_ns(timer->period)) { | ||
606 | timer->node.expires = ktime_add(timer->node.expires, | ||
607 | timer->period); | ||
608 | timer->enabled = 1; | ||
609 | timerqueue_add(&rtc->timerqueue, &timer->node); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | /* Set next alarm */ | ||
614 | if (next) { | ||
615 | struct rtc_wkalrm alarm; | ||
616 | int err; | ||
617 | alarm.time = rtc_ktime_to_tm(next->expires); | ||
618 | alarm.enabled = 1; | ||
619 | err = __rtc_set_alarm(rtc, &alarm); | ||
620 | if (err == -ETIME) | ||
621 | goto again; | ||
622 | } | ||
623 | |||
624 | mutex_unlock(&rtc->ops_lock); | ||
625 | } | ||
626 | |||
627 | |||
628 | /* rtc_timer_init - Initializes an rtc_timer | ||
629 | * @timer: timer to be intiialized | ||
630 | * @f: function pointer to be called when timer fires | ||
631 | * @data: private data passed to function pointer | ||
632 | * | ||
633 | * Kernel interface to initializing an rtc_timer. | ||
634 | */ | ||
635 | void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data) | ||
636 | { | ||
637 | timerqueue_init(&timer->node); | ||
638 | timer->enabled = 0; | ||
639 | timer->task.func = f; | ||
640 | timer->task.private_data = data; | ||
641 | } | ||
642 | |||
643 | /* rtc_timer_start - Sets an rtc_timer to fire in the future | ||
644 | * @ rtc: rtc device to be used | ||
645 | * @ timer: timer being set | ||
646 | * @ expires: time at which to expire the timer | ||
647 | * @ period: period that the timer will recur | ||
648 | * | ||
649 | * Kernel interface to set an rtc_timer | ||
650 | */ | ||
651 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, | ||
652 | ktime_t expires, ktime_t period) | ||
653 | { | ||
654 | int ret = 0; | ||
655 | mutex_lock(&rtc->ops_lock); | ||
656 | if (timer->enabled) | ||
657 | rtc_timer_remove(rtc, timer); | ||
658 | |||
659 | timer->node.expires = expires; | ||
660 | timer->period = period; | ||
661 | |||
662 | ret = rtc_timer_enqueue(rtc, timer); | ||
663 | |||
664 | mutex_unlock(&rtc->ops_lock); | ||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | /* rtc_timer_cancel - Stops an rtc_timer | ||
669 | * @ rtc: rtc device to be used | ||
670 | * @ timer: timer being set | ||
671 | * | ||
672 | * Kernel interface to cancel an rtc_timer | ||
673 | */ | ||
674 | int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer) | ||
675 | { | ||
676 | int ret = 0; | ||
677 | mutex_lock(&rtc->ops_lock); | ||
678 | if (timer->enabled) | ||
679 | rtc_timer_remove(rtc, timer); | ||
680 | mutex_unlock(&rtc->ops_lock); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | |||
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-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index b2752b6e7a2f..e725d51e773d 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -134,36 +134,29 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
134 | return ret; | 134 | return ret; |
135 | } | 135 | } |
136 | 136 | ||
137 | static int at32_rtc_ioctl(struct device *dev, unsigned int cmd, | 137 | static int at32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
138 | unsigned long arg) | ||
139 | { | 138 | { |
140 | struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); | 139 | struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); |
141 | int ret = 0; | 140 | int ret = 0; |
142 | 141 | ||
143 | spin_lock_irq(&rtc->lock); | 142 | spin_lock_irq(&rtc->lock); |
144 | 143 | ||
145 | switch (cmd) { | 144 | if(enabled) { |
146 | case RTC_AIE_ON: | ||
147 | if (rtc_readl(rtc, VAL) > rtc->alarm_time) { | 145 | if (rtc_readl(rtc, VAL) > rtc->alarm_time) { |
148 | ret = -EINVAL; | 146 | ret = -EINVAL; |
149 | break; | 147 | goto out; |
150 | } | 148 | } |
151 | rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | 149 | rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) |
152 | | RTC_BIT(CTRL_TOPEN)); | 150 | | RTC_BIT(CTRL_TOPEN)); |
153 | rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); | 151 | rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); |
154 | rtc_writel(rtc, IER, RTC_BIT(IER_TOPI)); | 152 | rtc_writel(rtc, IER, RTC_BIT(IER_TOPI)); |
155 | break; | 153 | } else { |
156 | case RTC_AIE_OFF: | ||
157 | rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | 154 | rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) |
158 | & ~RTC_BIT(CTRL_TOPEN)); | 155 | & ~RTC_BIT(CTRL_TOPEN)); |
159 | rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); | 156 | rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); |
160 | rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); | 157 | rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); |
161 | break; | ||
162 | default: | ||
163 | ret = -ENOIOCTLCMD; | ||
164 | break; | ||
165 | } | 158 | } |
166 | 159 | out: | |
167 | spin_unlock_irq(&rtc->lock); | 160 | spin_unlock_irq(&rtc->lock); |
168 | 161 | ||
169 | return ret; | 162 | return ret; |
@@ -195,11 +188,11 @@ static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id) | |||
195 | } | 188 | } |
196 | 189 | ||
197 | static struct rtc_class_ops at32_rtc_ops = { | 190 | static struct rtc_class_ops at32_rtc_ops = { |
198 | .ioctl = at32_rtc_ioctl, | ||
199 | .read_time = at32_rtc_readtime, | 191 | .read_time = at32_rtc_readtime, |
200 | .set_time = at32_rtc_settime, | 192 | .set_time = at32_rtc_settime, |
201 | .read_alarm = at32_rtc_readalarm, | 193 | .read_alarm = at32_rtc_readalarm, |
202 | .set_alarm = at32_rtc_setalarm, | 194 | .set_alarm = at32_rtc_setalarm, |
195 | .alarm_irq_enable = at32_rtc_alarm_irq_enable, | ||
203 | }; | 196 | }; |
204 | 197 | ||
205 | static int __init at32_rtc_probe(struct platform_device *pdev) | 198 | static int __init at32_rtc_probe(struct platform_device *pdev) |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index bc8bbca9a2e2..26d1cf5d19ae 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -195,13 +195,6 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
195 | 195 | ||
196 | /* important: scrub old status before enabling IRQs */ | 196 | /* important: scrub old status before enabling IRQs */ |
197 | switch (cmd) { | 197 | switch (cmd) { |
198 | case RTC_AIE_OFF: /* alarm off */ | ||
199 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | ||
200 | break; | ||
201 | case RTC_AIE_ON: /* alarm on */ | ||
202 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
203 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | ||
204 | break; | ||
205 | case RTC_UIE_OFF: /* update off */ | 198 | case RTC_UIE_OFF: /* update off */ |
206 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); | 199 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); |
207 | break; | 200 | break; |
@@ -217,6 +210,18 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
217 | return ret; | 210 | return ret; |
218 | } | 211 | } |
219 | 212 | ||
213 | static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
214 | { | ||
215 | pr_debug("%s(): cmd=%08x\n", __func__, enabled); | ||
216 | |||
217 | if (enabled) { | ||
218 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
219 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | ||
220 | } else | ||
221 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
220 | /* | 225 | /* |
221 | * Provide additional RTC information in /proc/driver/rtc | 226 | * Provide additional RTC information in /proc/driver/rtc |
222 | */ | 227 | */ |
@@ -270,6 +275,7 @@ static const struct rtc_class_ops at91_rtc_ops = { | |||
270 | .read_alarm = at91_rtc_readalarm, | 275 | .read_alarm = at91_rtc_readalarm, |
271 | .set_alarm = at91_rtc_setalarm, | 276 | .set_alarm = at91_rtc_setalarm, |
272 | .proc = at91_rtc_proc, | 277 | .proc = at91_rtc_proc, |
278 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, | ||
273 | }; | 279 | }; |
274 | 280 | ||
275 | /* | 281 | /* |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index f677e0710ca1..5469c52cba3d 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -229,12 +229,6 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
229 | dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); | 229 | dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); |
230 | 230 | ||
231 | switch (cmd) { | 231 | switch (cmd) { |
232 | case RTC_AIE_OFF: /* alarm off */ | ||
233 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
234 | break; | ||
235 | case RTC_AIE_ON: /* alarm on */ | ||
236 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
237 | break; | ||
238 | case RTC_UIE_OFF: /* update off */ | 232 | case RTC_UIE_OFF: /* update off */ |
239 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | 233 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); |
240 | break; | 234 | break; |
@@ -249,6 +243,19 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
249 | return ret; | 243 | return ret; |
250 | } | 244 | } |
251 | 245 | ||
246 | static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
247 | { | ||
248 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
249 | u32 mr = rtt_readl(rtc, MR); | ||
250 | |||
251 | dev_dbg(dev, "alarm_irq_enable: enabled=%08x, mr %08x\n", enabled, mr); | ||
252 | if (enabled) | ||
253 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
254 | else | ||
255 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
252 | /* | 259 | /* |
253 | * Provide additional RTC information in /proc/driver/rtc | 260 | * Provide additional RTC information in /proc/driver/rtc |
254 | */ | 261 | */ |
@@ -302,6 +309,7 @@ static const struct rtc_class_ops at91_rtc_ops = { | |||
302 | .read_alarm = at91_rtc_readalarm, | 309 | .read_alarm = at91_rtc_readalarm, |
303 | .set_alarm = at91_rtc_setalarm, | 310 | .set_alarm = at91_rtc_setalarm, |
304 | .proc = at91_rtc_proc, | 311 | .proc = at91_rtc_proc, |
312 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, | ||
305 | }; | 313 | }; |
306 | 314 | ||
307 | /* | 315 | /* |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index d4fb82d85e9b..17971d93354d 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 | ||
@@ -254,15 +259,6 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
254 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); | 259 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); |
255 | break; | 260 | break; |
256 | 261 | ||
257 | case RTC_AIE_ON: | ||
258 | dev_dbg_stamp(dev); | ||
259 | bfin_rtc_int_set_alarm(rtc); | ||
260 | break; | ||
261 | case RTC_AIE_OFF: | ||
262 | dev_dbg_stamp(dev); | ||
263 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | ||
264 | break; | ||
265 | |||
266 | default: | 262 | default: |
267 | dev_dbg_stamp(dev); | 263 | dev_dbg_stamp(dev); |
268 | ret = -ENOIOCTLCMD; | 264 | ret = -ENOIOCTLCMD; |
@@ -271,6 +267,17 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
271 | return ret; | 267 | return ret; |
272 | } | 268 | } |
273 | 269 | ||
270 | static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
271 | { | ||
272 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | ||
273 | |||
274 | dev_dbg_stamp(dev); | ||
275 | if (enabled) | ||
276 | bfin_rtc_int_set_alarm(rtc); | ||
277 | else | ||
278 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | ||
279 | } | ||
280 | |||
274 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) | 281 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) |
275 | { | 282 | { |
276 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 283 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
@@ -357,6 +364,7 @@ static struct rtc_class_ops bfin_rtc_ops = { | |||
357 | .read_alarm = bfin_rtc_read_alarm, | 364 | .read_alarm = bfin_rtc_read_alarm, |
358 | .set_alarm = bfin_rtc_set_alarm, | 365 | .set_alarm = bfin_rtc_set_alarm, |
359 | .proc = bfin_rtc_proc, | 366 | .proc = bfin_rtc_proc, |
367 | .alarm_irq_enable = bfin_rtc_alarm_irq_enable, | ||
360 | }; | 368 | }; |
361 | 369 | ||
362 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) | 370 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) |
@@ -422,9 +430,13 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
422 | #ifdef CONFIG_PM | 430 | #ifdef CONFIG_PM |
423 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 431 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
424 | { | 432 | { |
425 | if (device_may_wakeup(&pdev->dev)) { | 433 | struct device *dev = &pdev->dev; |
434 | |||
435 | dev_dbg_stamp(dev); | ||
436 | |||
437 | if (device_may_wakeup(dev)) { | ||
426 | enable_irq_wake(IRQ_RTC); | 438 | enable_irq_wake(IRQ_RTC); |
427 | bfin_rtc_sync_pending(&pdev->dev); | 439 | bfin_rtc_sync_pending(dev); |
428 | } else | 440 | } else |
429 | bfin_rtc_int_clear(0); | 441 | bfin_rtc_int_clear(0); |
430 | 442 | ||
@@ -433,7 +445,11 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
433 | 445 | ||
434 | static int bfin_rtc_resume(struct platform_device *pdev) | 446 | static int bfin_rtc_resume(struct platform_device *pdev) |
435 | { | 447 | { |
436 | if (device_may_wakeup(&pdev->dev)) | 448 | struct device *dev = &pdev->dev; |
449 | |||
450 | dev_dbg_stamp(dev); | ||
451 | |||
452 | if (device_may_wakeup(dev)) | ||
437 | disable_irq_wake(IRQ_RTC); | 453 | disable_irq_wake(IRQ_RTC); |
438 | 454 | ||
439 | /* | 455 | /* |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5856167a0c90..c7ff8df347e7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | ||
39 | 40 | ||
40 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 41 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
41 | #include <asm-generic/rtc.h> | 42 | #include <asm-generic/rtc.h> |
@@ -687,7 +688,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
687 | #if defined(CONFIG_ATARI) | 688 | #if defined(CONFIG_ATARI) |
688 | address_space = 64; | 689 | address_space = 64; |
689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ | 690 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) | 691 | || defined(__sparc__) || defined(__mips__) \ |
692 | || defined(__powerpc__) | ||
691 | address_space = 128; | 693 | address_space = 128; |
692 | #else | 694 | #else |
693 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 695 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
@@ -850,7 +852,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
850 | 852 | ||
851 | #ifdef CONFIG_PM | 853 | #ifdef CONFIG_PM |
852 | 854 | ||
853 | static int cmos_suspend(struct device *dev, pm_message_t mesg) | 855 | static int cmos_suspend(struct device *dev) |
854 | { | 856 | { |
855 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 857 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
856 | unsigned char tmp; | 858 | unsigned char tmp; |
@@ -898,7 +900,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
898 | */ | 900 | */ |
899 | static inline int cmos_poweroff(struct device *dev) | 901 | static inline int cmos_poweroff(struct device *dev) |
900 | { | 902 | { |
901 | return cmos_suspend(dev, PMSG_HIBERNATE); | 903 | return cmos_suspend(dev); |
902 | } | 904 | } |
903 | 905 | ||
904 | static int cmos_resume(struct device *dev) | 906 | static int cmos_resume(struct device *dev) |
@@ -945,9 +947,9 @@ static int cmos_resume(struct device *dev) | |||
945 | return 0; | 947 | return 0; |
946 | } | 948 | } |
947 | 949 | ||
950 | static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); | ||
951 | |||
948 | #else | 952 | #else |
949 | #define cmos_suspend NULL | ||
950 | #define cmos_resume NULL | ||
951 | 953 | ||
952 | static inline int cmos_poweroff(struct device *dev) | 954 | static inline int cmos_poweroff(struct device *dev) |
953 | { | 955 | { |
@@ -1077,7 +1079,7 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | |||
1077 | 1079 | ||
1078 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) | 1080 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) |
1079 | { | 1081 | { |
1080 | return cmos_suspend(&pnp->dev, mesg); | 1082 | return cmos_suspend(&pnp->dev); |
1081 | } | 1083 | } |
1082 | 1084 | ||
1083 | static int cmos_pnp_resume(struct pnp_dev *pnp) | 1085 | static int cmos_pnp_resume(struct pnp_dev *pnp) |
@@ -1157,8 +1159,9 @@ static struct platform_driver cmos_platform_driver = { | |||
1157 | .shutdown = cmos_platform_shutdown, | 1159 | .shutdown = cmos_platform_shutdown, |
1158 | .driver = { | 1160 | .driver = { |
1159 | .name = (char *) driver_name, | 1161 | .name = (char *) driver_name, |
1160 | .suspend = cmos_suspend, | 1162 | #ifdef CONFIG_PM |
1161 | .resume = cmos_resume, | 1163 | .pm = &cmos_pm_ops, |
1164 | #endif | ||
1162 | } | 1165 | } |
1163 | }; | 1166 | }; |
1164 | 1167 | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 62227cd52410..d0e06edb14c5 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -76,7 +76,7 @@ static void rtc_uie_task(struct work_struct *work) | |||
76 | } | 76 | } |
77 | spin_unlock_irq(&rtc->irq_lock); | 77 | spin_unlock_irq(&rtc->irq_lock); |
78 | if (num) | 78 | if (num) |
79 | rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF); | 79 | rtc_handle_legacy_irq(rtc, num, RTC_UF); |
80 | } | 80 | } |
81 | static void rtc_uie_timer(unsigned long data) | 81 | static void rtc_uie_timer(unsigned long data) |
82 | { | 82 | { |
@@ -253,19 +253,7 @@ static long rtc_dev_ioctl(struct file *file, | |||
253 | if (err) | 253 | if (err) |
254 | goto done; | 254 | goto done; |
255 | 255 | ||
256 | /* try the driver's ioctl interface */ | 256 | /* |
257 | if (ops->ioctl) { | ||
258 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | ||
259 | if (err != -ENOIOCTLCMD) { | ||
260 | mutex_unlock(&rtc->ops_lock); | ||
261 | return err; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /* if the driver does not provide the ioctl interface | ||
266 | * or if that particular ioctl was not implemented | ||
267 | * (-ENOIOCTLCMD), we will try to emulate here. | ||
268 | * | ||
269 | * Drivers *SHOULD NOT* provide ioctl implementations | 257 | * Drivers *SHOULD NOT* provide ioctl implementations |
270 | * for these requests. Instead, provide methods to | 258 | * for these requests. Instead, provide methods to |
271 | * support the following code, so that the RTC's main | 259 | * support the following code, so that the RTC's main |
@@ -428,7 +416,12 @@ static long rtc_dev_ioctl(struct file *file, | |||
428 | return err; | 416 | return err; |
429 | 417 | ||
430 | default: | 418 | default: |
431 | err = -ENOTTY; | 419 | /* Finally try the driver's ioctl interface */ |
420 | if (ops->ioctl) { | ||
421 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | ||
422 | if (err == -ENOIOCTLCMD) | ||
423 | err = -ENOTTY; | ||
424 | } | ||
432 | break; | 425 | break; |
433 | } | 426 | } |
434 | 427 | ||
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index bf430f9091ed..60ce69600828 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -40,6 +40,26 @@ static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg) | |||
40 | __raw_writel(data, &priv->rtcregs[reg]); | 40 | __raw_writel(data, &priv->rtcregs[reg]); |
41 | } | 41 | } |
42 | 42 | ||
43 | |||
44 | static int ds1286_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
45 | { | ||
46 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
47 | unsigned long flags; | ||
48 | unsigned char val; | ||
49 | |||
50 | /* Allow or mask alarm interrupts */ | ||
51 | spin_lock_irqsave(&priv->lock, flags); | ||
52 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
53 | if (enabled) | ||
54 | val &= ~RTC_TDM; | ||
55 | else | ||
56 | val |= RTC_TDM; | ||
57 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
58 | spin_unlock_irqrestore(&priv->lock, flags); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
43 | #ifdef CONFIG_RTC_INTF_DEV | 63 | #ifdef CONFIG_RTC_INTF_DEV |
44 | 64 | ||
45 | static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 65 | static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
@@ -49,22 +69,6 @@ static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
49 | unsigned char val; | 69 | unsigned char val; |
50 | 70 | ||
51 | switch (cmd) { | 71 | switch (cmd) { |
52 | case RTC_AIE_OFF: | ||
53 | /* Mask alarm int. enab. bit */ | ||
54 | spin_lock_irqsave(&priv->lock, flags); | ||
55 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
56 | val |= RTC_TDM; | ||
57 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
58 | spin_unlock_irqrestore(&priv->lock, flags); | ||
59 | break; | ||
60 | case RTC_AIE_ON: | ||
61 | /* Allow alarm interrupts. */ | ||
62 | spin_lock_irqsave(&priv->lock, flags); | ||
63 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
64 | val &= ~RTC_TDM; | ||
65 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
66 | spin_unlock_irqrestore(&priv->lock, flags); | ||
67 | break; | ||
68 | case RTC_WIE_OFF: | 72 | case RTC_WIE_OFF: |
69 | /* Mask watchdog int. enab. bit */ | 73 | /* Mask watchdog int. enab. bit */ |
70 | spin_lock_irqsave(&priv->lock, flags); | 74 | spin_lock_irqsave(&priv->lock, flags); |
@@ -316,12 +320,13 @@ static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
316 | } | 320 | } |
317 | 321 | ||
318 | static const struct rtc_class_ops ds1286_ops = { | 322 | static const struct rtc_class_ops ds1286_ops = { |
319 | .ioctl = ds1286_ioctl, | 323 | .ioctl = ds1286_ioctl, |
320 | .proc = ds1286_proc, | 324 | .proc = ds1286_proc, |
321 | .read_time = ds1286_read_time, | 325 | .read_time = ds1286_read_time, |
322 | .set_time = ds1286_set_time, | 326 | .set_time = ds1286_set_time, |
323 | .read_alarm = ds1286_read_alarm, | 327 | .read_alarm = ds1286_read_alarm, |
324 | .set_alarm = ds1286_set_alarm, | 328 | .set_alarm = ds1286_set_alarm, |
329 | .alarm_irq_enable = ds1286_alarm_irq_enable, | ||
325 | }; | 330 | }; |
326 | 331 | ||
327 | static int __devinit ds1286_probe(struct platform_device *pdev) | 332 | static int __devinit ds1286_probe(struct platform_device *pdev) |
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-ds1305.c b/drivers/rtc/rtc-ds1305.c index 48da85e97ca4..57fbcc149ba7 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -139,49 +139,32 @@ static u8 hour2bcd(bool hr12, int hour) | |||
139 | * Interface to RTC framework | 139 | * Interface to RTC framework |
140 | */ | 140 | */ |
141 | 141 | ||
142 | #ifdef CONFIG_RTC_INTF_DEV | 142 | static int ds1305_alarm_irq_enable(struct device *dev, unsigned int enabled) |
143 | |||
144 | /* | ||
145 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
146 | */ | ||
147 | static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg) | ||
148 | { | 143 | { |
149 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | 144 | struct ds1305 *ds1305 = dev_get_drvdata(dev); |
150 | u8 buf[2]; | 145 | u8 buf[2]; |
151 | int status = -ENOIOCTLCMD; | 146 | long err = -EINVAL; |
152 | 147 | ||
153 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | 148 | buf[0] = DS1305_WRITE | DS1305_CONTROL; |
154 | buf[1] = ds1305->ctrl[0]; | 149 | buf[1] = ds1305->ctrl[0]; |
155 | 150 | ||
156 | switch (cmd) { | 151 | if (enabled) { |
157 | case RTC_AIE_OFF: | ||
158 | status = 0; | ||
159 | if (!(buf[1] & DS1305_AEI0)) | ||
160 | goto done; | ||
161 | buf[1] &= ~DS1305_AEI0; | ||
162 | break; | ||
163 | |||
164 | case RTC_AIE_ON: | ||
165 | status = 0; | ||
166 | if (ds1305->ctrl[0] & DS1305_AEI0) | 152 | if (ds1305->ctrl[0] & DS1305_AEI0) |
167 | goto done; | 153 | goto done; |
168 | buf[1] |= DS1305_AEI0; | 154 | buf[1] |= DS1305_AEI0; |
169 | break; | 155 | } else { |
170 | } | 156 | if (!(buf[1] & DS1305_AEI0)) |
171 | if (status == 0) { | 157 | goto done; |
172 | status = spi_write_then_read(ds1305->spi, buf, sizeof buf, | 158 | buf[1] &= ~DS1305_AEI0; |
173 | NULL, 0); | ||
174 | if (status >= 0) | ||
175 | ds1305->ctrl[0] = buf[1]; | ||
176 | } | 159 | } |
177 | 160 | err = spi_write_then_read(ds1305->spi, buf, sizeof buf, NULL, 0); | |
161 | if (err >= 0) | ||
162 | ds1305->ctrl[0] = buf[1]; | ||
178 | done: | 163 | done: |
179 | return status; | 164 | return err; |
165 | |||
180 | } | 166 | } |
181 | 167 | ||
182 | #else | ||
183 | #define ds1305_ioctl NULL | ||
184 | #endif | ||
185 | 168 | ||
186 | /* | 169 | /* |
187 | * Get/set of date and time is pretty normal. | 170 | * Get/set of date and time is pretty normal. |
@@ -460,12 +443,12 @@ done: | |||
460 | #endif | 443 | #endif |
461 | 444 | ||
462 | static const struct rtc_class_ops ds1305_ops = { | 445 | static const struct rtc_class_ops ds1305_ops = { |
463 | .ioctl = ds1305_ioctl, | ||
464 | .read_time = ds1305_get_time, | 446 | .read_time = ds1305_get_time, |
465 | .set_time = ds1305_set_time, | 447 | .set_time = ds1305_set_time, |
466 | .read_alarm = ds1305_get_alarm, | 448 | .read_alarm = ds1305_get_alarm, |
467 | .set_alarm = ds1305_set_alarm, | 449 | .set_alarm = ds1305_set_alarm, |
468 | .proc = ds1305_proc, | 450 | .proc = ds1305_proc, |
451 | .alarm_irq_enable = ds1305_alarm_irq_enable, | ||
469 | }; | 452 | }; |
470 | 453 | ||
471 | static void ds1305_work(struct work_struct *work) | 454 | static void ds1305_work(struct work_struct *work) |
@@ -813,7 +796,7 @@ static int __devexit ds1305_remove(struct spi_device *spi) | |||
813 | if (spi->irq) { | 796 | if (spi->irq) { |
814 | set_bit(FLAG_EXITING, &ds1305->flags); | 797 | set_bit(FLAG_EXITING, &ds1305->flags); |
815 | free_irq(spi->irq, ds1305); | 798 | free_irq(spi->irq, ds1305); |
816 | flush_scheduled_work(); | 799 | cancel_work_sync(&ds1305->work); |
817 | } | 800 | } |
818 | 801 | ||
819 | rtc_device_unregister(ds1305->rtc); | 802 | rtc_device_unregister(ds1305->rtc); |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index d827ce570a8c..4724ba3acf1a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -106,9 +106,9 @@ struct ds1307 { | |||
106 | struct i2c_client *client; | 106 | struct i2c_client *client; |
107 | struct rtc_device *rtc; | 107 | struct rtc_device *rtc; |
108 | struct work_struct work; | 108 | struct work_struct work; |
109 | s32 (*read_block_data)(struct i2c_client *client, u8 command, | 109 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, |
110 | u8 length, u8 *values); | 110 | u8 length, u8 *values); |
111 | s32 (*write_block_data)(struct i2c_client *client, u8 command, | 111 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, |
112 | u8 length, const u8 *values); | 112 | u8 length, const u8 *values); |
113 | }; | 113 | }; |
114 | 114 | ||
@@ -158,8 +158,8 @@ MODULE_DEVICE_TABLE(i2c, ds1307_id); | |||
158 | 158 | ||
159 | #define BLOCK_DATA_MAX_TRIES 10 | 159 | #define BLOCK_DATA_MAX_TRIES 10 |
160 | 160 | ||
161 | static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | 161 | static s32 ds1307_read_block_data_once(const struct i2c_client *client, |
162 | u8 length, u8 *values) | 162 | u8 command, u8 length, u8 *values) |
163 | { | 163 | { |
164 | s32 i, data; | 164 | s32 i, data; |
165 | 165 | ||
@@ -172,7 +172,7 @@ static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | |||
172 | return i; | 172 | return i; |
173 | } | 173 | } |
174 | 174 | ||
175 | static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | 175 | static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command, |
176 | u8 length, u8 *values) | 176 | u8 length, u8 *values) |
177 | { | 177 | { |
178 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; | 178 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; |
@@ -198,7 +198,7 @@ static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | |||
198 | return length; | 198 | return length; |
199 | } | 199 | } |
200 | 200 | ||
201 | static s32 ds1307_write_block_data(struct i2c_client *client, u8 command, | 201 | static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command, |
202 | u8 length, const u8 *values) | 202 | u8 length, const u8 *values) |
203 | { | 203 | { |
204 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; | 204 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; |
@@ -495,50 +495,27 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
495 | return 0; | 495 | return 0; |
496 | } | 496 | } |
497 | 497 | ||
498 | static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 498 | static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled) |
499 | { | 499 | { |
500 | struct i2c_client *client = to_i2c_client(dev); | 500 | struct i2c_client *client = to_i2c_client(dev); |
501 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 501 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
502 | int ret; | 502 | int ret; |
503 | 503 | ||
504 | switch (cmd) { | 504 | if (!test_bit(HAS_ALARM, &ds1307->flags)) |
505 | case RTC_AIE_OFF: | 505 | return -ENOTTY; |
506 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
507 | return -ENOTTY; | ||
508 | |||
509 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
510 | if (ret < 0) | ||
511 | return ret; | ||
512 | |||
513 | ret &= ~DS1337_BIT_A1IE; | ||
514 | |||
515 | ret = i2c_smbus_write_byte_data(client, | ||
516 | DS1337_REG_CONTROL, ret); | ||
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | |||
520 | break; | ||
521 | |||
522 | case RTC_AIE_ON: | ||
523 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
524 | return -ENOTTY; | ||
525 | 506 | ||
526 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | 507 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); |
527 | if (ret < 0) | 508 | if (ret < 0) |
528 | return ret; | 509 | return ret; |
529 | 510 | ||
511 | if (enabled) | ||
530 | ret |= DS1337_BIT_A1IE; | 512 | ret |= DS1337_BIT_A1IE; |
513 | else | ||
514 | ret &= ~DS1337_BIT_A1IE; | ||
531 | 515 | ||
532 | ret = i2c_smbus_write_byte_data(client, | 516 | ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, ret); |
533 | DS1337_REG_CONTROL, ret); | 517 | if (ret < 0) |
534 | if (ret < 0) | 518 | return ret; |
535 | return ret; | ||
536 | |||
537 | break; | ||
538 | |||
539 | default: | ||
540 | return -ENOIOCTLCMD; | ||
541 | } | ||
542 | 519 | ||
543 | return 0; | 520 | return 0; |
544 | } | 521 | } |
@@ -548,7 +525,7 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { | |||
548 | .set_time = ds1307_set_time, | 525 | .set_time = ds1307_set_time, |
549 | .read_alarm = ds1337_read_alarm, | 526 | .read_alarm = ds1337_read_alarm, |
550 | .set_alarm = ds1337_set_alarm, | 527 | .set_alarm = ds1337_set_alarm, |
551 | .ioctl = ds1307_ioctl, | 528 | .alarm_irq_enable = ds1307_alarm_irq_enable, |
552 | }; | 529 | }; |
553 | 530 | ||
554 | /*----------------------------------------------------------------------*/ | 531 | /*----------------------------------------------------------------------*/ |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 1f0007fd4431..d834a63ec4b0 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -307,42 +307,25 @@ unlock: | |||
307 | mutex_unlock(&ds1374->mutex); | 307 | mutex_unlock(&ds1374->mutex); |
308 | } | 308 | } |
309 | 309 | ||
310 | static int ds1374_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 310 | static int ds1374_alarm_irq_enable(struct device *dev, unsigned int enabled) |
311 | { | 311 | { |
312 | struct i2c_client *client = to_i2c_client(dev); | 312 | struct i2c_client *client = to_i2c_client(dev); |
313 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | 313 | struct ds1374 *ds1374 = i2c_get_clientdata(client); |
314 | int ret = -ENOIOCTLCMD; | 314 | int ret; |
315 | 315 | ||
316 | mutex_lock(&ds1374->mutex); | 316 | mutex_lock(&ds1374->mutex); |
317 | 317 | ||
318 | switch (cmd) { | 318 | ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); |
319 | case RTC_AIE_OFF: | 319 | if (ret < 0) |
320 | ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | 320 | goto out; |
321 | if (ret < 0) | ||
322 | goto out; | ||
323 | |||
324 | ret &= ~DS1374_REG_CR_WACE; | ||
325 | |||
326 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); | ||
327 | if (ret < 0) | ||
328 | goto out; | ||
329 | |||
330 | break; | ||
331 | |||
332 | case RTC_AIE_ON: | ||
333 | ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
334 | if (ret < 0) | ||
335 | goto out; | ||
336 | 321 | ||
322 | if (enabled) { | ||
337 | ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; | 323 | ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; |
338 | ret &= ~DS1374_REG_CR_WDALM; | 324 | ret &= ~DS1374_REG_CR_WDALM; |
339 | 325 | } else { | |
340 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); | 326 | ret &= ~DS1374_REG_CR_WACE; |
341 | if (ret < 0) | ||
342 | goto out; | ||
343 | |||
344 | break; | ||
345 | } | 327 | } |
328 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); | ||
346 | 329 | ||
347 | out: | 330 | out: |
348 | mutex_unlock(&ds1374->mutex); | 331 | mutex_unlock(&ds1374->mutex); |
@@ -354,7 +337,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = { | |||
354 | .set_time = ds1374_set_time, | 337 | .set_time = ds1374_set_time, |
355 | .read_alarm = ds1374_read_alarm, | 338 | .read_alarm = ds1374_read_alarm, |
356 | .set_alarm = ds1374_set_alarm, | 339 | .set_alarm = ds1374_set_alarm, |
357 | .ioctl = ds1374_ioctl, | 340 | .alarm_irq_enable = ds1374_alarm_irq_enable, |
358 | }; | 341 | }; |
359 | 342 | ||
360 | static int ds1374_probe(struct i2c_client *client, | 343 | static int ds1374_probe(struct i2c_client *client, |
@@ -417,7 +400,7 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
417 | mutex_unlock(&ds1374->mutex); | 400 | mutex_unlock(&ds1374->mutex); |
418 | 401 | ||
419 | free_irq(client->irq, client); | 402 | free_irq(client->irq, client); |
420 | flush_scheduled_work(); | 403 | cancel_work_sync(&ds1374->work); |
421 | } | 404 | } |
422 | 405 | ||
423 | rtc_device_unregister(ds1374->rtc); | 406 | rtc_device_unregister(ds1374->rtc); |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 9de8516e3531..23a9ee19764c 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | 2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C |
3 | * | 3 | * |
4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | 4 | * Copyright (C) 2009-2010 Freescale Semiconductor. |
5 | * Author: Jack Lan <jack.lan@freescale.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
@@ -175,6 +176,182 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time) | |||
175 | DS3232_REG_SECONDS, 7, buf); | 176 | DS3232_REG_SECONDS, 7, buf); |
176 | } | 177 | } |
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 | |||
178 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | 355 | static irqreturn_t ds3232_irq(int irq, void *dev_id) |
179 | { | 356 | { |
180 | struct i2c_client *client = dev_id; | 357 | struct i2c_client *client = dev_id; |
@@ -222,6 +399,10 @@ unlock: | |||
222 | static const struct rtc_class_ops ds3232_rtc_ops = { | 399 | static const struct rtc_class_ops ds3232_rtc_ops = { |
223 | .read_time = ds3232_read_time, | 400 | .read_time = ds3232_read_time, |
224 | .set_time = ds3232_set_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, | ||
225 | }; | 406 | }; |
226 | 407 | ||
227 | static int __devinit ds3232_probe(struct i2c_client *client, | 408 | static int __devinit ds3232_probe(struct i2c_client *client, |
@@ -282,7 +463,7 @@ static int __devexit ds3232_remove(struct i2c_client *client) | |||
282 | mutex_unlock(&ds3232->mutex); | 463 | mutex_unlock(&ds3232->mutex); |
283 | 464 | ||
284 | free_irq(client->irq, client); | 465 | free_irq(client->irq, client); |
285 | flush_scheduled_work(); | 466 | cancel_work_sync(&ds3232->work); |
286 | } | 467 | } |
287 | 468 | ||
288 | rtc_device_unregister(ds3232->rtc); | 469 | rtc_device_unregister(ds3232->rtc); |
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-lib.c b/drivers/rtc/rtc-lib.c index 773851f338b8..075f1708deae 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -117,4 +117,32 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |||
117 | } | 117 | } |
118 | EXPORT_SYMBOL(rtc_tm_to_time); | 118 | EXPORT_SYMBOL(rtc_tm_to_time); |
119 | 119 | ||
120 | /* | ||
121 | * Convert rtc_time to ktime | ||
122 | */ | ||
123 | ktime_t rtc_tm_to_ktime(struct rtc_time tm) | ||
124 | { | ||
125 | time_t time; | ||
126 | rtc_tm_to_time(&tm, &time); | ||
127 | return ktime_set(time, 0); | ||
128 | } | ||
129 | EXPORT_SYMBOL_GPL(rtc_tm_to_ktime); | ||
130 | |||
131 | /* | ||
132 | * Convert ktime to rtc_time | ||
133 | */ | ||
134 | struct rtc_time rtc_ktime_to_tm(ktime_t kt) | ||
135 | { | ||
136 | struct timespec ts; | ||
137 | struct rtc_time ret; | ||
138 | |||
139 | ts = ktime_to_timespec(kt); | ||
140 | /* Round up any ns */ | ||
141 | if (ts.tv_nsec) | ||
142 | ts.tv_sec++; | ||
143 | rtc_time_to_tm(ts.tv_sec, &ret); | ||
144 | return ret; | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(rtc_ktime_to_tm); | ||
147 | |||
120 | MODULE_LICENSE("GPL"); | 148 | MODULE_LICENSE("GPL"); |
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 d60557cae8ef..69fe664a2228 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 }, |
@@ -212,41 +213,27 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
212 | return m41t80_set_datetime(to_i2c_client(dev), tm); | 213 | return m41t80_set_datetime(to_i2c_client(dev), tm); |
213 | } | 214 | } |
214 | 215 | ||
215 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | 216 | static int m41t80_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
216 | static int | ||
217 | m41t80_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
218 | { | 217 | { |
219 | struct i2c_client *client = to_i2c_client(dev); | 218 | struct i2c_client *client = to_i2c_client(dev); |
220 | int rc; | 219 | int rc; |
221 | 220 | ||
222 | switch (cmd) { | ||
223 | case RTC_AIE_OFF: | ||
224 | case RTC_AIE_ON: | ||
225 | break; | ||
226 | default: | ||
227 | return -ENOIOCTLCMD; | ||
228 | } | ||
229 | |||
230 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); | 221 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); |
231 | if (rc < 0) | 222 | if (rc < 0) |
232 | goto err; | 223 | goto err; |
233 | switch (cmd) { | 224 | |
234 | case RTC_AIE_OFF: | 225 | if (enabled) |
235 | rc &= ~M41T80_ALMON_AFE; | ||
236 | break; | ||
237 | case RTC_AIE_ON: | ||
238 | rc |= M41T80_ALMON_AFE; | 226 | rc |= M41T80_ALMON_AFE; |
239 | break; | 227 | else |
240 | } | 228 | rc &= ~M41T80_ALMON_AFE; |
229 | |||
241 | if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0) | 230 | if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0) |
242 | goto err; | 231 | goto err; |
232 | |||
243 | return 0; | 233 | return 0; |
244 | err: | 234 | err: |
245 | return -EIO; | 235 | return -EIO; |
246 | } | 236 | } |
247 | #else | ||
248 | #define m41t80_rtc_ioctl NULL | ||
249 | #endif | ||
250 | 237 | ||
251 | static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 238 | static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
252 | { | 239 | { |
@@ -373,7 +360,7 @@ static struct rtc_class_ops m41t80_rtc_ops = { | |||
373 | .read_alarm = m41t80_rtc_read_alarm, | 360 | .read_alarm = m41t80_rtc_read_alarm, |
374 | .set_alarm = m41t80_rtc_set_alarm, | 361 | .set_alarm = m41t80_rtc_set_alarm, |
375 | .proc = m41t80_rtc_proc, | 362 | .proc = m41t80_rtc_proc, |
376 | .ioctl = m41t80_rtc_ioctl, | 363 | .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, |
377 | }; | 364 | }; |
378 | 365 | ||
379 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) | 366 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) |
@@ -677,9 +664,9 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
677 | { | 664 | { |
678 | int ret; | 665 | int ret; |
679 | 666 | ||
680 | lock_kernel(); | 667 | mutex_lock(&m41t80_rtc_mutex); |
681 | ret = wdt_ioctl(file, cmd, arg); | 668 | ret = wdt_ioctl(file, cmd, arg); |
682 | unlock_kernel(); | 669 | mutex_unlock(&m41t80_rtc_mutex); |
683 | 670 | ||
684 | return ret; | 671 | return ret; |
685 | } | 672 | } |
@@ -693,16 +680,16 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
693 | static int wdt_open(struct inode *inode, struct file *file) | 680 | static int wdt_open(struct inode *inode, struct file *file) |
694 | { | 681 | { |
695 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { | 682 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { |
696 | lock_kernel(); | 683 | mutex_lock(&m41t80_rtc_mutex); |
697 | if (test_and_set_bit(0, &wdt_is_open)) { | 684 | if (test_and_set_bit(0, &wdt_is_open)) { |
698 | unlock_kernel(); | 685 | mutex_unlock(&m41t80_rtc_mutex); |
699 | return -EBUSY; | 686 | return -EBUSY; |
700 | } | 687 | } |
701 | /* | 688 | /* |
702 | * Activate | 689 | * Activate |
703 | */ | 690 | */ |
704 | wdt_is_open = 1; | 691 | wdt_is_open = 1; |
705 | unlock_kernel(); | 692 | mutex_unlock(&m41t80_rtc_mutex); |
706 | return nonseekable_open(inode, file); | 693 | return nonseekable_open(inode, file); |
707 | } | 694 | } |
708 | return -ENODEV; | 695 | return -ENODEV; |
@@ -748,6 +735,7 @@ static const struct file_operations wdt_fops = { | |||
748 | .write = wdt_write, | 735 | .write = wdt_write, |
749 | .open = wdt_open, | 736 | .open = wdt_open, |
750 | .release = wdt_release, | 737 | .release = wdt_release, |
738 | .llseek = no_llseek, | ||
751 | }; | 739 | }; |
752 | 740 | ||
753 | static struct miscdevice wdt_dev = { | 741 | static struct miscdevice wdt_dev = { |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index a99a0b554eb8..3978f4caf724 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -263,30 +263,21 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
263 | /* | 263 | /* |
264 | * Handle commands from user-space | 264 | * Handle commands from user-space |
265 | */ | 265 | */ |
266 | static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd, | 266 | static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
267 | unsigned long arg) | ||
268 | { | 267 | { |
269 | struct platform_device *pdev = to_platform_device(dev); | 268 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; | 269 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
271 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); | 270 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); |
272 | unsigned long flags; | 271 | unsigned long flags; |
273 | int ret = 0; | ||
274 | 272 | ||
275 | spin_lock_irqsave(&m48t59->lock, flags); | 273 | spin_lock_irqsave(&m48t59->lock, flags); |
276 | switch (cmd) { | 274 | if (enabled) |
277 | case RTC_AIE_OFF: /* alarm interrupt off */ | ||
278 | M48T59_WRITE(0x00, M48T59_INTR); | ||
279 | break; | ||
280 | case RTC_AIE_ON: /* alarm interrupt on */ | ||
281 | M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); | 275 | M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); |
282 | break; | 276 | else |
283 | default: | 277 | M48T59_WRITE(0x00, M48T59_INTR); |
284 | ret = -ENOIOCTLCMD; | ||
285 | break; | ||
286 | } | ||
287 | spin_unlock_irqrestore(&m48t59->lock, flags); | 278 | spin_unlock_irqrestore(&m48t59->lock, flags); |
288 | 279 | ||
289 | return ret; | 280 | return 0; |
290 | } | 281 | } |
291 | 282 | ||
292 | static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) | 283 | static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) |
@@ -330,12 +321,12 @@ static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id) | |||
330 | } | 321 | } |
331 | 322 | ||
332 | static const struct rtc_class_ops m48t59_rtc_ops = { | 323 | static const struct rtc_class_ops m48t59_rtc_ops = { |
333 | .ioctl = m48t59_rtc_ioctl, | ||
334 | .read_time = m48t59_rtc_read_time, | 324 | .read_time = m48t59_rtc_read_time, |
335 | .set_time = m48t59_rtc_set_time, | 325 | .set_time = m48t59_rtc_set_time, |
336 | .read_alarm = m48t59_rtc_readalarm, | 326 | .read_alarm = m48t59_rtc_readalarm, |
337 | .set_alarm = m48t59_rtc_setalarm, | 327 | .set_alarm = m48t59_rtc_setalarm, |
338 | .proc = m48t59_rtc_proc, | 328 | .proc = m48t59_rtc_proc, |
329 | .alarm_irq_enable = m48t59_rtc_alarm_irq_enable, | ||
339 | }; | 330 | }; |
340 | 331 | ||
341 | static const struct rtc_class_ops m48t02_rtc_ops = { | 332 | static const struct rtc_class_ops m48t02_rtc_ops = { |
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 657403ebd54a..0ec3f588a255 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c | |||
@@ -139,12 +139,13 @@ static int __devinit max6902_probe(struct spi_device *spi) | |||
139 | if (IS_ERR(rtc)) | 139 | if (IS_ERR(rtc)) |
140 | return PTR_ERR(rtc); | 140 | return PTR_ERR(rtc); |
141 | 141 | ||
142 | dev_set_drvdata(&spi->dev, rtc); | ||
142 | return 0; | 143 | return 0; |
143 | } | 144 | } |
144 | 145 | ||
145 | static int __devexit max6902_remove(struct spi_device *spi) | 146 | static int __devexit max6902_remove(struct spi_device *spi) |
146 | { | 147 | { |
147 | struct rtc_device *rtc = platform_get_drvdata(spi); | 148 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); |
148 | 149 | ||
149 | rtc_device_unregister(rtc); | 150 | rtc_device_unregister(rtc); |
150 | return 0; | 151 | return 0; |
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c new file mode 100644 index 000000000000..3f7bc6b9fefa --- /dev/null +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -0,0 +1,344 @@ | |||
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 | #include <linux/delay.h> | ||
24 | |||
25 | #define MAX8998_RTC_SEC 0x00 | ||
26 | #define MAX8998_RTC_MIN 0x01 | ||
27 | #define MAX8998_RTC_HOUR 0x02 | ||
28 | #define MAX8998_RTC_WEEKDAY 0x03 | ||
29 | #define MAX8998_RTC_DATE 0x04 | ||
30 | #define MAX8998_RTC_MONTH 0x05 | ||
31 | #define MAX8998_RTC_YEAR1 0x06 | ||
32 | #define MAX8998_RTC_YEAR2 0x07 | ||
33 | #define MAX8998_ALARM0_SEC 0x08 | ||
34 | #define MAX8998_ALARM0_MIN 0x09 | ||
35 | #define MAX8998_ALARM0_HOUR 0x0a | ||
36 | #define MAX8998_ALARM0_WEEKDAY 0x0b | ||
37 | #define MAX8998_ALARM0_DATE 0x0c | ||
38 | #define MAX8998_ALARM0_MONTH 0x0d | ||
39 | #define MAX8998_ALARM0_YEAR1 0x0e | ||
40 | #define MAX8998_ALARM0_YEAR2 0x0f | ||
41 | #define MAX8998_ALARM1_SEC 0x10 | ||
42 | #define MAX8998_ALARM1_MIN 0x11 | ||
43 | #define MAX8998_ALARM1_HOUR 0x12 | ||
44 | #define MAX8998_ALARM1_WEEKDAY 0x13 | ||
45 | #define MAX8998_ALARM1_DATE 0x14 | ||
46 | #define MAX8998_ALARM1_MONTH 0x15 | ||
47 | #define MAX8998_ALARM1_YEAR1 0x16 | ||
48 | #define MAX8998_ALARM1_YEAR2 0x17 | ||
49 | #define MAX8998_ALARM0_CONF 0x18 | ||
50 | #define MAX8998_ALARM1_CONF 0x19 | ||
51 | #define MAX8998_RTC_STATUS 0x1a | ||
52 | #define MAX8998_WTSR_SMPL_CNTL 0x1b | ||
53 | #define MAX8998_TEST 0x1f | ||
54 | |||
55 | #define HOUR_12 (1 << 7) | ||
56 | #define HOUR_PM (1 << 5) | ||
57 | #define ALARM0_STATUS (1 << 1) | ||
58 | #define ALARM1_STATUS (1 << 2) | ||
59 | |||
60 | enum { | ||
61 | RTC_SEC = 0, | ||
62 | RTC_MIN, | ||
63 | RTC_HOUR, | ||
64 | RTC_WEEKDAY, | ||
65 | RTC_DATE, | ||
66 | RTC_MONTH, | ||
67 | RTC_YEAR1, | ||
68 | RTC_YEAR2, | ||
69 | }; | ||
70 | |||
71 | struct max8998_rtc_info { | ||
72 | struct device *dev; | ||
73 | struct max8998_dev *max8998; | ||
74 | struct i2c_client *rtc; | ||
75 | struct rtc_device *rtc_dev; | ||
76 | int irq; | ||
77 | bool lp3974_bug_workaround; | ||
78 | }; | ||
79 | |||
80 | static void max8998_data_to_tm(u8 *data, struct rtc_time *tm) | ||
81 | { | ||
82 | tm->tm_sec = bcd2bin(data[RTC_SEC]); | ||
83 | tm->tm_min = bcd2bin(data[RTC_MIN]); | ||
84 | if (data[RTC_HOUR] & HOUR_12) { | ||
85 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); | ||
86 | if (data[RTC_HOUR] & HOUR_PM) | ||
87 | tm->tm_hour += 12; | ||
88 | } else | ||
89 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); | ||
90 | |||
91 | tm->tm_wday = data[RTC_WEEKDAY] & 0x07; | ||
92 | tm->tm_mday = bcd2bin(data[RTC_DATE]); | ||
93 | tm->tm_mon = bcd2bin(data[RTC_MONTH]); | ||
94 | tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; | ||
95 | tm->tm_year -= 1900; | ||
96 | } | ||
97 | |||
98 | static void max8998_tm_to_data(struct rtc_time *tm, u8 *data) | ||
99 | { | ||
100 | data[RTC_SEC] = bin2bcd(tm->tm_sec); | ||
101 | data[RTC_MIN] = bin2bcd(tm->tm_min); | ||
102 | data[RTC_HOUR] = bin2bcd(tm->tm_hour); | ||
103 | data[RTC_WEEKDAY] = tm->tm_wday; | ||
104 | data[RTC_DATE] = bin2bcd(tm->tm_mday); | ||
105 | data[RTC_MONTH] = bin2bcd(tm->tm_mon); | ||
106 | data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); | ||
107 | data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); | ||
108 | } | ||
109 | |||
110 | static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
111 | { | ||
112 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
113 | u8 data[8]; | ||
114 | int ret; | ||
115 | |||
116 | ret = max8998_bulk_read(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | max8998_data_to_tm(data, tm); | ||
121 | |||
122 | return rtc_valid_tm(tm); | ||
123 | } | ||
124 | |||
125 | static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
126 | { | ||
127 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
128 | u8 data[8]; | ||
129 | int ret; | ||
130 | |||
131 | max8998_tm_to_data(tm, data); | ||
132 | |||
133 | ret = max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
134 | |||
135 | if (info->lp3974_bug_workaround) | ||
136 | msleep(2000); | ||
137 | |||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
142 | { | ||
143 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
144 | u8 data[8]; | ||
145 | u8 val; | ||
146 | int ret; | ||
147 | |||
148 | ret = max8998_bulk_read(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
149 | if (ret < 0) | ||
150 | return ret; | ||
151 | |||
152 | max8998_data_to_tm(data, &alrm->time); | ||
153 | |||
154 | ret = max8998_read_reg(info->rtc, MAX8998_ALARM0_CONF, &val); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | |||
158 | alrm->enabled = !!val; | ||
159 | |||
160 | ret = max8998_read_reg(info->rtc, MAX8998_RTC_STATUS, &val); | ||
161 | if (ret < 0) | ||
162 | return ret; | ||
163 | |||
164 | if (val & ALARM0_STATUS) | ||
165 | alrm->pending = 1; | ||
166 | else | ||
167 | alrm->pending = 0; | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info) | ||
173 | { | ||
174 | int ret = max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0); | ||
175 | |||
176 | if (info->lp3974_bug_workaround) | ||
177 | msleep(2000); | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static int max8998_rtc_start_alarm(struct max8998_rtc_info *info) | ||
183 | { | ||
184 | int ret; | ||
185 | u8 alarm0_conf = 0x77; | ||
186 | |||
187 | /* LP3974 with delay bug chips has rtc alarm bugs with "MONTH" field */ | ||
188 | if (info->lp3974_bug_workaround) | ||
189 | alarm0_conf = 0x57; | ||
190 | |||
191 | ret = max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, alarm0_conf); | ||
192 | |||
193 | if (info->lp3974_bug_workaround) | ||
194 | msleep(2000); | ||
195 | |||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
200 | { | ||
201 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
202 | u8 data[8]; | ||
203 | int ret; | ||
204 | |||
205 | max8998_tm_to_data(&alrm->time, data); | ||
206 | |||
207 | ret = max8998_rtc_stop_alarm(info); | ||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | |||
211 | ret = max8998_bulk_write(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
212 | if (ret < 0) | ||
213 | return ret; | ||
214 | |||
215 | if (info->lp3974_bug_workaround) | ||
216 | msleep(2000); | ||
217 | |||
218 | if (alrm->enabled) | ||
219 | ret = max8998_rtc_start_alarm(info); | ||
220 | |||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | static int max8998_rtc_alarm_irq_enable(struct device *dev, | ||
225 | unsigned int enabled) | ||
226 | { | ||
227 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
228 | |||
229 | if (enabled) | ||
230 | return max8998_rtc_start_alarm(info); | ||
231 | else | ||
232 | return max8998_rtc_stop_alarm(info); | ||
233 | } | ||
234 | |||
235 | static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data) | ||
236 | { | ||
237 | struct max8998_rtc_info *info = data; | ||
238 | |||
239 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
240 | |||
241 | return IRQ_HANDLED; | ||
242 | } | ||
243 | |||
244 | static const struct rtc_class_ops max8998_rtc_ops = { | ||
245 | .read_time = max8998_rtc_read_time, | ||
246 | .set_time = max8998_rtc_set_time, | ||
247 | .read_alarm = max8998_rtc_read_alarm, | ||
248 | .set_alarm = max8998_rtc_set_alarm, | ||
249 | .alarm_irq_enable = max8998_rtc_alarm_irq_enable, | ||
250 | }; | ||
251 | |||
252 | static int __devinit max8998_rtc_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); | ||
255 | struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev); | ||
256 | struct max8998_rtc_info *info; | ||
257 | int ret; | ||
258 | |||
259 | info = kzalloc(sizeof(struct max8998_rtc_info), GFP_KERNEL); | ||
260 | if (!info) | ||
261 | return -ENOMEM; | ||
262 | |||
263 | info->dev = &pdev->dev; | ||
264 | info->max8998 = max8998; | ||
265 | info->rtc = max8998->rtc; | ||
266 | info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; | ||
267 | |||
268 | info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev, | ||
269 | &max8998_rtc_ops, THIS_MODULE); | ||
270 | |||
271 | if (IS_ERR(info->rtc_dev)) { | ||
272 | ret = PTR_ERR(info->rtc_dev); | ||
273 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
274 | goto out_rtc; | ||
275 | } | ||
276 | |||
277 | platform_set_drvdata(pdev, info); | ||
278 | |||
279 | ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0, | ||
280 | "rtc-alarm0", info); | ||
281 | |||
282 | if (ret < 0) | ||
283 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
284 | info->irq, ret); | ||
285 | |||
286 | dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); | ||
287 | if (pdata->rtc_delay) { | ||
288 | info->lp3974_bug_workaround = true; | ||
289 | dev_warn(&pdev->dev, "LP3974 with RTC REGERR option." | ||
290 | " RTC updates will be extremely slow.\n"); | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | out_rtc: | ||
296 | kfree(info); | ||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int __devexit max8998_rtc_remove(struct platform_device *pdev) | ||
301 | { | ||
302 | struct max8998_rtc_info *info = platform_get_drvdata(pdev); | ||
303 | |||
304 | if (info) { | ||
305 | free_irq(info->irq, info); | ||
306 | rtc_device_unregister(info->rtc_dev); | ||
307 | kfree(info); | ||
308 | } | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static const struct platform_device_id max8998_rtc_id[] = { | ||
314 | { "max8998-rtc", TYPE_MAX8998 }, | ||
315 | { "lp3974-rtc", TYPE_LP3974 }, | ||
316 | { } | ||
317 | }; | ||
318 | |||
319 | static struct platform_driver max8998_rtc_driver = { | ||
320 | .driver = { | ||
321 | .name = "max8998-rtc", | ||
322 | .owner = THIS_MODULE, | ||
323 | }, | ||
324 | .probe = max8998_rtc_probe, | ||
325 | .remove = __devexit_p(max8998_rtc_remove), | ||
326 | .id_table = max8998_rtc_id, | ||
327 | }; | ||
328 | |||
329 | static int __init max8998_rtc_init(void) | ||
330 | { | ||
331 | return platform_driver_register(&max8998_rtc_driver); | ||
332 | } | ||
333 | module_init(max8998_rtc_init); | ||
334 | |||
335 | static void __exit max8998_rtc_exit(void) | ||
336 | { | ||
337 | platform_driver_unregister(&max8998_rtc_driver); | ||
338 | } | ||
339 | module_exit(max8998_rtc_exit); | ||
340 | |||
341 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
342 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
343 | MODULE_DESCRIPTION("Maxim MAX8998 RTC driver"); | ||
344 | 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-mrst.c b/drivers/rtc/rtc-mrst.c new file mode 100644 index 000000000000..1db62db8469d --- /dev/null +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -0,0 +1,561 @@ | |||
1 | /* | ||
2 | * rtc-mrst.c: Driver for Moorestown virtual RTC | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * Author: Jacob Pan (jacob.jun.pan@intel.com) | ||
6 | * Feng Tang (feng.tang@intel.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | * | ||
13 | * Note: | ||
14 | * VRTC is emulated by system controller firmware, the real HW | ||
15 | * RTC is located in the PMIC device. SCU FW shadows PMIC RTC | ||
16 | * in a memory mapped IO space that is visible to the host IA | ||
17 | * processor. | ||
18 | * | ||
19 | * This driver is based upon drivers/rtc/rtc-cmos.c | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * Note: | ||
24 | * * vRTC only supports binary mode and 24H mode | ||
25 | * * vRTC only support PIE and AIE, no UIE, and its PIE only happens | ||
26 | * at 23:59:59pm everyday, no support for adjustable frequency | ||
27 | * * Alarm function is also limited to hr/min/sec. | ||
28 | */ | ||
29 | |||
30 | #include <linux/mod_devicetable.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/sfi.h> | ||
38 | |||
39 | #include <asm-generic/rtc.h> | ||
40 | #include <asm/intel_scu_ipc.h> | ||
41 | #include <asm/mrst.h> | ||
42 | #include <asm/mrst-vrtc.h> | ||
43 | |||
44 | struct mrst_rtc { | ||
45 | struct rtc_device *rtc; | ||
46 | struct device *dev; | ||
47 | int irq; | ||
48 | struct resource *iomem; | ||
49 | |||
50 | u8 enabled_wake; | ||
51 | u8 suspend_ctrl; | ||
52 | }; | ||
53 | |||
54 | static const char driver_name[] = "rtc_mrst"; | ||
55 | |||
56 | #define RTC_IRQMASK (RTC_PF | RTC_AF) | ||
57 | |||
58 | static inline int is_intr(u8 rtc_intr) | ||
59 | { | ||
60 | if (!(rtc_intr & RTC_IRQF)) | ||
61 | return 0; | ||
62 | return rtc_intr & RTC_IRQMASK; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * rtc_time's year contains the increment over 1900, but vRTC's YEAR | ||
67 | * register can't be programmed to value larger than 0x64, so vRTC | ||
68 | * driver chose to use 1960 (1970 is UNIX time start point) as the base, | ||
69 | * and does the translation at read/write time. | ||
70 | * | ||
71 | * Why not just use 1970 as the offset? it's because using 1960 will | ||
72 | * make it consistent in leap year setting for both vrtc and low-level | ||
73 | * physical rtc devices. | ||
74 | */ | ||
75 | static int mrst_read_time(struct device *dev, struct rtc_time *time) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | |||
79 | if (rtc_is_updating()) | ||
80 | mdelay(20); | ||
81 | |||
82 | spin_lock_irqsave(&rtc_lock, flags); | ||
83 | time->tm_sec = vrtc_cmos_read(RTC_SECONDS); | ||
84 | time->tm_min = vrtc_cmos_read(RTC_MINUTES); | ||
85 | time->tm_hour = vrtc_cmos_read(RTC_HOURS); | ||
86 | time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); | ||
87 | time->tm_mon = vrtc_cmos_read(RTC_MONTH); | ||
88 | time->tm_year = vrtc_cmos_read(RTC_YEAR); | ||
89 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
90 | |||
91 | /* Adjust for the 1960/1900 */ | ||
92 | time->tm_year += 60; | ||
93 | time->tm_mon--; | ||
94 | return RTC_24H; | ||
95 | } | ||
96 | |||
97 | static int mrst_set_time(struct device *dev, struct rtc_time *time) | ||
98 | { | ||
99 | int ret; | ||
100 | unsigned long flags; | ||
101 | unsigned char mon, day, hrs, min, sec; | ||
102 | unsigned int yrs; | ||
103 | |||
104 | yrs = time->tm_year; | ||
105 | mon = time->tm_mon + 1; /* tm_mon starts at zero */ | ||
106 | day = time->tm_mday; | ||
107 | hrs = time->tm_hour; | ||
108 | min = time->tm_min; | ||
109 | sec = time->tm_sec; | ||
110 | |||
111 | if (yrs < 70 || yrs > 138) | ||
112 | return -EINVAL; | ||
113 | yrs -= 60; | ||
114 | |||
115 | spin_lock_irqsave(&rtc_lock, flags); | ||
116 | |||
117 | vrtc_cmos_write(yrs, RTC_YEAR); | ||
118 | vrtc_cmos_write(mon, RTC_MONTH); | ||
119 | vrtc_cmos_write(day, RTC_DAY_OF_MONTH); | ||
120 | vrtc_cmos_write(hrs, RTC_HOURS); | ||
121 | vrtc_cmos_write(min, RTC_MINUTES); | ||
122 | vrtc_cmos_write(sec, RTC_SECONDS); | ||
123 | |||
124 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
125 | |||
126 | ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
131 | { | ||
132 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
133 | unsigned char rtc_control; | ||
134 | |||
135 | if (mrst->irq <= 0) | ||
136 | return -EIO; | ||
137 | |||
138 | /* Basic alarms only support hour, minute, and seconds fields. | ||
139 | * Some also support day and month, for alarms up to a year in | ||
140 | * the future. | ||
141 | */ | ||
142 | t->time.tm_mday = -1; | ||
143 | t->time.tm_mon = -1; | ||
144 | t->time.tm_year = -1; | ||
145 | |||
146 | /* vRTC only supports binary mode */ | ||
147 | spin_lock_irq(&rtc_lock); | ||
148 | t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); | ||
149 | t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM); | ||
150 | t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM); | ||
151 | |||
152 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
153 | spin_unlock_irq(&rtc_lock); | ||
154 | |||
155 | t->enabled = !!(rtc_control & RTC_AIE); | ||
156 | t->pending = 0; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control) | ||
162 | { | ||
163 | unsigned char rtc_intr; | ||
164 | |||
165 | /* | ||
166 | * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
167 | * allegedly some older rtcs need that to handle irqs properly | ||
168 | */ | ||
169 | rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
170 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
171 | if (is_intr(rtc_intr)) | ||
172 | rtc_update_irq(mrst->rtc, 1, rtc_intr); | ||
173 | } | ||
174 | |||
175 | static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) | ||
176 | { | ||
177 | unsigned char rtc_control; | ||
178 | |||
179 | /* | ||
180 | * Flush any pending IRQ status, notably for update irqs, | ||
181 | * before we enable new IRQs | ||
182 | */ | ||
183 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
184 | mrst_checkintr(mrst, rtc_control); | ||
185 | |||
186 | rtc_control |= mask; | ||
187 | vrtc_cmos_write(rtc_control, RTC_CONTROL); | ||
188 | |||
189 | mrst_checkintr(mrst, rtc_control); | ||
190 | } | ||
191 | |||
192 | static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) | ||
193 | { | ||
194 | unsigned char rtc_control; | ||
195 | |||
196 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
197 | rtc_control &= ~mask; | ||
198 | vrtc_cmos_write(rtc_control, RTC_CONTROL); | ||
199 | mrst_checkintr(mrst, rtc_control); | ||
200 | } | ||
201 | |||
202 | static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
203 | { | ||
204 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
205 | unsigned char hrs, min, sec; | ||
206 | int ret = 0; | ||
207 | |||
208 | if (!mrst->irq) | ||
209 | return -EIO; | ||
210 | |||
211 | hrs = t->time.tm_hour; | ||
212 | min = t->time.tm_min; | ||
213 | sec = t->time.tm_sec; | ||
214 | |||
215 | spin_lock_irq(&rtc_lock); | ||
216 | /* Next rtc irq must not be from previous alarm setting */ | ||
217 | mrst_irq_disable(mrst, RTC_AIE); | ||
218 | |||
219 | /* Update alarm */ | ||
220 | vrtc_cmos_write(hrs, RTC_HOURS_ALARM); | ||
221 | vrtc_cmos_write(min, RTC_MINUTES_ALARM); | ||
222 | vrtc_cmos_write(sec, RTC_SECONDS_ALARM); | ||
223 | |||
224 | spin_unlock_irq(&rtc_lock); | ||
225 | |||
226 | ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); | ||
227 | if (ret) | ||
228 | return ret; | ||
229 | |||
230 | spin_lock_irq(&rtc_lock); | ||
231 | if (t->enabled) | ||
232 | mrst_irq_enable(mrst, RTC_AIE); | ||
233 | |||
234 | spin_unlock_irq(&rtc_lock); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int mrst_irq_set_state(struct device *dev, int enabled) | ||
240 | { | ||
241 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
242 | unsigned long flags; | ||
243 | |||
244 | if (!mrst->irq) | ||
245 | return -ENXIO; | ||
246 | |||
247 | spin_lock_irqsave(&rtc_lock, flags); | ||
248 | |||
249 | if (enabled) | ||
250 | mrst_irq_enable(mrst, RTC_PIE); | ||
251 | else | ||
252 | mrst_irq_disable(mrst, RTC_PIE); | ||
253 | |||
254 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | /* Currently, the vRTC doesn't support UIE ON/OFF */ | ||
259 | static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
260 | { | ||
261 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
262 | unsigned long flags; | ||
263 | |||
264 | spin_lock_irqsave(&rtc_lock, flags); | ||
265 | if (enabled) | ||
266 | mrst_irq_enable(mrst, RTC_AIE); | ||
267 | else | ||
268 | mrst_irq_disable(mrst, RTC_AIE); | ||
269 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | |||
274 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | ||
275 | |||
276 | static int mrst_procfs(struct device *dev, struct seq_file *seq) | ||
277 | { | ||
278 | unsigned char rtc_control, valid; | ||
279 | |||
280 | spin_lock_irq(&rtc_lock); | ||
281 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
282 | valid = vrtc_cmos_read(RTC_VALID); | ||
283 | spin_unlock_irq(&rtc_lock); | ||
284 | |||
285 | return seq_printf(seq, | ||
286 | "periodic_IRQ\t: %s\n" | ||
287 | "alarm\t\t: %s\n" | ||
288 | "BCD\t\t: no\n" | ||
289 | "periodic_freq\t: daily (not adjustable)\n", | ||
290 | (rtc_control & RTC_PIE) ? "on" : "off", | ||
291 | (rtc_control & RTC_AIE) ? "on" : "off"); | ||
292 | } | ||
293 | |||
294 | #else | ||
295 | #define mrst_procfs NULL | ||
296 | #endif | ||
297 | |||
298 | static const struct rtc_class_ops mrst_rtc_ops = { | ||
299 | .read_time = mrst_read_time, | ||
300 | .set_time = mrst_set_time, | ||
301 | .read_alarm = mrst_read_alarm, | ||
302 | .set_alarm = mrst_set_alarm, | ||
303 | .proc = mrst_procfs, | ||
304 | .irq_set_state = mrst_irq_set_state, | ||
305 | .alarm_irq_enable = mrst_rtc_alarm_irq_enable, | ||
306 | }; | ||
307 | |||
308 | static struct mrst_rtc mrst_rtc; | ||
309 | |||
310 | /* | ||
311 | * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in | ||
312 | * Reg B, so no need for this driver to clear it | ||
313 | */ | ||
314 | static irqreturn_t mrst_rtc_irq(int irq, void *p) | ||
315 | { | ||
316 | u8 irqstat; | ||
317 | |||
318 | spin_lock(&rtc_lock); | ||
319 | /* This read will clear all IRQ flags inside Reg C */ | ||
320 | irqstat = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
321 | spin_unlock(&rtc_lock); | ||
322 | |||
323 | irqstat &= RTC_IRQMASK | RTC_IRQF; | ||
324 | if (is_intr(irqstat)) { | ||
325 | rtc_update_irq(p, 1, irqstat); | ||
326 | return IRQ_HANDLED; | ||
327 | } | ||
328 | return IRQ_NONE; | ||
329 | } | ||
330 | |||
331 | static int __init | ||
332 | vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | ||
333 | { | ||
334 | int retval = 0; | ||
335 | unsigned char rtc_control; | ||
336 | |||
337 | /* There can be only one ... */ | ||
338 | if (mrst_rtc.dev) | ||
339 | return -EBUSY; | ||
340 | |||
341 | if (!iomem) | ||
342 | return -ENODEV; | ||
343 | |||
344 | iomem = request_mem_region(iomem->start, | ||
345 | iomem->end + 1 - iomem->start, | ||
346 | driver_name); | ||
347 | if (!iomem) { | ||
348 | dev_dbg(dev, "i/o mem already in use.\n"); | ||
349 | return -EBUSY; | ||
350 | } | ||
351 | |||
352 | mrst_rtc.irq = rtc_irq; | ||
353 | mrst_rtc.iomem = iomem; | ||
354 | |||
355 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, | ||
356 | &mrst_rtc_ops, THIS_MODULE); | ||
357 | if (IS_ERR(mrst_rtc.rtc)) { | ||
358 | retval = PTR_ERR(mrst_rtc.rtc); | ||
359 | goto cleanup0; | ||
360 | } | ||
361 | |||
362 | mrst_rtc.dev = dev; | ||
363 | dev_set_drvdata(dev, &mrst_rtc); | ||
364 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); | ||
365 | |||
366 | spin_lock_irq(&rtc_lock); | ||
367 | mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); | ||
368 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
369 | spin_unlock_irq(&rtc_lock); | ||
370 | |||
371 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) | ||
372 | dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); | ||
373 | |||
374 | if (rtc_irq) { | ||
375 | retval = request_irq(rtc_irq, mrst_rtc_irq, | ||
376 | IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), | ||
377 | mrst_rtc.rtc); | ||
378 | if (retval < 0) { | ||
379 | dev_dbg(dev, "IRQ %d is already in use, err %d\n", | ||
380 | rtc_irq, retval); | ||
381 | goto cleanup1; | ||
382 | } | ||
383 | } | ||
384 | dev_dbg(dev, "initialised\n"); | ||
385 | return 0; | ||
386 | |||
387 | cleanup1: | ||
388 | mrst_rtc.dev = NULL; | ||
389 | rtc_device_unregister(mrst_rtc.rtc); | ||
390 | cleanup0: | ||
391 | release_region(iomem->start, iomem->end + 1 - iomem->start); | ||
392 | dev_err(dev, "rtc-mrst: unable to initialise\n"); | ||
393 | return retval; | ||
394 | } | ||
395 | |||
396 | static void rtc_mrst_do_shutdown(void) | ||
397 | { | ||
398 | spin_lock_irq(&rtc_lock); | ||
399 | mrst_irq_disable(&mrst_rtc, RTC_IRQMASK); | ||
400 | spin_unlock_irq(&rtc_lock); | ||
401 | } | ||
402 | |||
403 | static void __exit rtc_mrst_do_remove(struct device *dev) | ||
404 | { | ||
405 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
406 | struct resource *iomem; | ||
407 | |||
408 | rtc_mrst_do_shutdown(); | ||
409 | |||
410 | if (mrst->irq) | ||
411 | free_irq(mrst->irq, mrst->rtc); | ||
412 | |||
413 | rtc_device_unregister(mrst->rtc); | ||
414 | mrst->rtc = NULL; | ||
415 | |||
416 | iomem = mrst->iomem; | ||
417 | release_region(iomem->start, iomem->end + 1 - iomem->start); | ||
418 | mrst->iomem = NULL; | ||
419 | |||
420 | mrst->dev = NULL; | ||
421 | dev_set_drvdata(dev, NULL); | ||
422 | } | ||
423 | |||
424 | #ifdef CONFIG_PM | ||
425 | static int mrst_suspend(struct device *dev, pm_message_t mesg) | ||
426 | { | ||
427 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
428 | unsigned char tmp; | ||
429 | |||
430 | /* Only the alarm might be a wakeup event source */ | ||
431 | spin_lock_irq(&rtc_lock); | ||
432 | mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); | ||
433 | if (tmp & (RTC_PIE | RTC_AIE)) { | ||
434 | unsigned char mask; | ||
435 | |||
436 | if (device_may_wakeup(dev)) | ||
437 | mask = RTC_IRQMASK & ~RTC_AIE; | ||
438 | else | ||
439 | mask = RTC_IRQMASK; | ||
440 | tmp &= ~mask; | ||
441 | vrtc_cmos_write(tmp, RTC_CONTROL); | ||
442 | |||
443 | mrst_checkintr(mrst, tmp); | ||
444 | } | ||
445 | spin_unlock_irq(&rtc_lock); | ||
446 | |||
447 | if (tmp & RTC_AIE) { | ||
448 | mrst->enabled_wake = 1; | ||
449 | enable_irq_wake(mrst->irq); | ||
450 | } | ||
451 | |||
452 | dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", | ||
453 | (tmp & RTC_AIE) ? ", alarm may wake" : "", | ||
454 | tmp); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * We want RTC alarms to wake us from the deep power saving state | ||
461 | */ | ||
462 | static inline int mrst_poweroff(struct device *dev) | ||
463 | { | ||
464 | return mrst_suspend(dev, PMSG_HIBERNATE); | ||
465 | } | ||
466 | |||
467 | static int mrst_resume(struct device *dev) | ||
468 | { | ||
469 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
470 | unsigned char tmp = mrst->suspend_ctrl; | ||
471 | |||
472 | /* Re-enable any irqs previously active */ | ||
473 | if (tmp & RTC_IRQMASK) { | ||
474 | unsigned char mask; | ||
475 | |||
476 | if (mrst->enabled_wake) { | ||
477 | disable_irq_wake(mrst->irq); | ||
478 | mrst->enabled_wake = 0; | ||
479 | } | ||
480 | |||
481 | spin_lock_irq(&rtc_lock); | ||
482 | do { | ||
483 | vrtc_cmos_write(tmp, RTC_CONTROL); | ||
484 | |||
485 | mask = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
486 | mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; | ||
487 | if (!is_intr(mask)) | ||
488 | break; | ||
489 | |||
490 | rtc_update_irq(mrst->rtc, 1, mask); | ||
491 | tmp &= ~RTC_AIE; | ||
492 | } while (mask & RTC_AIE); | ||
493 | spin_unlock_irq(&rtc_lock); | ||
494 | } | ||
495 | |||
496 | dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | #else | ||
502 | #define mrst_suspend NULL | ||
503 | #define mrst_resume NULL | ||
504 | |||
505 | static inline int mrst_poweroff(struct device *dev) | ||
506 | { | ||
507 | return -ENOSYS; | ||
508 | } | ||
509 | |||
510 | #endif | ||
511 | |||
512 | static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) | ||
513 | { | ||
514 | return vrtc_mrst_do_probe(&pdev->dev, | ||
515 | platform_get_resource(pdev, IORESOURCE_MEM, 0), | ||
516 | platform_get_irq(pdev, 0)); | ||
517 | } | ||
518 | |||
519 | static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) | ||
520 | { | ||
521 | rtc_mrst_do_remove(&pdev->dev); | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static void vrtc_mrst_platform_shutdown(struct platform_device *pdev) | ||
526 | { | ||
527 | if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev)) | ||
528 | return; | ||
529 | |||
530 | rtc_mrst_do_shutdown(); | ||
531 | } | ||
532 | |||
533 | MODULE_ALIAS("platform:vrtc_mrst"); | ||
534 | |||
535 | static struct platform_driver vrtc_mrst_platform_driver = { | ||
536 | .probe = vrtc_mrst_platform_probe, | ||
537 | .remove = __exit_p(vrtc_mrst_platform_remove), | ||
538 | .shutdown = vrtc_mrst_platform_shutdown, | ||
539 | .driver = { | ||
540 | .name = (char *) driver_name, | ||
541 | .suspend = mrst_suspend, | ||
542 | .resume = mrst_resume, | ||
543 | } | ||
544 | }; | ||
545 | |||
546 | static int __init vrtc_mrst_init(void) | ||
547 | { | ||
548 | return platform_driver_register(&vrtc_mrst_platform_driver); | ||
549 | } | ||
550 | |||
551 | static void __exit vrtc_mrst_exit(void) | ||
552 | { | ||
553 | platform_driver_unregister(&vrtc_mrst_platform_driver); | ||
554 | } | ||
555 | |||
556 | module_init(vrtc_mrst_init); | ||
557 | module_exit(vrtc_mrst_exit); | ||
558 | |||
559 | MODULE_AUTHOR("Jacob Pan; Feng Tang"); | ||
560 | MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); | ||
561 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index b2fff0ca49f8..67820626e18f 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c | |||
@@ -82,7 +82,7 @@ static inline unsigned int msm6242_read(struct msm6242_priv *priv, | |||
82 | static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, | 82 | static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, |
83 | unsigned int reg) | 83 | unsigned int reg) |
84 | { | 84 | { |
85 | return __raw_writel(val, &priv->regs[reg]); | 85 | __raw_writel(val, &priv->regs[reg]); |
86 | } | 86 | } |
87 | 87 | ||
88 | static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, | 88 | static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index bcca47298554..60627a764514 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -169,25 +169,19 @@ static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | static int mv_rtc_ioctl(struct device *dev, unsigned int cmd, | 172 | static int mv_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
173 | unsigned long arg) | ||
174 | { | 173 | { |
175 | struct platform_device *pdev = to_platform_device(dev); | 174 | struct platform_device *pdev = to_platform_device(dev); |
176 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 175 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
177 | void __iomem *ioaddr = pdata->ioaddr; | 176 | void __iomem *ioaddr = pdata->ioaddr; |
178 | 177 | ||
179 | if (pdata->irq < 0) | 178 | if (pdata->irq < 0) |
180 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 179 | return -EINVAL; /* fall back into rtc-dev's emulation */ |
181 | switch (cmd) { | 180 | |
182 | case RTC_AIE_OFF: | 181 | if (enabled) |
183 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
184 | break; | ||
185 | case RTC_AIE_ON: | ||
186 | writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | 182 | writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); |
187 | break; | 183 | else |
188 | default: | 184 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); |
189 | return -ENOIOCTLCMD; | ||
190 | } | ||
191 | return 0; | 185 | return 0; |
192 | } | 186 | } |
193 | 187 | ||
@@ -216,7 +210,7 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = { | |||
216 | .set_time = mv_rtc_set_time, | 210 | .set_time = mv_rtc_set_time, |
217 | .read_alarm = mv_rtc_read_alarm, | 211 | .read_alarm = mv_rtc_read_alarm, |
218 | .set_alarm = mv_rtc_set_alarm, | 212 | .set_alarm = mv_rtc_set_alarm, |
219 | .ioctl = mv_rtc_ioctl, | 213 | .alarm_irq_enable = mv_rtc_alarm_irq_enable, |
220 | }; | 214 | }; |
221 | 215 | ||
222 | static int __devinit mv_rtc_probe(struct platform_device *pdev) | 216 | static int __devinit mv_rtc_probe(struct platform_device *pdev) |
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index 62de66af0a68..ddb0857e15a4 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -274,7 +274,7 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | |||
274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | 274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, |
275 | &nuc900_rtc_ops, THIS_MODULE); | 275 | &nuc900_rtc_ops, THIS_MODULE); |
276 | if (IS_ERR(nuc900_rtc->rtcdev)) { | 276 | if (IS_ERR(nuc900_rtc->rtcdev)) { |
277 | dev_err(&pdev->dev, "rtc device register faild\n"); | 277 | dev_err(&pdev->dev, "rtc device register failed\n"); |
278 | err = PTR_ERR(nuc900_rtc->rtcdev); | 278 | err = PTR_ERR(nuc900_rtc->rtcdev); |
279 | goto fail3; | 279 | goto fail3; |
280 | } | 280 | } |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 64d9727b7229..b4dbf3a319b3 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 |
@@ -142,8 +143,6 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
142 | u8 reg; | 143 | u8 reg; |
143 | 144 | ||
144 | switch (cmd) { | 145 | switch (cmd) { |
145 | case RTC_AIE_OFF: | ||
146 | case RTC_AIE_ON: | ||
147 | case RTC_UIE_OFF: | 146 | case RTC_UIE_OFF: |
148 | case RTC_UIE_ON: | 147 | case RTC_UIE_ON: |
149 | break; | 148 | break; |
@@ -155,13 +154,6 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
155 | rtc_wait_not_busy(); | 154 | rtc_wait_not_busy(); |
156 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 155 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
157 | switch (cmd) { | 156 | switch (cmd) { |
158 | /* AIE = Alarm Interrupt Enable */ | ||
159 | case RTC_AIE_OFF: | ||
160 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | ||
161 | break; | ||
162 | case RTC_AIE_ON: | ||
163 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | ||
164 | break; | ||
165 | /* UIE = Update Interrupt Enable (1/second) */ | 157 | /* UIE = Update Interrupt Enable (1/second) */ |
166 | case RTC_UIE_OFF: | 158 | case RTC_UIE_OFF: |
167 | reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER; | 159 | reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER; |
@@ -181,6 +173,24 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
181 | #define omap_rtc_ioctl NULL | 173 | #define omap_rtc_ioctl NULL |
182 | #endif | 174 | #endif |
183 | 175 | ||
176 | static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
177 | { | ||
178 | u8 reg; | ||
179 | |||
180 | local_irq_disable(); | ||
181 | rtc_wait_not_busy(); | ||
182 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | ||
183 | if (enabled) | ||
184 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | ||
185 | else | ||
186 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | ||
187 | rtc_wait_not_busy(); | ||
188 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); | ||
189 | local_irq_enable(); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
184 | /* this hardware doesn't support "don't care" alarm fields */ | 194 | /* this hardware doesn't support "don't care" alarm fields */ |
185 | static int tm2bcd(struct rtc_time *tm) | 195 | static int tm2bcd(struct rtc_time *tm) |
186 | { | 196 | { |
@@ -308,6 +318,7 @@ static struct rtc_class_ops omap_rtc_ops = { | |||
308 | .set_time = omap_rtc_set_time, | 318 | .set_time = omap_rtc_set_time, |
309 | .read_alarm = omap_rtc_read_alarm, | 319 | .read_alarm = omap_rtc_read_alarm, |
310 | .set_alarm = omap_rtc_set_alarm, | 320 | .set_alarm = omap_rtc_set_alarm, |
321 | .alarm_irq_enable = omap_rtc_alarm_irq_enable, | ||
311 | }; | 322 | }; |
312 | 323 | ||
313 | static int omap_rtc_alarm; | 324 | static int omap_rtc_alarm; |
@@ -401,16 +412,17 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
401 | 412 | ||
402 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 413 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
403 | * | 414 | * |
404 | * - Boards wired so that RTC_WAKE_INT does something, and muxed | 415 | * - Device wake-up capability setting should come through chip |
405 | * right (W13_1610_RTC_WAKE_INT is the default after chip reset), | 416 | * init logic. OMAP1 boards should initialize the "wakeup capable" |
406 | * should initialize the device wakeup flag appropriately. | 417 | * flag in the platform device if the board is wired right for |
418 | * being woken up by RTC alarm. For OMAP-L138, this capability | ||
419 | * is built into the SoC by the "Deep Sleep" capability. | ||
407 | * | 420 | * |
408 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, | 421 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, |
409 | * rather than nPWRON_RESET, should forcibly enable split | 422 | * rather than nPWRON_RESET, should forcibly enable split |
410 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT | 423 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT |
411 | * is write-only, and always reads as zero...) | 424 | * is write-only, and always reads as zero...) |
412 | */ | 425 | */ |
413 | device_init_wakeup(&pdev->dev, 0); | ||
414 | 426 | ||
415 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) | 427 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) |
416 | pr_info("%s: split power mode\n", pdev->name); | 428 | pr_info("%s: split power mode\n", pdev->name); |
@@ -427,13 +439,14 @@ fail1: | |||
427 | fail0: | 439 | fail0: |
428 | iounmap(rtc_base); | 440 | iounmap(rtc_base); |
429 | fail: | 441 | fail: |
430 | release_resource(mem); | 442 | release_mem_region(mem->start, resource_size(mem)); |
431 | return -EIO; | 443 | return -EIO; |
432 | } | 444 | } |
433 | 445 | ||
434 | static int __exit omap_rtc_remove(struct platform_device *pdev) | 446 | static int __exit omap_rtc_remove(struct platform_device *pdev) |
435 | { | 447 | { |
436 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 448 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
449 | struct resource *mem = dev_get_drvdata(&rtc->dev); | ||
437 | 450 | ||
438 | device_init_wakeup(&pdev->dev, 0); | 451 | device_init_wakeup(&pdev->dev, 0); |
439 | 452 | ||
@@ -445,8 +458,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
445 | if (omap_rtc_timer != omap_rtc_alarm) | 458 | if (omap_rtc_timer != omap_rtc_alarm) |
446 | free_irq(omap_rtc_alarm, rtc); | 459 | free_irq(omap_rtc_alarm, rtc); |
447 | 460 | ||
448 | release_resource(dev_get_drvdata(&rtc->dev)); | ||
449 | rtc_device_unregister(rtc); | 461 | rtc_device_unregister(rtc); |
462 | iounmap(rtc_base); | ||
463 | release_mem_region(mem->start, resource_size(mem)); | ||
450 | return 0; | 464 | return 0; |
451 | } | 465 | } |
452 | 466 | ||
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c index c086fc30a84c..242bbf86c74a 100644 --- a/drivers/rtc/rtc-proc.c +++ b/drivers/rtc/rtc-proc.c | |||
@@ -81,12 +81,16 @@ static int rtc_proc_show(struct seq_file *seq, void *offset) | |||
81 | 81 | ||
82 | static int rtc_proc_open(struct inode *inode, struct file *file) | 82 | static int rtc_proc_open(struct inode *inode, struct file *file) |
83 | { | 83 | { |
84 | int ret; | ||
84 | struct rtc_device *rtc = PDE(inode)->data; | 85 | struct rtc_device *rtc = PDE(inode)->data; |
85 | 86 | ||
86 | if (!try_module_get(THIS_MODULE)) | 87 | if (!try_module_get(THIS_MODULE)) |
87 | return -ENODEV; | 88 | return -ENODEV; |
88 | 89 | ||
89 | return single_open(file, rtc_proc_show, rtc); | 90 | ret = single_open(file, rtc_proc_show, rtc); |
91 | if (ret) | ||
92 | module_put(THIS_MODULE); | ||
93 | return ret; | ||
90 | } | 94 | } |
91 | 95 | ||
92 | static int rtc_proc_release(struct inode *inode, struct file *file) | 96 | static int rtc_proc_release(struct inode *inode, struct file *file) |
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index 36eb66184461..694da39b6dd2 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -76,7 +76,7 @@ static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, | |||
76 | static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, | 76 | static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, |
77 | unsigned int reg) | 77 | unsigned int reg) |
78 | { | 78 | { |
79 | return __raw_writel(val, &priv->regs[reg]); | 79 | __raw_writel(val, &priv->regs[reg]); |
80 | } | 80 | } |
81 | 81 | ||
82 | static void rp5c01_lock(struct rp5c01_priv *priv) | 82 | static void rp5c01_lock(struct rp5c01_priv *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..6aaa1550e3b1 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 " |
@@ -299,14 +299,6 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
299 | if (rs5c->type == rtc_rs5c372a | 299 | if (rs5c->type == rtc_rs5c372a |
300 | && (buf & RS5C372A_CTRL1_SL1)) | 300 | && (buf & RS5C372A_CTRL1_SL1)) |
301 | return -ENOIOCTLCMD; | 301 | return -ENOIOCTLCMD; |
302 | case RTC_AIE_OFF: | ||
303 | case RTC_AIE_ON: | ||
304 | /* these irq management calls only make sense for chips | ||
305 | * which are wired up to an IRQ. | ||
306 | */ | ||
307 | if (!rs5c->has_irq) | ||
308 | return -ENOIOCTLCMD; | ||
309 | break; | ||
310 | default: | 302 | default: |
311 | return -ENOIOCTLCMD; | 303 | return -ENOIOCTLCMD; |
312 | } | 304 | } |
@@ -317,12 +309,6 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
317 | 309 | ||
318 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | 310 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
319 | switch (cmd) { | 311 | switch (cmd) { |
320 | case RTC_AIE_OFF: /* alarm off */ | ||
321 | buf &= ~RS5C_CTRL1_AALE; | ||
322 | break; | ||
323 | case RTC_AIE_ON: /* alarm on */ | ||
324 | buf |= RS5C_CTRL1_AALE; | ||
325 | break; | ||
326 | case RTC_UIE_OFF: /* update off */ | 312 | case RTC_UIE_OFF: /* update off */ |
327 | buf &= ~RS5C_CTRL1_CT_MASK; | 313 | buf &= ~RS5C_CTRL1_CT_MASK; |
328 | break; | 314 | break; |
@@ -347,6 +333,39 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
347 | #endif | 333 | #endif |
348 | 334 | ||
349 | 335 | ||
336 | static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
337 | { | ||
338 | struct i2c_client *client = to_i2c_client(dev); | ||
339 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | ||
340 | unsigned char buf; | ||
341 | int status, addr; | ||
342 | |||
343 | buf = rs5c->regs[RS5C_REG_CTRL1]; | ||
344 | |||
345 | if (!rs5c->has_irq) | ||
346 | return -EINVAL; | ||
347 | |||
348 | status = rs5c_get_regs(rs5c); | ||
349 | if (status < 0) | ||
350 | return status; | ||
351 | |||
352 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | ||
353 | if (enabled) | ||
354 | buf |= RS5C_CTRL1_AALE; | ||
355 | else | ||
356 | buf &= ~RS5C_CTRL1_AALE; | ||
357 | |||
358 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | ||
359 | printk(KERN_WARNING "%s: can't update alarm\n", | ||
360 | rs5c->rtc->name); | ||
361 | status = -EIO; | ||
362 | } else | ||
363 | rs5c->regs[RS5C_REG_CTRL1] = buf; | ||
364 | |||
365 | return status; | ||
366 | } | ||
367 | |||
368 | |||
350 | /* NOTE: Since RTC_WKALM_{RD,SET} were originally defined for EFI, | 369 | /* NOTE: Since RTC_WKALM_{RD,SET} were originally defined for EFI, |
351 | * which only exposes a polled programming interface; and since | 370 | * which only exposes a polled programming interface; and since |
352 | * these calls map directly to those EFI requests; we don't demand | 371 | * these calls map directly to those EFI requests; we don't demand |
@@ -466,6 +485,7 @@ static const struct rtc_class_ops rs5c372_rtc_ops = { | |||
466 | .set_time = rs5c372_rtc_set_time, | 485 | .set_time = rs5c372_rtc_set_time, |
467 | .read_alarm = rs5c_read_alarm, | 486 | .read_alarm = rs5c_read_alarm, |
468 | .set_alarm = rs5c_set_alarm, | 487 | .set_alarm = rs5c_set_alarm, |
488 | .alarm_irq_enable = rs5c_rtc_alarm_irq_enable, | ||
469 | }; | 489 | }; |
470 | 490 | ||
471 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) | 491 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) |
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 1146e3522d3c..af32a62e12a8 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c | |||
@@ -650,7 +650,7 @@ static int __devexit rx8025_remove(struct i2c_client *client) | |||
650 | mutex_unlock(lock); | 650 | mutex_unlock(lock); |
651 | 651 | ||
652 | free_irq(client->irq, client); | 652 | free_irq(client->irq, client); |
653 | flush_scheduled_work(); | 653 | cancel_work_sync(&rx8025->work); |
654 | } | 654 | } |
655 | 655 | ||
656 | rx8025_sysfs_unregister(&client->dev); | 656 | rx8025_sysfs_unregister(&client->dev); |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f57a87f4ae96..cf953ecbfca9 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -100,7 +100,7 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
100 | spin_lock_irq(&s3c_rtc_pie_lock); | 100 | spin_lock_irq(&s3c_rtc_pie_lock); |
101 | 101 | ||
102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
103 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 103 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
104 | tmp &= ~S3C64XX_RTCCON_TICEN; | 104 | tmp &= ~S3C64XX_RTCCON_TICEN; |
105 | 105 | ||
106 | if (enabled) | 106 | if (enabled) |
@@ -171,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
171 | goto retry_get_time; | 171 | goto retry_get_time; |
172 | } | 172 | } |
173 | 173 | ||
174 | pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", | 174 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", |
175 | 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, |
176 | 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); |
177 | 177 | ||
178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
@@ -185,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
185 | rtc_tm->tm_year += 100; | 185 | rtc_tm->tm_year += 100; |
186 | rtc_tm->tm_mon -= 1; | 186 | rtc_tm->tm_mon -= 1; |
187 | 187 | ||
188 | return 0; | 188 | return rtc_valid_tm(rtc_tm); |
189 | } | 189 | } |
190 | 190 | ||
191 | 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) |
@@ -193,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
193 | void __iomem *base = s3c_rtc_base; | 193 | void __iomem *base = s3c_rtc_base; |
194 | int year = tm->tm_year - 100; | 194 | int year = tm->tm_year - 100; |
195 | 195 | ||
196 | pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", | 196 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
197 | tm->tm_year, tm->tm_mon, tm->tm_mday, | 197 | 1900 + tm->tm_year, 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 | 199 | ||
200 | /* we get around y2k by simply not supporting it */ | 200 | /* we get around y2k by simply not supporting it */ |
@@ -231,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
231 | 231 | ||
232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; | 232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; |
233 | 233 | ||
234 | 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", |
235 | alm_en, | 235 | alm_en, |
236 | 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, |
237 | 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); |
238 | 238 | ||
239 | 239 | ||
@@ -242,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
242 | if (alm_en & S3C2410_RTCALM_SECEN) | 242 | if (alm_en & S3C2410_RTCALM_SECEN) |
243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); | 243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
244 | else | 244 | else |
245 | alm_tm->tm_sec = 0xff; | 245 | alm_tm->tm_sec = -1; |
246 | 246 | ||
247 | if (alm_en & S3C2410_RTCALM_MINEN) | 247 | if (alm_en & S3C2410_RTCALM_MINEN) |
248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); | 248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
249 | else | 249 | else |
250 | alm_tm->tm_min = 0xff; | 250 | alm_tm->tm_min = -1; |
251 | 251 | ||
252 | if (alm_en & S3C2410_RTCALM_HOUREN) | 252 | if (alm_en & S3C2410_RTCALM_HOUREN) |
253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); | 253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
254 | else | 254 | else |
255 | alm_tm->tm_hour = 0xff; | 255 | alm_tm->tm_hour = -1; |
256 | 256 | ||
257 | if (alm_en & S3C2410_RTCALM_DAYEN) | 257 | if (alm_en & S3C2410_RTCALM_DAYEN) |
258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); | 258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
259 | else | 259 | else |
260 | alm_tm->tm_mday = 0xff; | 260 | alm_tm->tm_mday = -1; |
261 | 261 | ||
262 | if (alm_en & S3C2410_RTCALM_MONEN) { | 262 | if (alm_en & S3C2410_RTCALM_MONEN) { |
263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); | 263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
264 | alm_tm->tm_mon -= 1; | 264 | alm_tm->tm_mon -= 1; |
265 | } else { | 265 | } else { |
266 | alm_tm->tm_mon = 0xff; | 266 | alm_tm->tm_mon = -1; |
267 | } | 267 | } |
268 | 268 | ||
269 | if (alm_en & S3C2410_RTCALM_YEAREN) | 269 | if (alm_en & S3C2410_RTCALM_YEAREN) |
270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); | 270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
271 | else | 271 | else |
272 | alm_tm->tm_year = 0xffff; | 272 | alm_tm->tm_year = -1; |
273 | 273 | ||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
@@ -280,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
280 | void __iomem *base = s3c_rtc_base; | 280 | void __iomem *base = s3c_rtc_base; |
281 | unsigned int alrm_en; | 281 | unsigned int alrm_en; |
282 | 282 | ||
283 | 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", |
284 | alrm->enabled, | 284 | alrm->enabled, |
285 | tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, | 285 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
286 | tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); | 286 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
287 | 287 | ||
288 | 288 | ||
289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
@@ -318,7 +318,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
318 | unsigned int ticnt; | 318 | unsigned int ticnt; |
319 | 319 | ||
320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
321 | ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); | 321 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
322 | ticnt &= S3C64XX_RTCCON_TICEN; | 322 | ticnt &= S3C64XX_RTCCON_TICEN; |
323 | } else { | 323 | } else { |
324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
@@ -379,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = { | |||
379 | .set_alarm = s3c_rtc_setalarm, | 379 | .set_alarm = s3c_rtc_setalarm, |
380 | .irq_set_freq = s3c_rtc_setfreq, | 380 | .irq_set_freq = s3c_rtc_setfreq, |
381 | .irq_set_state = s3c_rtc_setpie, | 381 | .irq_set_state = s3c_rtc_setpie, |
382 | .proc = s3c_rtc_proc, | 382 | .proc = s3c_rtc_proc, |
383 | .alarm_irq_enable = s3c_rtc_setaie, | ||
383 | }; | 384 | }; |
384 | 385 | ||
385 | static void s3c_rtc_enable(struct platform_device *pdev, int en) | 386 | static void s3c_rtc_enable(struct platform_device *pdev, int en) |
@@ -391,11 +392,11 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
391 | return; | 392 | return; |
392 | 393 | ||
393 | if (!en) { | 394 | if (!en) { |
394 | tmp = readb(base + S3C2410_RTCCON); | 395 | tmp = readw(base + S3C2410_RTCCON); |
395 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 396 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
396 | tmp &= ~S3C64XX_RTCCON_TICEN; | 397 | tmp &= ~S3C64XX_RTCCON_TICEN; |
397 | tmp &= ~S3C2410_RTCCON_RTCEN; | 398 | tmp &= ~S3C2410_RTCCON_RTCEN; |
398 | writeb(tmp, base + S3C2410_RTCCON); | 399 | writew(tmp, base + S3C2410_RTCCON); |
399 | 400 | ||
400 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 401 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
401 | tmp = readb(base + S3C2410_TICNT); | 402 | tmp = readb(base + S3C2410_TICNT); |
@@ -405,25 +406,28 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
405 | } else { | 406 | } else { |
406 | /* re-enable the device, and check it is ok */ | 407 | /* re-enable the device, and check it is ok */ |
407 | 408 | ||
408 | if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ | 409 | if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { |
409 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); | 410 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); |
410 | 411 | ||
411 | tmp = readb(base + S3C2410_RTCCON); | 412 | tmp = readw(base + S3C2410_RTCCON); |
412 | writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); | 413 | writew(tmp | S3C2410_RTCCON_RTCEN, |
414 | base + S3C2410_RTCCON); | ||
413 | } | 415 | } |
414 | 416 | ||
415 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ | 417 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { |
416 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); | 418 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); |
417 | 419 | ||
418 | tmp = readb(base + S3C2410_RTCCON); | 420 | tmp = readw(base + S3C2410_RTCCON); |
419 | writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); | 421 | writew(tmp & ~S3C2410_RTCCON_CNTSEL, |
422 | base + S3C2410_RTCCON); | ||
420 | } | 423 | } |
421 | 424 | ||
422 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ | 425 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { |
423 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); | 426 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); |
424 | 427 | ||
425 | tmp = readb(base + S3C2410_RTCCON); | 428 | tmp = readw(base + S3C2410_RTCCON); |
426 | writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); | 429 | writew(tmp & ~S3C2410_RTCCON_CLKRST, |
430 | base + S3C2410_RTCCON); | ||
427 | } | 431 | } |
428 | } | 432 | } |
429 | } | 433 | } |
@@ -452,8 +456,8 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
452 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) | 456 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
453 | { | 457 | { |
454 | struct rtc_device *rtc; | 458 | struct rtc_device *rtc; |
459 | struct rtc_time rtc_tm; | ||
455 | struct resource *res; | 460 | struct resource *res; |
456 | unsigned int tmp, i; | ||
457 | int ret; | 461 | int ret; |
458 | 462 | ||
459 | pr_debug("%s: probe=%p\n", __func__, pdev); | 463 | pr_debug("%s: probe=%p\n", __func__, pdev); |
@@ -514,8 +518,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
514 | 518 | ||
515 | s3c_rtc_enable(pdev, 1); | 519 | s3c_rtc_enable(pdev, 1); |
516 | 520 | ||
517 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 521 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
518 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 522 | readw(s3c_rtc_base + S3C2410_RTCCON)); |
519 | 523 | ||
520 | device_init_wakeup(&pdev->dev, 1); | 524 | device_init_wakeup(&pdev->dev, 1); |
521 | 525 | ||
@@ -534,11 +538,19 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
534 | 538 | ||
535 | /* Check RTC Time */ | 539 | /* Check RTC Time */ |
536 | 540 | ||
537 | for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { | 541 | s3c_rtc_gettime(NULL, &rtc_tm); |
538 | tmp = readb(s3c_rtc_base + i); | 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); | ||
539 | 552 | ||
540 | if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) | 553 | dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); |
541 | writeb(0, s3c_rtc_base + i); | ||
542 | } | 554 | } |
543 | 555 | ||
544 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 556 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
@@ -578,7 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
578 | /* save TICNT for anyone using periodic interrupts */ | 590 | /* save TICNT for anyone using periodic interrupts */ |
579 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 591 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
580 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 592 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
581 | ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); | 593 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); |
582 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | 594 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; |
583 | } | 595 | } |
584 | s3c_rtc_enable(pdev, 0); | 596 | s3c_rtc_enable(pdev, 0); |
@@ -596,8 +608,8 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
596 | s3c_rtc_enable(pdev, 1); | 608 | s3c_rtc_enable(pdev, 1); |
597 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 609 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
598 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 610 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
599 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 611 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
600 | writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | 612 | writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); |
601 | } | 613 | } |
602 | 614 | ||
603 | if (device_may_wakeup(&pdev->dev)) | 615 | if (device_may_wakeup(&pdev->dev)) |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index e4a44b641702..5dfe5ffcb0d3 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -39,10 +39,10 @@ | |||
39 | #include <mach/regs-ost.h> | 39 | #include <mach/regs-ost.h> |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #define RTC_DEF_DIVIDER 32768 - 1 | 42 | #define RTC_DEF_DIVIDER (32768 - 1) |
43 | #define RTC_DEF_TRIM 0 | 43 | #define RTC_DEF_TRIM 0 |
44 | 44 | ||
45 | static unsigned long rtc_freq = 1024; | 45 | static const unsigned long RTC_FREQ = 1024; |
46 | static unsigned long timer_freq; | 46 | static unsigned long timer_freq; |
47 | static struct rtc_time rtc_alarm; | 47 | static struct rtc_time rtc_alarm; |
48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); |
@@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm) | |||
61 | * Calculate the next alarm time given the requested alarm time mask | 61 | * Calculate the next alarm time given the requested alarm time mask |
62 | * and the current time. | 62 | * and the current time. |
63 | */ | 63 | */ |
64 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm) | 64 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, |
65 | struct rtc_time *alrm) | ||
65 | { | 66 | { |
66 | unsigned long next_time; | 67 | unsigned long next_time; |
67 | unsigned long now_time; | 68 | unsigned long now_time; |
@@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
116 | rtsr = RTSR; | 117 | rtsr = RTSR; |
117 | /* clear interrupt sources */ | 118 | /* clear interrupt sources */ |
118 | RTSR = 0; | 119 | RTSR = 0; |
119 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | 120 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
121 | * See also the comments in sa1100_rtc_probe(). */ | ||
122 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { | ||
123 | /* This is the original code, before there was the if test | ||
124 | * above. This code does not clear interrupts that were not | ||
125 | * enabled. */ | ||
126 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | ||
127 | } else { | ||
128 | /* For some reason, it is possible to enter this routine | ||
129 | * without interruptions enabled, it has been tested with | ||
130 | * several units (Bug in SA11xx chip?). | ||
131 | * | ||
132 | * This situation leads to an infinite "loop" of interrupt | ||
133 | * routine calling and as a result the processor seems to | ||
134 | * lock on its first call to open(). */ | ||
135 | RTSR = RTSR_AL | RTSR_HZ; | ||
136 | } | ||
120 | 137 | ||
121 | /* clear alarm interrupt if it has occurred */ | 138 | /* clear alarm interrupt if it has occurred */ |
122 | if (rtsr & RTSR_AL) | 139 | if (rtsr & RTSR_AL) |
@@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
139 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
140 | } | 157 | } |
141 | 158 | ||
159 | static int sa1100_irq_set_freq(struct device *dev, int freq) | ||
160 | { | ||
161 | if (freq < 1 || freq > timer_freq) { | ||
162 | return -EINVAL; | ||
163 | } else { | ||
164 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
165 | |||
166 | rtc->irq_freq = freq; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
142 | static int rtc_timer1_count; | 172 | static int rtc_timer1_count; |
143 | 173 | ||
174 | static int sa1100_irq_set_state(struct device *dev, int enabled) | ||
175 | { | ||
176 | spin_lock_irq(&sa1100_rtc_lock); | ||
177 | if (enabled) { | ||
178 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
179 | |||
180 | OSMR1 = timer_freq / rtc->irq_freq + OSCR; | ||
181 | OIER |= OIER_E1; | ||
182 | rtc_timer1_count = 1; | ||
183 | } else { | ||
184 | OIER &= ~OIER_E1; | ||
185 | } | ||
186 | spin_unlock_irq(&sa1100_rtc_lock); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static inline int sa1100_timer1_retrigger(struct rtc_device *rtc) | ||
192 | { | ||
193 | unsigned long diff; | ||
194 | unsigned long period = timer_freq / rtc->irq_freq; | ||
195 | |||
196 | spin_lock_irq(&sa1100_rtc_lock); | ||
197 | |||
198 | do { | ||
199 | OSMR1 += period; | ||
200 | diff = OSMR1 - OSCR; | ||
201 | /* If OSCR > OSMR1, diff is a very large number (unsigned | ||
202 | * math). This means we have a lost interrupt. */ | ||
203 | } while (diff > period); | ||
204 | OIER |= OIER_E1; | ||
205 | |||
206 | spin_unlock_irq(&sa1100_rtc_lock); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
144 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) | 211 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) |
145 | { | 212 | { |
146 | struct platform_device *pdev = to_platform_device(dev_id); | 213 | struct platform_device *pdev = to_platform_device(dev_id); |
@@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) | |||
158 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); | 225 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); |
159 | 226 | ||
160 | if (rtc_timer1_count == 1) | 227 | if (rtc_timer1_count == 1) |
161 | rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2))); | 228 | rtc_timer1_count = |
229 | (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2))); | ||
230 | |||
231 | /* retrigger. */ | ||
232 | sa1100_timer1_retrigger(rtc); | ||
162 | 233 | ||
163 | return IRQ_HANDLED; | 234 | return IRQ_HANDLED; |
164 | } | 235 | } |
@@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) | |||
166 | static int sa1100_rtc_read_callback(struct device *dev, int data) | 237 | static int sa1100_rtc_read_callback(struct device *dev, int data) |
167 | { | 238 | { |
168 | if (data & RTC_PF) { | 239 | if (data & RTC_PF) { |
240 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
241 | |||
169 | /* interpolate missed periods and set match for the next */ | 242 | /* interpolate missed periods and set match for the next */ |
170 | unsigned long period = timer_freq / rtc_freq; | 243 | unsigned long period = timer_freq / rtc->irq_freq; |
171 | unsigned long oscr = OSCR; | 244 | unsigned long oscr = OSCR; |
172 | unsigned long osmr1 = OSMR1; | 245 | unsigned long osmr1 = OSMR1; |
173 | unsigned long missed = (oscr - osmr1)/period; | 246 | unsigned long missed = (oscr - osmr1)/period; |
@@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data) | |||
178 | * Here we compare (match - OSCR) 8 instead of 0 -- | 251 | * Here we compare (match - OSCR) 8 instead of 0 -- |
179 | * see comment in pxa_timer_interrupt() for explanation. | 252 | * see comment in pxa_timer_interrupt() for explanation. |
180 | */ | 253 | */ |
181 | while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { | 254 | while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) { |
182 | data += 0x100; | 255 | data += 0x100; |
183 | OSSR = OSSR_M1; /* clear match on timer 1 */ | 256 | OSSR = OSSR_M1; /* clear match on timer 1 */ |
184 | OSMR1 = osmr1 + period; | 257 | OSMR1 = osmr1 + period; |
@@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data) | |||
190 | static int sa1100_rtc_open(struct device *dev) | 263 | static int sa1100_rtc_open(struct device *dev) |
191 | { | 264 | { |
192 | int ret; | 265 | int ret; |
266 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
193 | 267 | ||
194 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 268 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, |
195 | "rtc 1Hz", dev); | 269 | "rtc 1Hz", dev); |
196 | if (ret) { | 270 | if (ret) { |
197 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); | 271 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); |
198 | goto fail_ui; | 272 | goto fail_ui; |
199 | } | 273 | } |
200 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, | 274 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, |
201 | "rtc Alrm", dev); | 275 | "rtc Alrm", dev); |
202 | if (ret) { | 276 | if (ret) { |
203 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 277 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); |
204 | goto fail_ai; | 278 | goto fail_ai; |
205 | } | 279 | } |
206 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, | 280 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, |
207 | "rtc timer", dev); | 281 | "rtc timer", dev); |
208 | if (ret) { | 282 | if (ret) { |
209 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); | 283 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); |
210 | goto fail_pi; | 284 | goto fail_pi; |
211 | } | 285 | } |
286 | rtc->max_user_freq = RTC_FREQ; | ||
287 | sa1100_irq_set_freq(dev, RTC_FREQ); | ||
288 | |||
212 | return 0; | 289 | return 0; |
213 | 290 | ||
214 | fail_pi: | 291 | fail_pi: |
@@ -236,17 +313,7 @@ static void sa1100_rtc_release(struct device *dev) | |||
236 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | 313 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, |
237 | unsigned long arg) | 314 | unsigned long arg) |
238 | { | 315 | { |
239 | switch(cmd) { | 316 | switch (cmd) { |
240 | case RTC_AIE_OFF: | ||
241 | spin_lock_irq(&sa1100_rtc_lock); | ||
242 | RTSR &= ~RTSR_ALE; | ||
243 | spin_unlock_irq(&sa1100_rtc_lock); | ||
244 | return 0; | ||
245 | case RTC_AIE_ON: | ||
246 | spin_lock_irq(&sa1100_rtc_lock); | ||
247 | RTSR |= RTSR_ALE; | ||
248 | spin_unlock_irq(&sa1100_rtc_lock); | ||
249 | return 0; | ||
250 | case RTC_UIE_OFF: | 317 | case RTC_UIE_OFF: |
251 | spin_lock_irq(&sa1100_rtc_lock); | 318 | spin_lock_irq(&sa1100_rtc_lock); |
252 | RTSR &= ~RTSR_HZE; | 319 | RTSR &= ~RTSR_HZE; |
@@ -257,29 +324,21 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
257 | RTSR |= RTSR_HZE; | 324 | RTSR |= RTSR_HZE; |
258 | spin_unlock_irq(&sa1100_rtc_lock); | 325 | spin_unlock_irq(&sa1100_rtc_lock); |
259 | return 0; | 326 | return 0; |
260 | case RTC_PIE_OFF: | ||
261 | spin_lock_irq(&sa1100_rtc_lock); | ||
262 | OIER &= ~OIER_E1; | ||
263 | spin_unlock_irq(&sa1100_rtc_lock); | ||
264 | return 0; | ||
265 | case RTC_PIE_ON: | ||
266 | spin_lock_irq(&sa1100_rtc_lock); | ||
267 | OSMR1 = timer_freq / rtc_freq + OSCR; | ||
268 | OIER |= OIER_E1; | ||
269 | rtc_timer1_count = 1; | ||
270 | spin_unlock_irq(&sa1100_rtc_lock); | ||
271 | return 0; | ||
272 | case RTC_IRQP_READ: | ||
273 | return put_user(rtc_freq, (unsigned long *)arg); | ||
274 | case RTC_IRQP_SET: | ||
275 | if (arg < 1 || arg > timer_freq) | ||
276 | return -EINVAL; | ||
277 | rtc_freq = arg; | ||
278 | return 0; | ||
279 | } | 327 | } |
280 | return -ENOIOCTLCMD; | 328 | return -ENOIOCTLCMD; |
281 | } | 329 | } |
282 | 330 | ||
331 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
332 | { | ||
333 | spin_lock_irq(&sa1100_rtc_lock); | ||
334 | if (enabled) | ||
335 | RTSR |= RTSR_ALE; | ||
336 | else | ||
337 | RTSR &= ~RTSR_ALE; | ||
338 | spin_unlock_irq(&sa1100_rtc_lock); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
283 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 342 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
284 | { | 343 | { |
285 | rtc_time_to_tm(RCNR, tm); | 344 | rtc_time_to_tm(RCNR, tm); |
@@ -327,12 +386,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
327 | 386 | ||
328 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | 387 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) |
329 | { | 388 | { |
389 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
390 | |||
330 | seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); | 391 | seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); |
331 | seq_printf(seq, "update_IRQ\t: %s\n", | 392 | seq_printf(seq, "update_IRQ\t: %s\n", |
332 | (RTSR & RTSR_HZE) ? "yes" : "no"); | 393 | (RTSR & RTSR_HZE) ? "yes" : "no"); |
333 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 394 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
334 | (OIER & OIER_E1) ? "yes" : "no"); | 395 | (OIER & OIER_E1) ? "yes" : "no"); |
335 | seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); | 396 | seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq); |
397 | seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR); | ||
336 | 398 | ||
337 | return 0; | 399 | return 0; |
338 | } | 400 | } |
@@ -347,6 +409,9 @@ static const struct rtc_class_ops sa1100_rtc_ops = { | |||
347 | .read_alarm = sa1100_rtc_read_alarm, | 409 | .read_alarm = sa1100_rtc_read_alarm, |
348 | .set_alarm = sa1100_rtc_set_alarm, | 410 | .set_alarm = sa1100_rtc_set_alarm, |
349 | .proc = sa1100_rtc_proc, | 411 | .proc = sa1100_rtc_proc, |
412 | .irq_set_freq = sa1100_irq_set_freq, | ||
413 | .irq_set_state = sa1100_irq_set_state, | ||
414 | .alarm_irq_enable = sa1100_rtc_alarm_irq_enable, | ||
350 | }; | 415 | }; |
351 | 416 | ||
352 | static int sa1100_rtc_probe(struct platform_device *pdev) | 417 | static int sa1100_rtc_probe(struct platform_device *pdev) |
@@ -364,7 +429,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
364 | */ | 429 | */ |
365 | if (RTTR == 0) { | 430 | if (RTTR == 0) { |
366 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); | 431 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); |
367 | dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n"); | 432 | dev_warn(&pdev->dev, "warning: " |
433 | "initializing default clock divider/trim value\n"); | ||
368 | /* The current RTC value probably doesn't make sense either */ | 434 | /* The current RTC value probably doesn't make sense either */ |
369 | RCNR = 0; | 435 | RCNR = 0; |
370 | } | 436 | } |
@@ -372,13 +438,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
372 | device_init_wakeup(&pdev->dev, 1); | 438 | device_init_wakeup(&pdev->dev, 1); |
373 | 439 | ||
374 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, | 440 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, |
375 | THIS_MODULE); | 441 | THIS_MODULE); |
376 | 442 | ||
377 | if (IS_ERR(rtc)) | 443 | if (IS_ERR(rtc)) |
378 | return PTR_ERR(rtc); | 444 | return PTR_ERR(rtc); |
379 | 445 | ||
380 | platform_set_drvdata(pdev, rtc); | 446 | platform_set_drvdata(pdev, rtc); |
381 | 447 | ||
448 | /* Set the irq_freq */ | ||
449 | /*TODO: Find out who is messing with this value after we initialize | ||
450 | * it here.*/ | ||
451 | rtc->irq_freq = RTC_FREQ; | ||
452 | |||
453 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | ||
454 | * See also the comments in sa1100_rtc_interrupt(). | ||
455 | * | ||
456 | * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an | ||
457 | * interrupt pending, even though interrupts were never enabled. | ||
458 | * In this case, this bit it must be reset before enabling | ||
459 | * interruptions to avoid a nonexistent interrupt to occur. | ||
460 | * | ||
461 | * In principle, the same problem would apply to bit 0, although it has | ||
462 | * never been observed to happen. | ||
463 | * | ||
464 | * This issue is addressed both here and in sa1100_rtc_interrupt(). | ||
465 | * If the issue is not addressed here, in the times when the processor | ||
466 | * wakes up with the bit set there will be one spurious interrupt. | ||
467 | * | ||
468 | * The issue is also dealt with in sa1100_rtc_interrupt() to be on the | ||
469 | * safe side, once the condition that lead to this strange | ||
470 | * initialization is unknown and could in principle happen during | ||
471 | * normal processing. | ||
472 | * | ||
473 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to | ||
474 | * the corresponding bits in RTSR. */ | ||
475 | RTSR = RTSR_AL | RTSR_HZ; | ||
476 | |||
382 | return 0; | 477 | return 0; |
383 | } | 478 | } |
384 | 479 | ||
@@ -386,7 +481,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
386 | { | 481 | { |
387 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 482 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
388 | 483 | ||
389 | if (rtc) | 484 | if (rtc) |
390 | rtc_device_unregister(rtc); | 485 | rtc_device_unregister(rtc); |
391 | 486 | ||
392 | return 0; | 487 | return 0; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 5efbd5990ff8..93314a9e7fa9 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -350,10 +350,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
350 | unsigned int ret = 0; | 350 | unsigned int ret = 0; |
351 | 351 | ||
352 | switch (cmd) { | 352 | switch (cmd) { |
353 | case RTC_AIE_OFF: | ||
354 | case RTC_AIE_ON: | ||
355 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); | ||
356 | break; | ||
357 | case RTC_UIE_OFF: | 353 | case RTC_UIE_OFF: |
358 | rtc->periodic_freq &= ~PF_OXS; | 354 | rtc->periodic_freq &= ~PF_OXS; |
359 | sh_rtc_setcie(dev, 0); | 355 | sh_rtc_setcie(dev, 0); |
@@ -369,6 +365,12 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
369 | return ret; | 365 | return ret; |
370 | } | 366 | } |
371 | 367 | ||
368 | static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
369 | { | ||
370 | sh_rtc_setaie(dev, enabled); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
372 | static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) | 374 | static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) |
373 | { | 375 | { |
374 | struct platform_device *pdev = to_platform_device(dev); | 376 | struct platform_device *pdev = to_platform_device(dev); |
@@ -604,6 +606,7 @@ static struct rtc_class_ops sh_rtc_ops = { | |||
604 | .irq_set_state = sh_rtc_irq_set_state, | 606 | .irq_set_state = sh_rtc_irq_set_state, |
605 | .irq_set_freq = sh_rtc_irq_set_freq, | 607 | .irq_set_freq = sh_rtc_irq_set_freq, |
606 | .proc = sh_rtc_proc, | 608 | .proc = sh_rtc_proc, |
609 | .alarm_irq_enable = sh_rtc_alarm_irq_enable, | ||
607 | }; | 610 | }; |
608 | 611 | ||
609 | static int __init sh_rtc_probe(struct platform_device *pdev) | 612 | static int __init sh_rtc_probe(struct platform_device *pdev) |
@@ -761,7 +764,7 @@ err_unmap: | |||
761 | clk_put(rtc->clk); | 764 | clk_put(rtc->clk); |
762 | iounmap(rtc->regbase); | 765 | iounmap(rtc->regbase); |
763 | err_badmap: | 766 | err_badmap: |
764 | release_resource(rtc->res); | 767 | release_mem_region(rtc->res->start, rtc->regsize); |
765 | err_badres: | 768 | err_badres: |
766 | kfree(rtc); | 769 | kfree(rtc); |
767 | 770 | ||
@@ -786,7 +789,7 @@ static int __exit sh_rtc_remove(struct platform_device *pdev) | |||
786 | } | 789 | } |
787 | 790 | ||
788 | iounmap(rtc->regbase); | 791 | iounmap(rtc->regbase); |
789 | release_resource(rtc->res); | 792 | release_mem_region(rtc->res->start, rtc->regsize); |
790 | 793 | ||
791 | clk_disable(rtc->clk); | 794 | clk_disable(rtc->clk); |
792 | clk_put(rtc->clk); | 795 | clk_put(rtc->clk); |
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 51725f7755b0..a82d6fe97076 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c | |||
@@ -50,24 +50,9 @@ static int test_rtc_proc(struct device *dev, struct seq_file *seq) | |||
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | 52 | ||
53 | static int test_rtc_ioctl(struct device *dev, unsigned int cmd, | 53 | static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) |
54 | unsigned long arg) | ||
55 | { | 54 | { |
56 | /* We do support interrupts, they're generated | 55 | return 0; |
57 | * using the sysfs interface. | ||
58 | */ | ||
59 | switch (cmd) { | ||
60 | case RTC_PIE_ON: | ||
61 | case RTC_PIE_OFF: | ||
62 | case RTC_UIE_ON: | ||
63 | case RTC_UIE_OFF: | ||
64 | case RTC_AIE_ON: | ||
65 | case RTC_AIE_OFF: | ||
66 | return 0; | ||
67 | |||
68 | default: | ||
69 | return -ENOIOCTLCMD; | ||
70 | } | ||
71 | } | 56 | } |
72 | 57 | ||
73 | static const struct rtc_class_ops test_rtc_ops = { | 58 | static const struct rtc_class_ops test_rtc_ops = { |
@@ -76,7 +61,7 @@ static const struct rtc_class_ops test_rtc_ops = { | |||
76 | .read_alarm = test_rtc_read_alarm, | 61 | .read_alarm = test_rtc_read_alarm, |
77 | .set_alarm = test_rtc_set_alarm, | 62 | .set_alarm = test_rtc_set_alarm, |
78 | .set_mmss = test_rtc_set_mmss, | 63 | .set_mmss = test_rtc_set_mmss, |
79 | .ioctl = test_rtc_ioctl, | 64 | .alarm_irq_enable = test_rtc_alarm_irq_enable, |
80 | }; | 65 | }; |
81 | 66 | ||
82 | static ssize_t test_irq_show(struct device *dev, | 67 | static ssize_t test_irq_show(struct device *dev, |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index c3244244e8cf..769190ac6d11 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -240,26 +240,6 @@ static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled) | |||
240 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 240 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
241 | { | 241 | { |
242 | switch (cmd) { | 242 | switch (cmd) { |
243 | case RTC_AIE_ON: | ||
244 | spin_lock_irq(&rtc_lock); | ||
245 | |||
246 | if (!alarm_enabled) { | ||
247 | enable_irq(aie_irq); | ||
248 | alarm_enabled = 1; | ||
249 | } | ||
250 | |||
251 | spin_unlock_irq(&rtc_lock); | ||
252 | break; | ||
253 | case RTC_AIE_OFF: | ||
254 | spin_lock_irq(&rtc_lock); | ||
255 | |||
256 | if (alarm_enabled) { | ||
257 | disable_irq(aie_irq); | ||
258 | alarm_enabled = 0; | ||
259 | } | ||
260 | |||
261 | spin_unlock_irq(&rtc_lock); | ||
262 | break; | ||
263 | case RTC_EPOCH_READ: | 243 | case RTC_EPOCH_READ: |
264 | return put_user(epoch, (unsigned long __user *)arg); | 244 | return put_user(epoch, (unsigned long __user *)arg); |
265 | case RTC_EPOCH_SET: | 245 | case RTC_EPOCH_SET: |
@@ -275,6 +255,24 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long | |||
275 | return 0; | 255 | return 0; |
276 | } | 256 | } |
277 | 257 | ||
258 | static int vr41xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
259 | { | ||
260 | spin_lock_irq(&rtc_lock); | ||
261 | if (enabled) { | ||
262 | if (!alarm_enabled) { | ||
263 | enable_irq(aie_irq); | ||
264 | alarm_enabled = 1; | ||
265 | } | ||
266 | } else { | ||
267 | if (alarm_enabled) { | ||
268 | disable_irq(aie_irq); | ||
269 | alarm_enabled = 0; | ||
270 | } | ||
271 | } | ||
272 | spin_unlock_irq(&rtc_lock); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
278 | static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id) | 276 | static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id) |
279 | { | 277 | { |
280 | struct platform_device *pdev = (struct platform_device *)dev_id; | 278 | struct platform_device *pdev = (struct platform_device *)dev_id; |