diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-vr41xx.c | 65 |
1 files changed, 34 insertions, 31 deletions
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index be9c70d0b193..884b635f028b 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); |
36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL v2"); |
38 | 38 | ||
39 | /* RTC 1 registers */ | 39 | /* RTC 1 registers */ |
40 | #define ETIMELREG 0x00 | 40 | #define ETIMELREG 0x00 |
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ | |||
82 | 82 | ||
83 | static DEFINE_SPINLOCK(rtc_lock); | 83 | static DEFINE_SPINLOCK(rtc_lock); |
84 | static char rtc_name[] = "RTC"; | 84 | static char rtc_name[] = "RTC"; |
85 | static unsigned long periodic_frequency; | ||
86 | static unsigned long periodic_count; | 85 | static unsigned long periodic_count; |
87 | static unsigned int alarm_enabled; | 86 | static unsigned int alarm_enabled; |
88 | static int aie_irq = -1; | 87 | static int aie_irq = -1; |
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
207 | return 0; | 206 | return 0; |
208 | } | 207 | } |
209 | 208 | ||
210 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 209 | static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq) |
211 | { | 210 | { |
212 | unsigned long count; | 211 | unsigned long count; |
213 | 212 | ||
213 | count = RTC_FREQUENCY; | ||
214 | do_div(count, freq); | ||
215 | |||
216 | periodic_count = count; | ||
217 | |||
218 | spin_lock_irq(&rtc_lock); | ||
219 | |||
220 | rtc1_write(RTCL1LREG, count); | ||
221 | rtc1_write(RTCL1HREG, count >> 16); | ||
222 | |||
223 | spin_unlock_irq(&rtc_lock); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled) | ||
229 | { | ||
230 | if (enabled) | ||
231 | enable_irq(pie_irq); | ||
232 | else | ||
233 | disable_irq(pie_irq); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
239 | { | ||
214 | switch (cmd) { | 240 | switch (cmd) { |
215 | case RTC_AIE_ON: | 241 | case RTC_AIE_ON: |
216 | spin_lock_irq(&rtc_lock); | 242 | spin_lock_irq(&rtc_lock); |
@@ -232,33 +258,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long | |||
232 | 258 | ||
233 | spin_unlock_irq(&rtc_lock); | 259 | spin_unlock_irq(&rtc_lock); |
234 | break; | 260 | break; |
235 | case RTC_PIE_ON: | ||
236 | enable_irq(pie_irq); | ||
237 | break; | ||
238 | case RTC_PIE_OFF: | ||
239 | disable_irq(pie_irq); | ||
240 | break; | ||
241 | case RTC_IRQP_READ: | ||
242 | return put_user(periodic_frequency, (unsigned long __user *)arg); | ||
243 | break; | ||
244 | case RTC_IRQP_SET: | ||
245 | if (arg > MAX_PERIODIC_RATE) | ||
246 | return -EINVAL; | ||
247 | |||
248 | periodic_frequency = arg; | ||
249 | |||
250 | count = RTC_FREQUENCY; | ||
251 | do_div(count, arg); | ||
252 | |||
253 | periodic_count = count; | ||
254 | |||
255 | spin_lock_irq(&rtc_lock); | ||
256 | |||
257 | rtc1_write(RTCL1LREG, count); | ||
258 | rtc1_write(RTCL1HREG, count >> 16); | ||
259 | |||
260 | spin_unlock_irq(&rtc_lock); | ||
261 | break; | ||
262 | case RTC_EPOCH_READ: | 261 | case RTC_EPOCH_READ: |
263 | return put_user(epoch, (unsigned long __user *)arg); | 262 | return put_user(epoch, (unsigned long __user *)arg); |
264 | case RTC_EPOCH_SET: | 263 | case RTC_EPOCH_SET: |
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = { | |||
309 | .set_time = vr41xx_rtc_set_time, | 308 | .set_time = vr41xx_rtc_set_time, |
310 | .read_alarm = vr41xx_rtc_read_alarm, | 309 | .read_alarm = vr41xx_rtc_read_alarm, |
311 | .set_alarm = vr41xx_rtc_set_alarm, | 310 | .set_alarm = vr41xx_rtc_set_alarm, |
311 | .irq_set_freq = vr41xx_rtc_irq_set_freq, | ||
312 | .irq_set_state = vr41xx_rtc_irq_set_state, | ||
312 | }; | 313 | }; |
313 | 314 | ||
314 | static int __devinit rtc_probe(struct platform_device *pdev) | 315 | static int __devinit rtc_probe(struct platform_device *pdev) |
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
346 | goto err_iounmap_all; | 347 | goto err_iounmap_all; |
347 | } | 348 | } |
348 | 349 | ||
350 | rtc->max_user_freq = MAX_PERIODIC_RATE; | ||
351 | |||
349 | spin_lock_irq(&rtc_lock); | 352 | spin_lock_irq(&rtc_lock); |
350 | 353 | ||
351 | rtc1_write(ECMPLREG, 0); | 354 | rtc1_write(ECMPLREG, 0); |