aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-at91sam9.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-at91sam9.c')
-rw-r--r--drivers/rtc/rtc-at91sam9.c133
1 files changed, 79 insertions, 54 deletions
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 39cfd2ee004..a3ad957507d 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -19,8 +19,8 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/ioctl.h> 20#include <linux/ioctl.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/platform_data/atmel.h>
23 22
23#include <mach/board.h>
24#include <mach/at91_rtt.h> 24#include <mach/at91_rtt.h>
25#include <mach/cpu.h> 25#include <mach/cpu.h>
26 26
@@ -57,8 +57,6 @@ struct sam9_rtc {
57 void __iomem *rtt; 57 void __iomem *rtt;
58 struct rtc_device *rtcdev; 58 struct rtc_device *rtcdev;
59 u32 imr; 59 u32 imr;
60 void __iomem *gpbr;
61 int irq;
62}; 60};
63 61
64#define rtt_readl(rtc, field) \ 62#define rtt_readl(rtc, field) \
@@ -67,9 +65,9 @@ struct sam9_rtc {
67 __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) 65 __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field)
68 66
69#define gpbr_readl(rtc) \ 67#define gpbr_readl(rtc) \
70 __raw_readl((rtc)->gpbr) 68 at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR)
71#define gpbr_writel(rtc, val) \ 69#define gpbr_writel(rtc, val) \
72 __raw_writel((val), (rtc)->gpbr) 70 at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val))
73 71
74/* 72/*
75 * Read current time and date in RTC 73 * Read current time and date in RTC
@@ -289,50 +287,28 @@ static const struct rtc_class_ops at91_rtc_ops = {
289/* 287/*
290 * Initialize and install RTC driver 288 * Initialize and install RTC driver
291 */ 289 */
292static int at91_rtc_probe(struct platform_device *pdev) 290static int __init at91_rtc_probe(struct platform_device *pdev)
293{ 291{
294 struct resource *r, *r_gpbr; 292 struct resource *r;
295 struct sam9_rtc *rtc; 293 struct sam9_rtc *rtc;
296 int ret, irq; 294 int ret;
297 u32 mr; 295 u32 mr;
298 296
299 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 297 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
300 r_gpbr = platform_get_resource(pdev, IORESOURCE_MEM, 1); 298 if (!r)
301 if (!r || !r_gpbr) {
302 dev_err(&pdev->dev, "need 2 ressources\n");
303 return -ENODEV; 299 return -ENODEV;
304 }
305
306 irq = platform_get_irq(pdev, 0);
307 if (irq < 0) {
308 dev_err(&pdev->dev, "failed to get interrupt resource\n");
309 return irq;
310 }
311 300
312 rtc = kzalloc(sizeof *rtc, GFP_KERNEL); 301 rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
313 if (!rtc) 302 if (!rtc)
314 return -ENOMEM; 303 return -ENOMEM;
315 304
316 rtc->irq = irq;
317
318 /* platform setup code should have handled this; sigh */ 305 /* platform setup code should have handled this; sigh */
319 if (!device_can_wakeup(&pdev->dev)) 306 if (!device_can_wakeup(&pdev->dev))
320 device_init_wakeup(&pdev->dev, 1); 307 device_init_wakeup(&pdev->dev, 1);
321 308
322 platform_set_drvdata(pdev, rtc); 309 platform_set_drvdata(pdev, rtc);
323 rtc->rtt = ioremap(r->start, resource_size(r)); 310 rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
324 if (!rtc->rtt) { 311 rtc->rtt += r->start;
325 dev_err(&pdev->dev, "failed to map registers, aborting.\n");
326 ret = -ENOMEM;
327 goto fail;
328 }
329
330 rtc->gpbr = ioremap(r_gpbr->start, resource_size(r_gpbr));
331 if (!rtc->gpbr) {
332 dev_err(&pdev->dev, "failed to map gpbr registers, aborting.\n");
333 ret = -ENOMEM;
334 goto fail_gpbr;
335 }
336 312
337 mr = rtt_readl(rtc, MR); 313 mr = rtt_readl(rtc, MR);
338 314
@@ -350,16 +326,17 @@ static int at91_rtc_probe(struct platform_device *pdev)
350 &at91_rtc_ops, THIS_MODULE); 326 &at91_rtc_ops, THIS_MODULE);
351 if (IS_ERR(rtc->rtcdev)) { 327 if (IS_ERR(rtc->rtcdev)) {
352 ret = PTR_ERR(rtc->rtcdev); 328 ret = PTR_ERR(rtc->rtcdev);
353 goto fail_register; 329 goto fail;
354 } 330 }
355 331
356 /* register irq handler after we know what name we'll use */ 332 /* register irq handler after we know what name we'll use */
357 ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED, 333 ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
334 IRQF_DISABLED | IRQF_SHARED,
358 dev_name(&rtc->rtcdev->dev), rtc); 335 dev_name(&rtc->rtcdev->dev), rtc);
359 if (ret) { 336 if (ret) {
360 dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq); 337 dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
361 rtc_device_unregister(rtc->rtcdev); 338 rtc_device_unregister(rtc->rtcdev);
362 goto fail_register; 339 goto fail;
363 } 340 }
364 341
365 /* NOTE: sam9260 rev A silicon has a ROM bug which resets the 342 /* NOTE: sam9260 rev A silicon has a ROM bug which resets the
@@ -374,10 +351,6 @@ static int at91_rtc_probe(struct platform_device *pdev)
374 351
375 return 0; 352 return 0;
376 353
377fail_register:
378 iounmap(rtc->gpbr);
379fail_gpbr:
380 iounmap(rtc->rtt);
381fail: 354fail:
382 platform_set_drvdata(pdev, NULL); 355 platform_set_drvdata(pdev, NULL);
383 kfree(rtc); 356 kfree(rtc);
@@ -387,19 +360,17 @@ fail:
387/* 360/*
388 * Disable and remove the RTC driver 361 * Disable and remove the RTC driver
389 */ 362 */
390static int at91_rtc_remove(struct platform_device *pdev) 363static int __exit at91_rtc_remove(struct platform_device *pdev)
391{ 364{
392 struct sam9_rtc *rtc = platform_get_drvdata(pdev); 365 struct sam9_rtc *rtc = platform_get_drvdata(pdev);
393 u32 mr = rtt_readl(rtc, MR); 366 u32 mr = rtt_readl(rtc, MR);
394 367
395 /* disable all interrupts */ 368 /* disable all interrupts */
396 rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); 369 rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
397 free_irq(rtc->irq, rtc); 370 free_irq(AT91_ID_SYS, rtc);
398 371
399 rtc_device_unregister(rtc->rtcdev); 372 rtc_device_unregister(rtc->rtcdev);
400 373
401 iounmap(rtc->gpbr);
402 iounmap(rtc->rtt);
403 platform_set_drvdata(pdev, NULL); 374 platform_set_drvdata(pdev, NULL);
404 kfree(rtc); 375 kfree(rtc);
405 return 0; 376 return 0;
@@ -431,7 +402,7 @@ static int at91_rtc_suspend(struct platform_device *pdev,
431 rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); 402 rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
432 if (rtc->imr) { 403 if (rtc->imr) {
433 if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { 404 if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
434 enable_irq_wake(rtc->irq); 405 enable_irq_wake(AT91_ID_SYS);
435 /* don't let RTTINC cause wakeups */ 406 /* don't let RTTINC cause wakeups */
436 if (mr & AT91_RTT_RTTINCIEN) 407 if (mr & AT91_RTT_RTTINCIEN)
437 rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); 408 rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
@@ -449,7 +420,7 @@ static int at91_rtc_resume(struct platform_device *pdev)
449 420
450 if (rtc->imr) { 421 if (rtc->imr) {
451 if (device_may_wakeup(&pdev->dev)) 422 if (device_may_wakeup(&pdev->dev))
452 disable_irq_wake(rtc->irq); 423 disable_irq_wake(AT91_ID_SYS);
453 mr = rtt_readl(rtc, MR); 424 mr = rtt_readl(rtc, MR);
454 rtt_writel(rtc, MR, mr | rtc->imr); 425 rtt_writel(rtc, MR, mr | rtc->imr);
455 } 426 }
@@ -462,18 +433,72 @@ static int at91_rtc_resume(struct platform_device *pdev)
462#endif 433#endif
463 434
464static struct platform_driver at91_rtc_driver = { 435static struct platform_driver at91_rtc_driver = {
465 .probe = at91_rtc_probe, 436 .driver.name = "rtc-at91sam9",
466 .remove = at91_rtc_remove, 437 .driver.owner = THIS_MODULE,
438 .remove = __exit_p(at91_rtc_remove),
467 .shutdown = at91_rtc_shutdown, 439 .shutdown = at91_rtc_shutdown,
468 .suspend = at91_rtc_suspend, 440 .suspend = at91_rtc_suspend,
469 .resume = at91_rtc_resume, 441 .resume = at91_rtc_resume,
470 .driver = {
471 .name = "rtc-at91sam9",
472 .owner = THIS_MODULE,
473 },
474}; 442};
475 443
476module_platform_driver(at91_rtc_driver); 444/* Chips can have more than one RTT module, and they can be used for more
445 * than just RTCs. So we can't just register as "the" RTT driver.
446 *
447 * A normal approach in such cases is to create a library to allocate and
448 * free the modules. Here we just use bus_find_device() as like such a
449 * library, binding directly ... no runtime "library" footprint is needed.
450 */
451static int __init at91_rtc_match(struct device *dev, void *v)
452{
453 struct platform_device *pdev = to_platform_device(dev);
454 int ret;
455
456 /* continue searching if this isn't the RTT we need */
457 if (strcmp("at91_rtt", pdev->name) != 0
458 || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT)
459 goto fail;
460
461 /* else we found it ... but fail unless we can bind to the RTC driver */
462 if (dev->driver) {
463 dev_dbg(dev, "busy, can't use as RTC!\n");
464 goto fail;
465 }
466 dev->driver = &at91_rtc_driver.driver;
467 if (device_attach(dev) == 0) {
468 dev_dbg(dev, "can't attach RTC!\n");
469 goto fail;
470 }
471 ret = at91_rtc_probe(pdev);
472 if (ret == 0)
473 return true;
474
475 dev_dbg(dev, "RTC probe err %d!\n", ret);
476fail:
477 return false;
478}
479
480static int __init at91_rtc_init(void)
481{
482 int status;
483 struct device *rtc;
484
485 status = platform_driver_register(&at91_rtc_driver);
486 if (status)
487 return status;
488 rtc = bus_find_device(&platform_bus_type, NULL,
489 NULL, at91_rtc_match);
490 if (!rtc)
491 platform_driver_unregister(&at91_rtc_driver);
492 return rtc ? 0 : -ENODEV;
493}
494module_init(at91_rtc_init);
495
496static void __exit at91_rtc_exit(void)
497{
498 platform_driver_unregister(&at91_rtc_driver);
499}
500module_exit(at91_rtc_exit);
501
477 502
478MODULE_AUTHOR("Michel Benoit"); 503MODULE_AUTHOR("Michel Benoit");
479MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); 504MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x");