aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-at91sam9.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 19:47:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 19:47:35 -0400
commit66f03c614c0902ccf7d6160459362a9352f33271 (patch)
treeb9a8864efe5aa7fc5c96cc5ccbeca41f5cd6f6a7 /drivers/rtc/rtc-at91sam9.c
parent34800598b2eebe061445216473b1e4c2ff5cba99 (diff)
parentcdc3df6f44f72c5924a16a47e1663c3fb0e57820 (diff)
Merge tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull "ARM: device tree work" from Arnd Bergmann: "Most of these patches convert code from using static platform data to describing the hardware in the device tree. This is only the first half of the changes for v3.4 because a lot of patches for this topic came in the last week before the merge window. Signed-off-by: Arnd Bergmann <arnd@arndb.de>" Fix up trivial conflicts in arch/arm/mach-vexpress/{Kconfig,core.h} * tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (86 commits) Document: devicetree: add OF documents for arch-mmp ARM: dts: append DTS file of pxa168 ARM: mmp: append OF support on pxa168 ARM: mmp: enable rtc clk in pxa168 i2c: pxa: add OF support serial: pxa: add OF support arm/dts: mt_ventoux: very basic support for TeeJet Mt.Ventoux board ARM: OMAP2+: Remove extra ifdefs for board-generic ARM: OMAP2+: Fix build error when only ARCH_OMAP2/3 or 4 is selected ASoC: DT: Add digital microphone binding to PAZ00 board. ARM: dt: Add ARM PMU to tegra*.dtsi ARM: at91: at91sam9x5cm/dt: add leds support ARM: at91: usb_a9g20/dt: add gpio-keys support ARM: at91: at91sam9m10g45ek/dt: add gpio-keys support ARM: at91: at91sam9m10g45ek/dt: add leds support ARM: at91: usb_a9g20/dt: add leds support ARM: at91/pio: add new PIO3 features ARM: at91: add sam9_smc.o to at91sam9x5 build ARM: at91/tc/clocksource: Add 32 bit variant to Timer Counter ARM: at91/tc: add device tree support to atmel_tclib ...
Diffstat (limited to 'drivers/rtc/rtc-at91sam9.c')
-rw-r--r--drivers/rtc/rtc-at91sam9.c85
1 files changed, 28 insertions, 57 deletions
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 274a0aafe42b..831868904e02 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -57,6 +57,7 @@ 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;
60}; 61};
61 62
62#define rtt_readl(rtc, field) \ 63#define rtt_readl(rtc, field) \
@@ -65,9 +66,9 @@ struct sam9_rtc {
65 __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) 66 __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field)
66 67
67#define gpbr_readl(rtc) \ 68#define gpbr_readl(rtc) \
68 at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR) 69 __raw_readl((rtc)->gpbr)
69#define gpbr_writel(rtc, val) \ 70#define gpbr_writel(rtc, val) \
70 at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val)) 71 __raw_writel((val), (rtc)->gpbr)
71 72
72/* 73/*
73 * Read current time and date in RTC 74 * Read current time and date in RTC
@@ -287,16 +288,19 @@ static const struct rtc_class_ops at91_rtc_ops = {
287/* 288/*
288 * Initialize and install RTC driver 289 * Initialize and install RTC driver
289 */ 290 */
290static int __init at91_rtc_probe(struct platform_device *pdev) 291static int __devinit at91_rtc_probe(struct platform_device *pdev)
291{ 292{
292 struct resource *r; 293 struct resource *r, *r_gpbr;
293 struct sam9_rtc *rtc; 294 struct sam9_rtc *rtc;
294 int ret; 295 int ret;
295 u32 mr; 296 u32 mr;
296 297
297 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 298 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
298 if (!r) 299 r_gpbr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
300 if (!r || !r_gpbr) {
301 dev_err(&pdev->dev, "need 2 ressources\n");
299 return -ENODEV; 302 return -ENODEV;
303 }
300 304
301 rtc = kzalloc(sizeof *rtc, GFP_KERNEL); 305 rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
302 if (!rtc) 306 if (!rtc)
@@ -314,6 +318,13 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
314 goto fail; 318 goto fail;
315 } 319 }
316 320
321 rtc->gpbr = ioremap(r_gpbr->start, resource_size(r_gpbr));
322 if (!rtc->gpbr) {
323 dev_err(&pdev->dev, "failed to map gpbr registers, aborting.\n");
324 ret = -ENOMEM;
325 goto fail_gpbr;
326 }
327
317 mr = rtt_readl(rtc, MR); 328 mr = rtt_readl(rtc, MR);
318 329
319 /* unless RTT is counting at 1 Hz, re-initialize it */ 330 /* unless RTT is counting at 1 Hz, re-initialize it */
@@ -340,7 +351,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
340 if (ret) { 351 if (ret) {
341 dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); 352 dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
342 rtc_device_unregister(rtc->rtcdev); 353 rtc_device_unregister(rtc->rtcdev);
343 goto fail; 354 goto fail_register;
344 } 355 }
345 356
346 /* NOTE: sam9260 rev A silicon has a ROM bug which resets the 357 /* NOTE: sam9260 rev A silicon has a ROM bug which resets the
@@ -356,6 +367,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
356 return 0; 367 return 0;
357 368
358fail_register: 369fail_register:
370 iounmap(rtc->gpbr);
371fail_gpbr:
359 iounmap(rtc->rtt); 372 iounmap(rtc->rtt);
360fail: 373fail:
361 platform_set_drvdata(pdev, NULL); 374 platform_set_drvdata(pdev, NULL);
@@ -366,7 +379,7 @@ fail:
366/* 379/*
367 * Disable and remove the RTC driver 380 * Disable and remove the RTC driver
368 */ 381 */
369static int __exit at91_rtc_remove(struct platform_device *pdev) 382static int __devexit at91_rtc_remove(struct platform_device *pdev)
370{ 383{
371 struct sam9_rtc *rtc = platform_get_drvdata(pdev); 384 struct sam9_rtc *rtc = platform_get_drvdata(pdev);
372 u32 mr = rtt_readl(rtc, MR); 385 u32 mr = rtt_readl(rtc, MR);
@@ -377,6 +390,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
377 390
378 rtc_device_unregister(rtc->rtcdev); 391 rtc_device_unregister(rtc->rtcdev);
379 392
393 iounmap(rtc->gpbr);
380 iounmap(rtc->rtt); 394 iounmap(rtc->rtt);
381 platform_set_drvdata(pdev, NULL); 395 platform_set_drvdata(pdev, NULL);
382 kfree(rtc); 396 kfree(rtc);
@@ -440,63 +454,20 @@ static int at91_rtc_resume(struct platform_device *pdev)
440#endif 454#endif
441 455
442static struct platform_driver at91_rtc_driver = { 456static struct platform_driver at91_rtc_driver = {
443 .driver.name = "rtc-at91sam9", 457 .probe = at91_rtc_probe,
444 .driver.owner = THIS_MODULE, 458 .remove = __devexit_p(at91_rtc_remove),
445 .remove = __exit_p(at91_rtc_remove),
446 .shutdown = at91_rtc_shutdown, 459 .shutdown = at91_rtc_shutdown,
447 .suspend = at91_rtc_suspend, 460 .suspend = at91_rtc_suspend,
448 .resume = at91_rtc_resume, 461 .resume = at91_rtc_resume,
462 .driver = {
463 .name = "rtc-at91sam9",
464 .owner = THIS_MODULE,
465 },
449}; 466};
450 467
451/* Chips can have more than one RTT module, and they can be used for more
452 * than just RTCs. So we can't just register as "the" RTT driver.
453 *
454 * A normal approach in such cases is to create a library to allocate and
455 * free the modules. Here we just use bus_find_device() as like such a
456 * library, binding directly ... no runtime "library" footprint is needed.
457 */
458static int __init at91_rtc_match(struct device *dev, void *v)
459{
460 struct platform_device *pdev = to_platform_device(dev);
461 int ret;
462
463 /* continue searching if this isn't the RTT we need */
464 if (strcmp("at91_rtt", pdev->name) != 0
465 || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT)
466 goto fail;
467
468 /* else we found it ... but fail unless we can bind to the RTC driver */
469 if (dev->driver) {
470 dev_dbg(dev, "busy, can't use as RTC!\n");
471 goto fail;
472 }
473 dev->driver = &at91_rtc_driver.driver;
474 if (device_attach(dev) == 0) {
475 dev_dbg(dev, "can't attach RTC!\n");
476 goto fail;
477 }
478 ret = at91_rtc_probe(pdev);
479 if (ret == 0)
480 return true;
481
482 dev_dbg(dev, "RTC probe err %d!\n", ret);
483fail:
484 return false;
485}
486
487static int __init at91_rtc_init(void) 468static int __init at91_rtc_init(void)
488{ 469{
489 int status; 470 return platform_driver_register(&at91_rtc_driver);
490 struct device *rtc;
491
492 status = platform_driver_register(&at91_rtc_driver);
493 if (status)
494 return status;
495 rtc = bus_find_device(&platform_bus_type, NULL,
496 NULL, at91_rtc_match);
497 if (!rtc)
498 platform_driver_unregister(&at91_rtc_driver);
499 return rtc ? 0 : -ENODEV;
500} 471}
501module_init(at91_rtc_init); 472module_init(at91_rtc_init);
502 473