diff options
Diffstat (limited to 'drivers/rtc/rtc-mrst.c')
-rw-r--r-- | drivers/rtc/rtc-mrst.c | 79 |
1 files changed, 25 insertions, 54 deletions
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index bcd0cf63eb16..b2f096871a97 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr) | |||
62 | return rtc_intr & RTC_IRQMASK; | 62 | return rtc_intr & RTC_IRQMASK; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline unsigned char vrtc_is_updating(void) | ||
66 | { | ||
67 | unsigned char uip; | ||
68 | unsigned long flags; | ||
69 | |||
70 | spin_lock_irqsave(&rtc_lock, flags); | ||
71 | uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP); | ||
72 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
73 | return uip; | ||
74 | } | ||
75 | |||
65 | /* | 76 | /* |
66 | * rtc_time's year contains the increment over 1900, but vRTC's YEAR | 77 | * 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 | 78 | * register can't be programmed to value larger than 0x64, so vRTC |
@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time) | |||
76 | { | 87 | { |
77 | unsigned long flags; | 88 | unsigned long flags; |
78 | 89 | ||
79 | if (rtc_is_updating()) | 90 | if (vrtc_is_updating()) |
80 | mdelay(20); | 91 | mdelay(20); |
81 | 92 | ||
82 | spin_lock_irqsave(&rtc_lock, flags); | 93 | spin_lock_irqsave(&rtc_lock, flags); |
@@ -236,61 +247,21 @@ static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
236 | return 0; | 247 | return 0; |
237 | } | 248 | } |
238 | 249 | ||
239 | static int mrst_irq_set_state(struct device *dev, int enabled) | 250 | /* Currently, the vRTC doesn't support UIE ON/OFF */ |
251 | static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
240 | { | 252 | { |
241 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | 253 | struct mrst_rtc *mrst = dev_get_drvdata(dev); |
242 | unsigned long flags; | 254 | unsigned long flags; |
243 | 255 | ||
244 | if (!mrst->irq) | ||
245 | return -ENXIO; | ||
246 | |||
247 | spin_lock_irqsave(&rtc_lock, flags); | 256 | spin_lock_irqsave(&rtc_lock, flags); |
248 | |||
249 | if (enabled) | 257 | if (enabled) |
250 | mrst_irq_enable(mrst, RTC_PIE); | 258 | mrst_irq_enable(mrst, RTC_AIE); |
251 | else | 259 | else |
252 | mrst_irq_disable(mrst, RTC_PIE); | ||
253 | |||
254 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | ||
259 | |||
260 | /* Currently, the vRTC doesn't support UIE ON/OFF */ | ||
261 | static int | ||
262 | mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
263 | { | ||
264 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
265 | unsigned long flags; | ||
266 | |||
267 | switch (cmd) { | ||
268 | case RTC_AIE_OFF: | ||
269 | case RTC_AIE_ON: | ||
270 | if (!mrst->irq) | ||
271 | return -EINVAL; | ||
272 | break; | ||
273 | default: | ||
274 | /* PIE ON/OFF is handled by mrst_irq_set_state() */ | ||
275 | return -ENOIOCTLCMD; | ||
276 | } | ||
277 | |||
278 | spin_lock_irqsave(&rtc_lock, flags); | ||
279 | switch (cmd) { | ||
280 | case RTC_AIE_OFF: /* alarm off */ | ||
281 | mrst_irq_disable(mrst, RTC_AIE); | 260 | mrst_irq_disable(mrst, RTC_AIE); |
282 | break; | ||
283 | case RTC_AIE_ON: /* alarm on */ | ||
284 | mrst_irq_enable(mrst, RTC_AIE); | ||
285 | break; | ||
286 | } | ||
287 | spin_unlock_irqrestore(&rtc_lock, flags); | 261 | spin_unlock_irqrestore(&rtc_lock, flags); |
288 | return 0; | 262 | return 0; |
289 | } | 263 | } |
290 | 264 | ||
291 | #else | ||
292 | #define mrst_rtc_ioctl NULL | ||
293 | #endif | ||
294 | 265 | ||
295 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | 266 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) |
296 | 267 | ||
@@ -317,13 +288,12 @@ static int mrst_procfs(struct device *dev, struct seq_file *seq) | |||
317 | #endif | 288 | #endif |
318 | 289 | ||
319 | static const struct rtc_class_ops mrst_rtc_ops = { | 290 | static const struct rtc_class_ops mrst_rtc_ops = { |
320 | .ioctl = mrst_rtc_ioctl, | ||
321 | .read_time = mrst_read_time, | 291 | .read_time = mrst_read_time, |
322 | .set_time = mrst_set_time, | 292 | .set_time = mrst_set_time, |
323 | .read_alarm = mrst_read_alarm, | 293 | .read_alarm = mrst_read_alarm, |
324 | .set_alarm = mrst_set_alarm, | 294 | .set_alarm = mrst_set_alarm, |
325 | .proc = mrst_procfs, | 295 | .proc = mrst_procfs, |
326 | .irq_set_state = mrst_irq_set_state, | 296 | .alarm_irq_enable = mrst_rtc_alarm_irq_enable, |
327 | }; | 297 | }; |
328 | 298 | ||
329 | static struct mrst_rtc mrst_rtc; | 299 | static struct mrst_rtc mrst_rtc; |
@@ -349,7 +319,7 @@ static irqreturn_t mrst_rtc_irq(int irq, void *p) | |||
349 | return IRQ_NONE; | 319 | return IRQ_NONE; |
350 | } | 320 | } |
351 | 321 | ||
352 | static int __init | 322 | static int __devinit |
353 | vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | 323 | vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) |
354 | { | 324 | { |
355 | int retval = 0; | 325 | int retval = 0; |
@@ -372,6 +342,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
372 | 342 | ||
373 | mrst_rtc.irq = rtc_irq; | 343 | mrst_rtc.irq = rtc_irq; |
374 | mrst_rtc.iomem = iomem; | 344 | mrst_rtc.iomem = iomem; |
345 | mrst_rtc.dev = dev; | ||
346 | dev_set_drvdata(dev, &mrst_rtc); | ||
375 | 347 | ||
376 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, | 348 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, |
377 | &mrst_rtc_ops, THIS_MODULE); | 349 | &mrst_rtc_ops, THIS_MODULE); |
@@ -380,8 +352,6 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
380 | goto cleanup0; | 352 | goto cleanup0; |
381 | } | 353 | } |
382 | 354 | ||
383 | mrst_rtc.dev = dev; | ||
384 | dev_set_drvdata(dev, &mrst_rtc); | ||
385 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); | 355 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); |
386 | 356 | ||
387 | spin_lock_irq(&rtc_lock); | 357 | spin_lock_irq(&rtc_lock); |
@@ -406,9 +376,10 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
406 | return 0; | 376 | return 0; |
407 | 377 | ||
408 | cleanup1: | 378 | cleanup1: |
409 | mrst_rtc.dev = NULL; | ||
410 | rtc_device_unregister(mrst_rtc.rtc); | 379 | rtc_device_unregister(mrst_rtc.rtc); |
411 | cleanup0: | 380 | cleanup0: |
381 | dev_set_drvdata(dev, NULL); | ||
382 | mrst_rtc.dev = NULL; | ||
412 | release_region(iomem->start, iomem->end + 1 - iomem->start); | 383 | release_region(iomem->start, iomem->end + 1 - iomem->start); |
413 | dev_err(dev, "rtc-mrst: unable to initialise\n"); | 384 | dev_err(dev, "rtc-mrst: unable to initialise\n"); |
414 | return retval; | 385 | return retval; |
@@ -421,7 +392,7 @@ static void rtc_mrst_do_shutdown(void) | |||
421 | spin_unlock_irq(&rtc_lock); | 392 | spin_unlock_irq(&rtc_lock); |
422 | } | 393 | } |
423 | 394 | ||
424 | static void __exit rtc_mrst_do_remove(struct device *dev) | 395 | static void __devexit rtc_mrst_do_remove(struct device *dev) |
425 | { | 396 | { |
426 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | 397 | struct mrst_rtc *mrst = dev_get_drvdata(dev); |
427 | struct resource *iomem; | 398 | struct resource *iomem; |
@@ -530,14 +501,14 @@ static inline int mrst_poweroff(struct device *dev) | |||
530 | 501 | ||
531 | #endif | 502 | #endif |
532 | 503 | ||
533 | static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) | 504 | static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev) |
534 | { | 505 | { |
535 | return vrtc_mrst_do_probe(&pdev->dev, | 506 | return vrtc_mrst_do_probe(&pdev->dev, |
536 | platform_get_resource(pdev, IORESOURCE_MEM, 0), | 507 | platform_get_resource(pdev, IORESOURCE_MEM, 0), |
537 | platform_get_irq(pdev, 0)); | 508 | platform_get_irq(pdev, 0)); |
538 | } | 509 | } |
539 | 510 | ||
540 | static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) | 511 | static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev) |
541 | { | 512 | { |
542 | rtc_mrst_do_remove(&pdev->dev); | 513 | rtc_mrst_do_remove(&pdev->dev); |
543 | return 0; | 514 | return 0; |
@@ -555,7 +526,7 @@ MODULE_ALIAS("platform:vrtc_mrst"); | |||
555 | 526 | ||
556 | static struct platform_driver vrtc_mrst_platform_driver = { | 527 | static struct platform_driver vrtc_mrst_platform_driver = { |
557 | .probe = vrtc_mrst_platform_probe, | 528 | .probe = vrtc_mrst_platform_probe, |
558 | .remove = __exit_p(vrtc_mrst_platform_remove), | 529 | .remove = __devexit_p(vrtc_mrst_platform_remove), |
559 | .shutdown = vrtc_mrst_platform_shutdown, | 530 | .shutdown = vrtc_mrst_platform_shutdown, |
560 | .driver = { | 531 | .driver = { |
561 | .name = (char *) driver_name, | 532 | .name = (char *) driver_name, |