diff options
Diffstat (limited to 'drivers/rtc/rtc-at91sam9.c')
-rw-r--r-- | drivers/rtc/rtc-at91sam9.c | 108 |
1 files changed, 36 insertions, 72 deletions
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 1d31c0ae6334..4daf3789b978 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -1,14 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
1 | /* | 2 | /* |
2 | * "RTT as Real Time Clock" driver for AT91SAM9 SoC family | 3 | * "RTT as Real Time Clock" driver for AT91SAM9 SoC family |
3 | * | 4 | * |
4 | * (C) 2007 Michel Benoit | 5 | * (C) 2007 Michel Benoit |
5 | * | 6 | * |
6 | * Based on rtc-at91rm9200.c by Rick Bronson | 7 | * Based on rtc-at91rm9200.c by Rick Bronson |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | 8 | */ |
13 | 9 | ||
14 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
@@ -47,21 +43,21 @@ | |||
47 | * registers available, likewise usable for more than "RTC" support. | 43 | * registers available, likewise usable for more than "RTC" support. |
48 | */ | 44 | */ |
49 | 45 | ||
50 | #define AT91_RTT_MR 0x00 /* Real-time Mode Register */ | 46 | #define AT91_RTT_MR 0x00 /* Real-time Mode Register */ |
51 | #define AT91_RTT_RTPRES (0xffff << 0) /* Real-time Timer Prescaler Value */ | 47 | #define AT91_RTT_RTPRES (0xffff << 0) /* Timer Prescaler Value */ |
52 | #define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ | 48 | #define AT91_RTT_ALMIEN BIT(16) /* Alarm Interrupt Enable */ |
53 | #define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ | 49 | #define AT91_RTT_RTTINCIEN BIT(17) /* Increment Interrupt Enable */ |
54 | #define AT91_RTT_RTTRST (1 << 18) /* Real Time Timer Restart */ | 50 | #define AT91_RTT_RTTRST BIT(18) /* Timer Restart */ |
55 | 51 | ||
56 | #define AT91_RTT_AR 0x04 /* Real-time Alarm Register */ | 52 | #define AT91_RTT_AR 0x04 /* Real-time Alarm Register */ |
57 | #define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */ | 53 | #define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */ |
58 | 54 | ||
59 | #define AT91_RTT_VR 0x08 /* Real-time Value Register */ | 55 | #define AT91_RTT_VR 0x08 /* Real-time Value Register */ |
60 | #define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */ | 56 | #define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */ |
61 | 57 | ||
62 | #define AT91_RTT_SR 0x0c /* Real-time Status Register */ | 58 | #define AT91_RTT_SR 0x0c /* Real-time Status Register */ |
63 | #define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ | 59 | #define AT91_RTT_ALMS BIT(0) /* Alarm Status */ |
64 | #define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ | 60 | #define AT91_RTT_RTTINC BIT(1) /* Timer Increment */ |
65 | 61 | ||
66 | /* | 62 | /* |
67 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. | 63 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. |
@@ -69,14 +65,13 @@ | |||
69 | */ | 65 | */ |
70 | #define ALARM_DISABLED ((u32)~0) | 66 | #define ALARM_DISABLED ((u32)~0) |
71 | 67 | ||
72 | |||
73 | struct sam9_rtc { | 68 | struct sam9_rtc { |
74 | void __iomem *rtt; | 69 | void __iomem *rtt; |
75 | struct rtc_device *rtcdev; | 70 | struct rtc_device *rtcdev; |
76 | u32 imr; | 71 | u32 imr; |
77 | struct regmap *gpbr; | 72 | struct regmap *gpbr; |
78 | unsigned int gpbr_offset; | 73 | unsigned int gpbr_offset; |
79 | int irq; | 74 | int irq; |
80 | struct clk *sclk; | 75 | struct clk *sclk; |
81 | bool suspended; | 76 | bool suspended; |
82 | unsigned long events; | 77 | unsigned long events; |
@@ -122,7 +117,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | |||
122 | if (secs != secs2) | 117 | if (secs != secs2) |
123 | secs = rtt_readl(rtc, VR); | 118 | secs = rtt_readl(rtc, VR); |
124 | 119 | ||
125 | rtc_time_to_tm(offset + secs, tm); | 120 | rtc_time64_to_tm(offset + secs, tm); |
126 | 121 | ||
127 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); | 122 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); |
128 | 123 | ||
@@ -135,15 +130,12 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | |||
135 | static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | 130 | static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) |
136 | { | 131 | { |
137 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | 132 | struct sam9_rtc *rtc = dev_get_drvdata(dev); |
138 | int err; | ||
139 | u32 offset, alarm, mr; | 133 | u32 offset, alarm, mr; |
140 | unsigned long secs; | 134 | unsigned long secs; |
141 | 135 | ||
142 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); | 136 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); |
143 | 137 | ||
144 | err = rtc_tm_to_time(tm, &secs); | 138 | secs = rtc_tm_to_time64(tm); |
145 | if (err != 0) | ||
146 | return err; | ||
147 | 139 | ||
148 | mr = rtt_readl(rtc, MR); | 140 | mr = rtt_readl(rtc, MR); |
149 | 141 | ||
@@ -193,7 +185,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
193 | 185 | ||
194 | memset(alrm, 0, sizeof(*alrm)); | 186 | memset(alrm, 0, sizeof(*alrm)); |
195 | if (alarm != ALARM_DISABLED && offset != 0) { | 187 | if (alarm != ALARM_DISABLED && offset != 0) { |
196 | rtc_time_to_tm(offset + alarm, tm); | 188 | rtc_time64_to_tm(offset + alarm, tm); |
197 | 189 | ||
198 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); | 190 | dev_dbg(dev, "%s: %ptR\n", __func__, tm); |
199 | 191 | ||
@@ -211,11 +203,8 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
211 | unsigned long secs; | 203 | unsigned long secs; |
212 | u32 offset; | 204 | u32 offset; |
213 | u32 mr; | 205 | u32 mr; |
214 | int err; | ||
215 | 206 | ||
216 | err = rtc_tm_to_time(tm, &secs); | 207 | secs = rtc_tm_to_time64(tm); |
217 | if (err != 0) | ||
218 | return err; | ||
219 | 208 | ||
220 | offset = gpbr_readl(rtc); | 209 | offset = gpbr_readl(rtc); |
221 | if (offset == 0) { | 210 | if (offset == 0) { |
@@ -263,7 +252,7 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | |||
263 | u32 mr = rtt_readl(rtc, MR); | 252 | u32 mr = rtt_readl(rtc, MR); |
264 | 253 | ||
265 | seq_printf(seq, "update_IRQ\t: %s\n", | 254 | seq_printf(seq, "update_IRQ\t: %s\n", |
266 | (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); | 255 | (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); |
267 | return 0; | 256 | return 0; |
268 | } | 257 | } |
269 | 258 | ||
@@ -299,7 +288,7 @@ static void at91_rtc_flush_events(struct sam9_rtc *rtc) | |||
299 | rtc->events = 0; | 288 | rtc->events = 0; |
300 | 289 | ||
301 | pr_debug("%s: num=%ld, events=0x%02lx\n", __func__, | 290 | pr_debug("%s: num=%ld, events=0x%02lx\n", __func__, |
302 | rtc->events >> 8, rtc->events & 0x000000FF); | 291 | rtc->events >> 8, rtc->events & 0x000000FF); |
303 | } | 292 | } |
304 | 293 | ||
305 | /* | 294 | /* |
@@ -340,13 +329,6 @@ static const struct rtc_class_ops at91_rtc_ops = { | |||
340 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, | 329 | .alarm_irq_enable = at91_rtc_alarm_irq_enable, |
341 | }; | 330 | }; |
342 | 331 | ||
343 | static const struct regmap_config gpbr_regmap_config = { | ||
344 | .name = "gpbr", | ||
345 | .reg_bits = 32, | ||
346 | .val_bits = 32, | ||
347 | .reg_stride = 4, | ||
348 | }; | ||
349 | |||
350 | /* | 332 | /* |
351 | * Initialize and install RTC driver | 333 | * Initialize and install RTC driver |
352 | */ | 334 | */ |
@@ -357,6 +339,7 @@ static int at91_rtc_probe(struct platform_device *pdev) | |||
357 | int ret, irq; | 339 | int ret, irq; |
358 | u32 mr; | 340 | u32 mr; |
359 | unsigned int sclk_rate; | 341 | unsigned int sclk_rate; |
342 | struct of_phandle_args args; | ||
360 | 343 | ||
361 | irq = platform_get_irq(pdev, 0); | 344 | irq = platform_get_irq(pdev, 0); |
362 | if (irq < 0) { | 345 | if (irq < 0) { |
@@ -382,34 +365,14 @@ static int at91_rtc_probe(struct platform_device *pdev) | |||
382 | if (IS_ERR(rtc->rtt)) | 365 | if (IS_ERR(rtc->rtt)) |
383 | return PTR_ERR(rtc->rtt); | 366 | return PTR_ERR(rtc->rtt); |
384 | 367 | ||
385 | if (!pdev->dev.of_node) { | 368 | ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, |
386 | /* | 369 | "atmel,rtt-rtc-time-reg", 1, 0, |
387 | * TODO: Remove this code chunk when removing non DT board | 370 | &args); |
388 | * support. Remember to remove the gpbr_regmap_config | 371 | if (ret) |
389 | * variable too. | 372 | return ret; |
390 | */ | ||
391 | void __iomem *gpbr; | ||
392 | |||
393 | r = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
394 | gpbr = devm_ioremap_resource(&pdev->dev, r); | ||
395 | if (IS_ERR(gpbr)) | ||
396 | return PTR_ERR(gpbr); | ||
397 | |||
398 | rtc->gpbr = regmap_init_mmio(NULL, gpbr, | ||
399 | &gpbr_regmap_config); | ||
400 | } else { | ||
401 | struct of_phandle_args args; | ||
402 | |||
403 | ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, | ||
404 | "atmel,rtt-rtc-time-reg", 1, 0, | ||
405 | &args); | ||
406 | if (ret) | ||
407 | return ret; | ||
408 | |||
409 | rtc->gpbr = syscon_node_to_regmap(args.np); | ||
410 | rtc->gpbr_offset = args.args[0]; | ||
411 | } | ||
412 | 373 | ||
374 | rtc->gpbr = syscon_node_to_regmap(args.np); | ||
375 | rtc->gpbr_offset = args.args[0]; | ||
413 | if (IS_ERR(rtc->gpbr)) { | 376 | if (IS_ERR(rtc->gpbr)) { |
414 | dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n"); | 377 | dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n"); |
415 | return -ENOMEM; | 378 | return -ENOMEM; |
@@ -444,13 +407,15 @@ static int at91_rtc_probe(struct platform_device *pdev) | |||
444 | mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | 407 | mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); |
445 | rtt_writel(rtc, MR, mr); | 408 | rtt_writel(rtc, MR, mr); |
446 | 409 | ||
447 | rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name, | 410 | rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev); |
448 | &at91_rtc_ops, THIS_MODULE); | ||
449 | if (IS_ERR(rtc->rtcdev)) { | 411 | if (IS_ERR(rtc->rtcdev)) { |
450 | ret = PTR_ERR(rtc->rtcdev); | 412 | ret = PTR_ERR(rtc->rtcdev); |
451 | goto err_clk; | 413 | goto err_clk; |
452 | } | 414 | } |
453 | 415 | ||
416 | rtc->rtcdev->ops = &at91_rtc_ops; | ||
417 | rtc->rtcdev->range_max = U32_MAX; | ||
418 | |||
454 | /* register irq handler after we know what name we'll use */ | 419 | /* register irq handler after we know what name we'll use */ |
455 | ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt, | 420 | ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt, |
456 | IRQF_SHARED | IRQF_COND_SUSPEND, | 421 | IRQF_SHARED | IRQF_COND_SUSPEND, |
@@ -468,9 +433,9 @@ static int at91_rtc_probe(struct platform_device *pdev) | |||
468 | 433 | ||
469 | if (gpbr_readl(rtc) == 0) | 434 | if (gpbr_readl(rtc) == 0) |
470 | dev_warn(&pdev->dev, "%s: SET TIME!\n", | 435 | dev_warn(&pdev->dev, "%s: SET TIME!\n", |
471 | dev_name(&rtc->rtcdev->dev)); | 436 | dev_name(&rtc->rtcdev->dev)); |
472 | 437 | ||
473 | return 0; | 438 | return rtc_register_device(rtc->rtcdev); |
474 | 439 | ||
475 | err_clk: | 440 | err_clk: |
476 | clk_disable_unprepare(rtc->sclk); | 441 | clk_disable_unprepare(rtc->sclk); |
@@ -528,8 +493,9 @@ static int at91_rtc_suspend(struct device *dev) | |||
528 | /* don't let RTTINC cause wakeups */ | 493 | /* don't let RTTINC cause wakeups */ |
529 | if (mr & AT91_RTT_RTTINCIEN) | 494 | if (mr & AT91_RTT_RTTINCIEN) |
530 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | 495 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); |
531 | } else | 496 | } else { |
532 | rtt_writel(rtc, MR, mr & ~rtc->imr); | 497 | rtt_writel(rtc, MR, mr & ~rtc->imr); |
498 | } | ||
533 | } | 499 | } |
534 | 500 | ||
535 | return 0; | 501 | return 0; |
@@ -561,13 +527,11 @@ static int at91_rtc_resume(struct device *dev) | |||
561 | 527 | ||
562 | static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); | 528 | static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); |
563 | 529 | ||
564 | #ifdef CONFIG_OF | ||
565 | static const struct of_device_id at91_rtc_dt_ids[] = { | 530 | static const struct of_device_id at91_rtc_dt_ids[] = { |
566 | { .compatible = "atmel,at91sam9260-rtt" }, | 531 | { .compatible = "atmel,at91sam9260-rtt" }, |
567 | { /* sentinel */ } | 532 | { /* sentinel */ } |
568 | }; | 533 | }; |
569 | MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids); | 534 | MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids); |
570 | #endif | ||
571 | 535 | ||
572 | static struct platform_driver at91_rtc_driver = { | 536 | static struct platform_driver at91_rtc_driver = { |
573 | .probe = at91_rtc_probe, | 537 | .probe = at91_rtc_probe, |