aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-at91rm9200.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-at91rm9200.c')
-rw-r--r--drivers/rtc/rtc-at91rm9200.c135
1 files changed, 112 insertions, 23 deletions
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 0eab77b22340..741892632ae0 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -25,13 +25,13 @@
25#include <linux/rtc.h> 25#include <linux/rtc.h>
26#include <linux/bcd.h> 26#include <linux/bcd.h>
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/spinlock.h>
28#include <linux/ioctl.h> 29#include <linux/ioctl.h>
29#include <linux/completion.h> 30#include <linux/completion.h>
30#include <linux/io.h> 31#include <linux/io.h>
31#include <linux/of.h> 32#include <linux/of.h>
32#include <linux/of_device.h> 33#include <linux/of_device.h>
33 34#include <linux/uaccess.h>
34#include <asm/uaccess.h>
35 35
36#include "rtc-at91rm9200.h" 36#include "rtc-at91rm9200.h"
37 37
@@ -42,10 +42,65 @@
42 42
43#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ 43#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */
44 44
45struct at91_rtc_config {
46 bool use_shadow_imr;
47};
48
49static const struct at91_rtc_config *at91_rtc_config;
45static DECLARE_COMPLETION(at91_rtc_updated); 50static DECLARE_COMPLETION(at91_rtc_updated);
46static unsigned int at91_alarm_year = AT91_RTC_EPOCH; 51static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
47static void __iomem *at91_rtc_regs; 52static void __iomem *at91_rtc_regs;
48static int irq; 53static int irq;
54static DEFINE_SPINLOCK(at91_rtc_lock);
55static u32 at91_rtc_shadow_imr;
56
57static void at91_rtc_write_ier(u32 mask)
58{
59 unsigned long flags;
60
61 spin_lock_irqsave(&at91_rtc_lock, flags);
62 at91_rtc_shadow_imr |= mask;
63 at91_rtc_write(AT91_RTC_IER, mask);
64 spin_unlock_irqrestore(&at91_rtc_lock, flags);
65}
66
67static void at91_rtc_write_idr(u32 mask)
68{
69 unsigned long flags;
70
71 spin_lock_irqsave(&at91_rtc_lock, flags);
72 at91_rtc_write(AT91_RTC_IDR, mask);
73 /*
74 * Register read back (of any RTC-register) needed to make sure
75 * IDR-register write has reached the peripheral before updating
76 * shadow mask.
77 *
78 * Note that there is still a possibility that the mask is updated
79 * before interrupts have actually been disabled in hardware. The only
80 * way to be certain would be to poll the IMR-register, which is is
81 * the very register we are trying to emulate. The register read back
82 * is a reasonable heuristic.
83 */
84 at91_rtc_read(AT91_RTC_SR);
85 at91_rtc_shadow_imr &= ~mask;
86 spin_unlock_irqrestore(&at91_rtc_lock, flags);
87}
88
89static u32 at91_rtc_read_imr(void)
90{
91 unsigned long flags;
92 u32 mask;
93
94 if (at91_rtc_config->use_shadow_imr) {
95 spin_lock_irqsave(&at91_rtc_lock, flags);
96 mask = at91_rtc_shadow_imr;
97 spin_unlock_irqrestore(&at91_rtc_lock, flags);
98 } else {
99 mask = at91_rtc_read(AT91_RTC_IMR);
100 }
101
102 return mask;
103}
49 104
50/* 105/*
51 * Decode time/date into rtc_time structure 106 * Decode time/date into rtc_time structure
@@ -110,9 +165,9 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
110 cr = at91_rtc_read(AT91_RTC_CR); 165 cr = at91_rtc_read(AT91_RTC_CR);
111 at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); 166 at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
112 167
113 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); 168 at91_rtc_write_ier(AT91_RTC_ACKUPD);
114 wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ 169 wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
115 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); 170 at91_rtc_write_idr(AT91_RTC_ACKUPD);
116 171
117 at91_rtc_write(AT91_RTC_TIMR, 172 at91_rtc_write(AT91_RTC_TIMR,
118 bin2bcd(tm->tm_sec) << 0 173 bin2bcd(tm->tm_sec) << 0
@@ -144,7 +199,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
144 tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); 199 tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
145 tm->tm_year = at91_alarm_year - 1900; 200 tm->tm_year = at91_alarm_year - 1900;
146 201
147 alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) 202 alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
148 ? 1 : 0; 203 ? 1 : 0;
149 204
150 dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, 205 dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
@@ -169,7 +224,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
169 tm.tm_min = alrm->time.tm_min; 224 tm.tm_min = alrm->time.tm_min;
170 tm.tm_sec = alrm->time.tm_sec; 225 tm.tm_sec = alrm->time.tm_sec;
171 226
172 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); 227 at91_rtc_write_idr(AT91_RTC_ALARM);
173 at91_rtc_write(AT91_RTC_TIMALR, 228 at91_rtc_write(AT91_RTC_TIMALR,
174 bin2bcd(tm.tm_sec) << 0 229 bin2bcd(tm.tm_sec) << 0
175 | bin2bcd(tm.tm_min) << 8 230 | bin2bcd(tm.tm_min) << 8
@@ -182,7 +237,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
182 237
183 if (alrm->enabled) { 238 if (alrm->enabled) {
184 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); 239 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
185 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); 240 at91_rtc_write_ier(AT91_RTC_ALARM);
186 } 241 }
187 242
188 dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, 243 dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
@@ -198,9 +253,9 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
198 253
199 if (enabled) { 254 if (enabled) {
200 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); 255 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
201 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); 256 at91_rtc_write_ier(AT91_RTC_ALARM);
202 } else 257 } else
203 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); 258 at91_rtc_write_idr(AT91_RTC_ALARM);
204 259
205 return 0; 260 return 0;
206} 261}
@@ -209,7 +264,7 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
209 */ 264 */
210static int at91_rtc_proc(struct device *dev, struct seq_file *seq) 265static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
211{ 266{
212 unsigned long imr = at91_rtc_read(AT91_RTC_IMR); 267 unsigned long imr = at91_rtc_read_imr();
213 268
214 seq_printf(seq, "update_IRQ\t: %s\n", 269 seq_printf(seq, "update_IRQ\t: %s\n",
215 (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); 270 (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
@@ -229,7 +284,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
229 unsigned int rtsr; 284 unsigned int rtsr;
230 unsigned long events = 0; 285 unsigned long events = 0;
231 286
232 rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR); 287 rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read_imr();
233 if (rtsr) { /* this interrupt is shared! Is it ours? */ 288 if (rtsr) { /* this interrupt is shared! Is it ours? */
234 if (rtsr & AT91_RTC_ALARM) 289 if (rtsr & AT91_RTC_ALARM)
235 events |= (RTC_AF | RTC_IRQF); 290 events |= (RTC_AF | RTC_IRQF);
@@ -250,6 +305,43 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
250 return IRQ_NONE; /* not handled */ 305 return IRQ_NONE; /* not handled */
251} 306}
252 307
308static const struct at91_rtc_config at91rm9200_config = {
309};
310
311static const struct at91_rtc_config at91sam9x5_config = {
312 .use_shadow_imr = true,
313};
314
315#ifdef CONFIG_OF
316static const struct of_device_id at91_rtc_dt_ids[] = {
317 {
318 .compatible = "atmel,at91rm9200-rtc",
319 .data = &at91rm9200_config,
320 }, {
321 .compatible = "atmel,at91sam9x5-rtc",
322 .data = &at91sam9x5_config,
323 }, {
324 /* sentinel */
325 }
326};
327MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
328#endif
329
330static const struct at91_rtc_config *
331at91_rtc_get_config(struct platform_device *pdev)
332{
333 const struct of_device_id *match;
334
335 if (pdev->dev.of_node) {
336 match = of_match_node(at91_rtc_dt_ids, pdev->dev.of_node);
337 if (!match)
338 return NULL;
339 return (const struct at91_rtc_config *)match->data;
340 }
341
342 return &at91rm9200_config;
343}
344
253static const struct rtc_class_ops at91_rtc_ops = { 345static const struct rtc_class_ops at91_rtc_ops = {
254 .read_time = at91_rtc_readtime, 346 .read_time = at91_rtc_readtime,
255 .set_time = at91_rtc_settime, 347 .set_time = at91_rtc_settime,
@@ -268,6 +360,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
268 struct resource *regs; 360 struct resource *regs;
269 int ret = 0; 361 int ret = 0;
270 362
363 at91_rtc_config = at91_rtc_get_config(pdev);
364 if (!at91_rtc_config)
365 return -ENODEV;
366
271 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 367 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
272 if (!regs) { 368 if (!regs) {
273 dev_err(&pdev->dev, "no mmio resource defined\n"); 369 dev_err(&pdev->dev, "no mmio resource defined\n");
@@ -290,7 +386,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
290 at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */ 386 at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */
291 387
292 /* Disable all interrupts */ 388 /* Disable all interrupts */
293 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | 389 at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
294 AT91_RTC_SECEV | AT91_RTC_TIMEV | 390 AT91_RTC_SECEV | AT91_RTC_TIMEV |
295 AT91_RTC_CALEV); 391 AT91_RTC_CALEV);
296 392
@@ -335,14 +431,13 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
335 struct rtc_device *rtc = platform_get_drvdata(pdev); 431 struct rtc_device *rtc = platform_get_drvdata(pdev);
336 432
337 /* Disable all interrupts */ 433 /* Disable all interrupts */
338 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | 434 at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
339 AT91_RTC_SECEV | AT91_RTC_TIMEV | 435 AT91_RTC_SECEV | AT91_RTC_TIMEV |
340 AT91_RTC_CALEV); 436 AT91_RTC_CALEV);
341 free_irq(irq, pdev); 437 free_irq(irq, pdev);
342 438
343 rtc_device_unregister(rtc); 439 rtc_device_unregister(rtc);
344 iounmap(at91_rtc_regs); 440 iounmap(at91_rtc_regs);
345 platform_set_drvdata(pdev, NULL);
346 441
347 return 0; 442 return 0;
348} 443}
@@ -358,13 +453,13 @@ static int at91_rtc_suspend(struct device *dev)
358 /* this IRQ is shared with DBGU and other hardware which isn't 453 /* this IRQ is shared with DBGU and other hardware which isn't
359 * necessarily doing PM like we are... 454 * necessarily doing PM like we are...
360 */ 455 */
361 at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR) 456 at91_rtc_imr = at91_rtc_read_imr()
362 & (AT91_RTC_ALARM|AT91_RTC_SECEV); 457 & (AT91_RTC_ALARM|AT91_RTC_SECEV);
363 if (at91_rtc_imr) { 458 if (at91_rtc_imr) {
364 if (device_may_wakeup(dev)) 459 if (device_may_wakeup(dev))
365 enable_irq_wake(irq); 460 enable_irq_wake(irq);
366 else 461 else
367 at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr); 462 at91_rtc_write_idr(at91_rtc_imr);
368 } 463 }
369 return 0; 464 return 0;
370} 465}
@@ -375,7 +470,7 @@ static int at91_rtc_resume(struct device *dev)
375 if (device_may_wakeup(dev)) 470 if (device_may_wakeup(dev))
376 disable_irq_wake(irq); 471 disable_irq_wake(irq);
377 else 472 else
378 at91_rtc_write(AT91_RTC_IER, at91_rtc_imr); 473 at91_rtc_write_ier(at91_rtc_imr);
379 } 474 }
380 return 0; 475 return 0;
381} 476}
@@ -383,12 +478,6 @@ static int at91_rtc_resume(struct device *dev)
383 478
384static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); 479static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
385 480
386static const struct of_device_id at91_rtc_dt_ids[] = {
387 { .compatible = "atmel,at91rm9200-rtc" },
388 { /* sentinel */ }
389};
390MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
391
392static struct platform_driver at91_rtc_driver = { 481static struct platform_driver at91_rtc_driver = {
393 .remove = __exit_p(at91_rtc_remove), 482 .remove = __exit_p(at91_rtc_remove),
394 .driver = { 483 .driver = {