diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-11-20 07:42:21 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-11-20 07:42:21 -0500 |
commit | c3e6dc65f2ce83dacc0a18104bf44931e7eb8a5d (patch) | |
tree | c2e1420d066463a15d6b28b2dc1588353d88b63c /drivers/rtc | |
parent | 27bc375a9c50f70a9c600a6771cc50ffd5cf8c98 (diff) | |
parent | 2c91e61dc97cce57ffd9dd654a6ee284e1f45a1f (diff) |
Merge tag 'at91-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91 into next/drivers
Pull "First batch of drivers for 3.19" from Nicolas Ferre:
It is only about a not so recent driver for old platforms: RTT as RTC driver:
- RTT as RTC driver enhancements and machine specific include files removal
- RTT as RTC driver conversion to device tree
* tag 'at91-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91:
rtc: at91sam9: add DT bindings documentation
rtc: at91sam9: use clk API instead of relying on AT91_SLOW_CLOCK
ARM: at91: add clk_lookup entry for RTT devices
rtc: at91sam9: rework the Kconfig description
rtc: at91sam9: make use of syscon/regmap to access GPBR registers
rtc: at91sam9: add DT support
rtc: at91sam9: replace devm_ioremap by devm_ioremap_resource
rtc: at91sam9: use standard readl/writel functions instead of raw versions
rtc: at91sam9: remove references to mach specific headers
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 24 | ||||
-rw-r--r-- | drivers/rtc/rtc-at91sam9.c | 138 |
2 files changed, 125 insertions, 37 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6dd12ddbabc6..77eb13cabe6d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -1109,16 +1109,18 @@ config RTC_DRV_AT91RM9200 | |||
1109 | this is powered by the backup power supply. | 1109 | this is powered by the backup power supply. |
1110 | 1110 | ||
1111 | config RTC_DRV_AT91SAM9 | 1111 | config RTC_DRV_AT91SAM9 |
1112 | tristate "AT91SAM9x/AT91CAP9 RTT as RTC" | 1112 | tristate "AT91SAM9 RTT as RTC" |
1113 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | 1113 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) |
1114 | select MFD_SYSCON | ||
1114 | help | 1115 | help |
1115 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT | 1116 | Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which |
1116 | (Real Time Timer). These timers are powered by the backup power | 1117 | can be used as an RTC thanks to the backup power supply (e.g. a |
1117 | supply (such as a small coin cell battery), but do not need to | 1118 | small coin cell battery) which keeps this block and the GPBR |
1118 | be used as RTCs. | 1119 | (General Purpose Backup Registers) block powered when the device |
1119 | 1120 | is shutdown. | |
1120 | (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the | 1121 | Some AT91SAM9 SoCs provide a real RTC block, on those ones you'd |
1121 | dedicated RTC module and leave the RTT available for other uses.) | 1122 | probably want to use the real RTC block instead of the "RTT as an |
1123 | RTC" driver. | ||
1122 | 1124 | ||
1123 | config RTC_DRV_AT91SAM9_RTT | 1125 | config RTC_DRV_AT91SAM9_RTT |
1124 | int | 1126 | int |
@@ -1127,6 +1129,9 @@ config RTC_DRV_AT91SAM9_RTT | |||
1127 | prompt "RTT module Number" if ARCH_AT91SAM9263 | 1129 | prompt "RTT module Number" if ARCH_AT91SAM9263 |
1128 | depends on RTC_DRV_AT91SAM9 | 1130 | depends on RTC_DRV_AT91SAM9 |
1129 | help | 1131 | help |
1132 | This option is only relevant for legacy board support and | ||
1133 | won't be used when booting a DT board. | ||
1134 | |||
1130 | More than one RTT module is available. You can choose which | 1135 | More than one RTT module is available. You can choose which |
1131 | one will be used as an RTC. The default of zero is normally | 1136 | one will be used as an RTC. The default of zero is normally |
1132 | OK to use, though some systems use that for non-RTC purposes. | 1137 | OK to use, though some systems use that for non-RTC purposes. |
@@ -1139,6 +1144,9 @@ config RTC_DRV_AT91SAM9_GPBR | |||
1139 | prompt "Backup Register Number" | 1144 | prompt "Backup Register Number" |
1140 | depends on RTC_DRV_AT91SAM9 | 1145 | depends on RTC_DRV_AT91SAM9 |
1141 | help | 1146 | help |
1147 | This option is only relevant for legacy board support and | ||
1148 | won't be used when booting a DT board. | ||
1149 | |||
1142 | The RTC driver needs to use one of the General Purpose Backup | 1150 | The RTC driver needs to use one of the General Purpose Backup |
1143 | Registers (GPBRs) as well as the RTT. You can choose which one | 1151 | Registers (GPBRs) as well as the RTT. You can choose which one |
1144 | will be used. The default of zero is normally OK to use, but | 1152 | will be used. The default of zero is normally OK to use, but |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 596374304532..abac38abd38e 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -21,10 +21,9 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/platform_data/atmel.h> | 22 | #include <linux/platform_data/atmel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/mfd/syscon.h> | |
25 | #include <mach/at91_rtt.h> | 25 | #include <linux/regmap.h> |
26 | #include <mach/cpu.h> | 26 | #include <linux/clk.h> |
27 | #include <mach/hardware.h> | ||
28 | 27 | ||
29 | /* | 28 | /* |
30 | * This driver uses two configurable hardware resources that live in the | 29 | * This driver uses two configurable hardware resources that live in the |
@@ -47,6 +46,22 @@ | |||
47 | * registers available, likewise usable for more than "RTC" support. | 46 | * registers available, likewise usable for more than "RTC" support. |
48 | */ | 47 | */ |
49 | 48 | ||
49 | #define AT91_RTT_MR 0x00 /* Real-time Mode Register */ | ||
50 | #define AT91_RTT_RTPRES (0xffff << 0) /* Real-time Timer Prescaler Value */ | ||
51 | #define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ | ||
52 | #define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ | ||
53 | #define AT91_RTT_RTTRST (1 << 18) /* Real Time Timer Restart */ | ||
54 | |||
55 | #define AT91_RTT_AR 0x04 /* Real-time Alarm Register */ | ||
56 | #define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */ | ||
57 | |||
58 | #define AT91_RTT_VR 0x08 /* Real-time Value Register */ | ||
59 | #define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */ | ||
60 | |||
61 | #define AT91_RTT_SR 0x0c /* Real-time Status Register */ | ||
62 | #define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ | ||
63 | #define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ | ||
64 | |||
50 | /* | 65 | /* |
51 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. | 66 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. |
52 | * It's also the reset value for that field. | 67 | * It's also the reset value for that field. |
@@ -58,19 +73,30 @@ struct sam9_rtc { | |||
58 | void __iomem *rtt; | 73 | void __iomem *rtt; |
59 | struct rtc_device *rtcdev; | 74 | struct rtc_device *rtcdev; |
60 | u32 imr; | 75 | u32 imr; |
61 | void __iomem *gpbr; | 76 | struct regmap *gpbr; |
77 | unsigned int gpbr_offset; | ||
62 | int irq; | 78 | int irq; |
79 | struct clk *sclk; | ||
63 | }; | 80 | }; |
64 | 81 | ||
65 | #define rtt_readl(rtc, field) \ | 82 | #define rtt_readl(rtc, field) \ |
66 | __raw_readl((rtc)->rtt + AT91_RTT_ ## field) | 83 | readl((rtc)->rtt + AT91_RTT_ ## field) |
67 | #define rtt_writel(rtc, field, val) \ | 84 | #define rtt_writel(rtc, field, val) \ |
68 | __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) | 85 | writel((val), (rtc)->rtt + AT91_RTT_ ## field) |
86 | |||
87 | static inline unsigned int gpbr_readl(struct sam9_rtc *rtc) | ||
88 | { | ||
89 | unsigned int val; | ||
90 | |||
91 | regmap_read(rtc->gpbr, rtc->gpbr_offset, &val); | ||
69 | 92 | ||
70 | #define gpbr_readl(rtc) \ | 93 | return val; |
71 | __raw_readl((rtc)->gpbr) | 94 | } |
72 | #define gpbr_writel(rtc, val) \ | 95 | |
73 | __raw_writel((val), (rtc)->gpbr) | 96 | static inline void gpbr_writel(struct sam9_rtc *rtc, unsigned int val) |
97 | { | ||
98 | regmap_write(rtc->gpbr, rtc->gpbr_offset, val); | ||
99 | } | ||
74 | 100 | ||
75 | /* | 101 | /* |
76 | * Read current time and date in RTC | 102 | * Read current time and date in RTC |
@@ -287,22 +313,22 @@ static const struct rtc_class_ops at91_rtc_ops = { | |||
287 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, | 313 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, |
288 | }; | 314 | }; |
289 | 315 | ||
316 | static struct regmap_config gpbr_regmap_config = { | ||
317 | .reg_bits = 32, | ||
318 | .val_bits = 32, | ||
319 | .reg_stride = 4, | ||
320 | }; | ||
321 | |||
290 | /* | 322 | /* |
291 | * Initialize and install RTC driver | 323 | * Initialize and install RTC driver |
292 | */ | 324 | */ |
293 | static int at91_rtc_probe(struct platform_device *pdev) | 325 | static int at91_rtc_probe(struct platform_device *pdev) |
294 | { | 326 | { |
295 | struct resource *r, *r_gpbr; | 327 | struct resource *r; |
296 | struct sam9_rtc *rtc; | 328 | struct sam9_rtc *rtc; |
297 | int ret, irq; | 329 | int ret, irq; |
298 | u32 mr; | 330 | u32 mr; |
299 | 331 | unsigned int sclk_rate; | |
300 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
301 | r_gpbr = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
302 | if (!r || !r_gpbr) { | ||
303 | dev_err(&pdev->dev, "need 2 ressources\n"); | ||
304 | return -ENODEV; | ||
305 | } | ||
306 | 332 | ||
307 | irq = platform_get_irq(pdev, 0); | 333 | irq = platform_get_irq(pdev, 0); |
308 | if (irq < 0) { | 334 | if (irq < 0) { |
@@ -321,24 +347,66 @@ static int at91_rtc_probe(struct platform_device *pdev) | |||
321 | device_init_wakeup(&pdev->dev, 1); | 347 | device_init_wakeup(&pdev->dev, 1); |
322 | 348 | ||
323 | platform_set_drvdata(pdev, rtc); | 349 | platform_set_drvdata(pdev, rtc); |
324 | rtc->rtt = devm_ioremap(&pdev->dev, r->start, resource_size(r)); | 350 | |
325 | if (!rtc->rtt) { | 351 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
326 | dev_err(&pdev->dev, "failed to map registers, aborting.\n"); | 352 | rtc->rtt = devm_ioremap_resource(&pdev->dev, r); |
327 | return -ENOMEM; | 353 | if (IS_ERR(rtc->rtt)) |
354 | return PTR_ERR(rtc->rtt); | ||
355 | |||
356 | if (!pdev->dev.of_node) { | ||
357 | /* | ||
358 | * TODO: Remove this code chunk when removing non DT board | ||
359 | * support. Remember to remove the gpbr_regmap_config | ||
360 | * variable too. | ||
361 | */ | ||
362 | void __iomem *gpbr; | ||
363 | |||
364 | r = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
365 | gpbr = devm_ioremap_resource(&pdev->dev, r); | ||
366 | if (IS_ERR(gpbr)) | ||
367 | return PTR_ERR(gpbr); | ||
368 | |||
369 | rtc->gpbr = regmap_init_mmio(NULL, gpbr, | ||
370 | &gpbr_regmap_config); | ||
371 | } else { | ||
372 | struct of_phandle_args args; | ||
373 | |||
374 | ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, | ||
375 | "atmel,rtt-rtc-time-reg", 1, 0, | ||
376 | &args); | ||
377 | if (ret) | ||
378 | return ret; | ||
379 | |||
380 | rtc->gpbr = syscon_node_to_regmap(args.np); | ||
381 | rtc->gpbr_offset = args.args[0]; | ||
328 | } | 382 | } |
329 | 383 | ||
330 | rtc->gpbr = devm_ioremap(&pdev->dev, r_gpbr->start, | 384 | if (IS_ERR(rtc->gpbr)) { |
331 | resource_size(r_gpbr)); | 385 | dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n"); |
332 | if (!rtc->gpbr) { | ||
333 | dev_err(&pdev->dev, "failed to map gpbr registers, aborting.\n"); | ||
334 | return -ENOMEM; | 386 | return -ENOMEM; |
335 | } | 387 | } |
336 | 388 | ||
389 | rtc->sclk = devm_clk_get(&pdev->dev, NULL); | ||
390 | if (IS_ERR(rtc->sclk)) | ||
391 | return PTR_ERR(rtc->sclk); | ||
392 | |||
393 | sclk_rate = clk_get_rate(rtc->sclk); | ||
394 | if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) { | ||
395 | dev_err(&pdev->dev, "Invalid slow clock rate\n"); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | ret = clk_prepare_enable(rtc->sclk); | ||
400 | if (ret) { | ||
401 | dev_err(&pdev->dev, "Could not enable slow clock\n"); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
337 | mr = rtt_readl(rtc, MR); | 405 | mr = rtt_readl(rtc, MR); |
338 | 406 | ||
339 | /* unless RTT is counting at 1 Hz, re-initialize it */ | 407 | /* unless RTT is counting at 1 Hz, re-initialize it */ |
340 | if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { | 408 | if ((mr & AT91_RTT_RTPRES) != sclk_rate) { |
341 | mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); | 409 | mr = AT91_RTT_RTTRST | (sclk_rate & AT91_RTT_RTPRES); |
342 | gpbr_writel(rtc, 0); | 410 | gpbr_writel(rtc, 0); |
343 | } | 411 | } |
344 | 412 | ||
@@ -383,6 +451,9 @@ static int at91_rtc_remove(struct platform_device *pdev) | |||
383 | /* disable all interrupts */ | 451 | /* disable all interrupts */ |
384 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | 452 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); |
385 | 453 | ||
454 | if (!IS_ERR(rtc->sclk)) | ||
455 | clk_disable_unprepare(rtc->sclk); | ||
456 | |||
386 | return 0; | 457 | return 0; |
387 | } | 458 | } |
388 | 459 | ||
@@ -440,6 +511,14 @@ static int at91_rtc_resume(struct device *dev) | |||
440 | 511 | ||
441 | static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); | 512 | static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); |
442 | 513 | ||
514 | #ifdef CONFIG_OF | ||
515 | static const struct of_device_id at91_rtc_dt_ids[] = { | ||
516 | { .compatible = "atmel,at91sam9260-rtt" }, | ||
517 | { /* sentinel */ } | ||
518 | }; | ||
519 | MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids); | ||
520 | #endif | ||
521 | |||
443 | static struct platform_driver at91_rtc_driver = { | 522 | static struct platform_driver at91_rtc_driver = { |
444 | .probe = at91_rtc_probe, | 523 | .probe = at91_rtc_probe, |
445 | .remove = at91_rtc_remove, | 524 | .remove = at91_rtc_remove, |
@@ -448,6 +527,7 @@ static struct platform_driver at91_rtc_driver = { | |||
448 | .name = "rtc-at91sam9", | 527 | .name = "rtc-at91sam9", |
449 | .owner = THIS_MODULE, | 528 | .owner = THIS_MODULE, |
450 | .pm = &at91_rtc_pm_ops, | 529 | .pm = &at91_rtc_pm_ops, |
530 | .of_match_table = of_match_ptr(at91_rtc_dt_ids), | ||
451 | }, | 531 | }, |
452 | }; | 532 | }; |
453 | 533 | ||