diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 19:47:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 19:47:35 -0400 |
commit | 66f03c614c0902ccf7d6160459362a9352f33271 (patch) | |
tree | b9a8864efe5aa7fc5c96cc5ccbeca41f5cd6f6a7 /drivers/rtc/rtc-at91sam9.c | |
parent | 34800598b2eebe061445216473b1e4c2ff5cba99 (diff) | |
parent | cdc3df6f44f72c5924a16a47e1663c3fb0e57820 (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.c | 85 |
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 | */ |
290 | static int __init at91_rtc_probe(struct platform_device *pdev) | 291 | static 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 | ||
358 | fail_register: | 369 | fail_register: |
370 | iounmap(rtc->gpbr); | ||
371 | fail_gpbr: | ||
359 | iounmap(rtc->rtt); | 372 | iounmap(rtc->rtt); |
360 | fail: | 373 | fail: |
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 | */ |
369 | static int __exit at91_rtc_remove(struct platform_device *pdev) | 382 | static 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 | ||
442 | static struct platform_driver at91_rtc_driver = { | 456 | static 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 | */ | ||
458 | static 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); | ||
483 | fail: | ||
484 | return false; | ||
485 | } | ||
486 | |||
487 | static int __init at91_rtc_init(void) | 468 | static 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 | } |
501 | module_init(at91_rtc_init); | 472 | module_init(at91_rtc_init); |
502 | 473 | ||