diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-09 17:46:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-09 17:46:33 -0400 |
commit | 8e4ff713ce313dcabbb60e6ede1ffc193e67631f (patch) | |
tree | 8efdfe4925570ec8608d40e229ed01a5432d901e /drivers/rtc/rtc-at91sam9.c | |
parent | 45182e4e1f8ac04708ca7508c51d9103f07d81ab (diff) | |
parent | dacb6a4035a010e41abaf81c1cfe2beadfb05ec8 (diff) |
Merge tag 'rtc-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"A huge series from me this cycle. I went through many drivers to set
the date and time range supported by the RTC which helps solving HW
limitation when the time comes (as early as next year for some). This
time, I focused on drivers using .set_mms and .set_mmss64, allowing me
to remove those callbacks. About a third of the patches got reviews, I
actually own the RTCs and I tested another third and the remaining one
are unlikely to cause any issues.
Other than that, a single new driver and the usual fixes here and there.
Summary:
Subsystem:
- set_mmss and set_mmss64 rtc_ops removal
- Fix timestamp value for RTC_TIMESTAMP_BEGIN_1900
- Use SPDX identifier for the core
- validate upper bound of tm->tm_year
New driver:
- Aspeed BMC SoC RTC
Drivers:
- abx80x: use rtc_add_group
- ds3232: nvram support
- pcf85063: add alarm, nvram, offset correction and microcrystal
rv8263 support
- x1205: add of_match_table
- Use set_time instead of set_mms/set_mmss64 for: ab3100, coh901331,
digicolor, ds1672, ds2404, ep93xx, imxdi, jz4740, lpc32xx, mc13xxx,
mxc, pcap, stmp3xxx, test, wm831x, xgene.
- Set RTC range for: ab3100, at91sam9, coh901331, da9063, digicolor,
dm355evm, ds1672, ds2404, ep39xx, goldfish, imxdi, jz4740, lpc32xx,
mc13xxx, mv, mxc, omap, pcap, pcf85063, pcf85363, ps3, sh,
stmp3xxx, sun4v, tegra, wm831x, xgene.
- Switch to rtc_time64_to_tm/rtc_tm_to_time64 for the driver that
properly set the RTC range.
- Use dev_get_drvdata instead of multiple indirections"
* tag 'rtc-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (177 commits)
rtc: snvs: Use __maybe_unused instead of #if CONFIG_PM_SLEEP
rtc: imxdi: remove unused variable
rtc: drop set_mms and set_mmss64
rtc: pcap: convert to SPDX identifier
rtc: pcap: use .set_time
rtc: pcap: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: pcap: set range
rtc: digicolor: convert to SPDX identifier
rtc: digicolor: use .set_time
rtc: digicolor: set range
rtc: digicolor: fix possible race condition
rtc: jz4740: convert to SPDX identifier
rtc: jz4740: rework invalid time detection
rtc: jz4740: use dev_pm_set_wake_irq() to simplify code
rtc: jz4740: use .set_time
rtc: jz4740: remove useless check
rtc: jz4740: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: jz4740: set range
rtc: 88pm860x: prevent use-after-free on device remove
rtc: Use dev_get_drvdata()
...
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, |