aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2014-09-23 07:14:44 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2014-11-13 10:08:00 -0500
commit43e112bb3dea87f392871220fcde175c814e26ca (patch)
treebe9be4cd27b0354914d07fc060b56f41c2a23041
parent07d4d72450ef9bf317dff3d9f3bcad8d1f220f58 (diff)
rtc: at91sam9: make use of syscon/regmap to access GPBR registers
The GPBR registers are not part of the RTT block and thus should not be defined in the reg property of the rtt node. Use syscon to provide a proper DT representation and reference the GPBR syscon device in a new "atmel,rtt-rtc-time-reg" property which store both the syscon device phandle and the register offset within the GPBR block. When using non DT boards, we won't be able to retrieve the syscon regmap, hence we need to create our own regmap using the memory region defined in the 2nd memory resource assigned to the RTT platform device. Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Acked-by: Johan Hovold <johan@kernel.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-rw-r--r--drivers/rtc/Kconfig1
-rw-r--r--drivers/rtc/rtc-at91sam9.c64
2 files changed, 56 insertions, 9 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 94ae1798d48a..7b1f59258062 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1111,6 +1111,7 @@ config RTC_DRV_AT91RM9200
1111config RTC_DRV_AT91SAM9 1111config RTC_DRV_AT91SAM9
1112 tristate "AT91SAM9x/AT91CAP9 RTT as RTC" 1112 tristate "AT91SAM9x/AT91CAP9 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 RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT
1116 (Real Time Timer). These timers are powered by the backup power 1117 (Real Time Timer). These timers are powered by the backup power
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index d72c34d3f130..be9c28b9d057 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -21,6 +21,8 @@
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#include <linux/mfd/syscon.h>
25#include <linux/regmap.h>
24 26
25/* 27/*
26 * This driver uses two configurable hardware resources that live in the 28 * This driver uses two configurable hardware resources that live in the
@@ -72,7 +74,8 @@ struct sam9_rtc {
72 void __iomem *rtt; 74 void __iomem *rtt;
73 struct rtc_device *rtcdev; 75 struct rtc_device *rtcdev;
74 u32 imr; 76 u32 imr;
75 void __iomem *gpbr; 77 struct regmap *gpbr;
78 unsigned int gpbr_offset;
76 int irq; 79 int irq;
77}; 80};
78 81
@@ -81,10 +84,19 @@ struct sam9_rtc {
81#define rtt_writel(rtc, field, val) \ 84#define rtt_writel(rtc, field, val) \
82 writel((val), (rtc)->rtt + AT91_RTT_ ## field) 85 writel((val), (rtc)->rtt + AT91_RTT_ ## field)
83 86
84#define gpbr_readl(rtc) \ 87static inline unsigned int gpbr_readl(struct sam9_rtc *rtc)
85 readl((rtc)->gpbr) 88{
86#define gpbr_writel(rtc, val) \ 89 unsigned int val;
87 writel((val), (rtc)->gpbr) 90
91 regmap_read(rtc->gpbr, rtc->gpbr_offset, &val);
92
93 return val;
94}
95
96static inline void gpbr_writel(struct sam9_rtc *rtc, unsigned int val)
97{
98 regmap_write(rtc->gpbr, rtc->gpbr_offset, val);
99}
88 100
89/* 101/*
90 * Read current time and date in RTC 102 * Read current time and date in RTC
@@ -301,6 +313,12 @@ static const struct rtc_class_ops at91_rtc_ops = {
301 .alarm_irq_enable = at91_rtc_alarm_irq_enable, 313 .alarm_irq_enable = at91_rtc_alarm_irq_enable,
302}; 314};
303 315
316static struct regmap_config gpbr_regmap_config = {
317 .reg_bits = 32,
318 .val_bits = 32,
319 .reg_stride = 4,
320};
321
304/* 322/*
305 * Initialize and install RTC driver 323 * Initialize and install RTC driver
306 */ 324 */
@@ -334,10 +352,38 @@ static int at91_rtc_probe(struct platform_device *pdev)
334 if (IS_ERR(rtc->rtt)) 352 if (IS_ERR(rtc->rtt))
335 return PTR_ERR(rtc->rtt); 353 return PTR_ERR(rtc->rtt);
336 354
337 r = platform_get_resource(pdev, IORESOURCE_MEM, 1); 355 if (!pdev->dev.of_node) {
338 rtc->gpbr = devm_ioremap_resource(&pdev->dev, r); 356 /*
339 if (IS_ERR(rtc->gpbr)) 357 * TODO: Remove this code chunk when removing non DT board
340 return PTR_ERR(rtc->rtt); 358 * support. Remember to remove the gpbr_regmap_config
359 * variable too.
360 */
361 void __iomem *gpbr;
362
363 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
364 gpbr = devm_ioremap_resource(&pdev->dev, r);
365 if (IS_ERR(gpbr))
366 return PTR_ERR(gpbr);
367
368 rtc->gpbr = regmap_init_mmio(NULL, gpbr,
369 &gpbr_regmap_config);
370 } else {
371 struct of_phandle_args args;
372
373 ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
374 "atmel,rtt-rtc-time-reg", 1, 0,
375 &args);
376 if (ret)
377 return ret;
378
379 rtc->gpbr = syscon_node_to_regmap(args.np);
380 rtc->gpbr_offset = args.args[0];
381 }
382
383 if (IS_ERR(rtc->gpbr)) {
384 dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n");
385 return -ENOMEM;
386 }
341 387
342 mr = rtt_readl(rtc, MR); 388 mr = rtt_readl(rtc, MR);
343 389