diff options
Diffstat (limited to 'drivers/rtc/rtc-omap.c')
-rw-r--r-- | drivers/rtc/rtc-omap.c | 138 |
1 files changed, 78 insertions, 60 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 26de5f8c2ae4..21142e6574a9 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -73,43 +73,52 @@ | |||
73 | #define OMAP_RTC_IRQWAKEEN 0x7c | 73 | #define OMAP_RTC_IRQWAKEEN 0x7c |
74 | 74 | ||
75 | /* OMAP_RTC_CTRL_REG bit fields: */ | 75 | /* OMAP_RTC_CTRL_REG bit fields: */ |
76 | #define OMAP_RTC_CTRL_SPLIT (1<<7) | 76 | #define OMAP_RTC_CTRL_SPLIT BIT(7) |
77 | #define OMAP_RTC_CTRL_DISABLE (1<<6) | 77 | #define OMAP_RTC_CTRL_DISABLE BIT(6) |
78 | #define OMAP_RTC_CTRL_SET_32_COUNTER (1<<5) | 78 | #define OMAP_RTC_CTRL_SET_32_COUNTER BIT(5) |
79 | #define OMAP_RTC_CTRL_TEST (1<<4) | 79 | #define OMAP_RTC_CTRL_TEST BIT(4) |
80 | #define OMAP_RTC_CTRL_MODE_12_24 (1<<3) | 80 | #define OMAP_RTC_CTRL_MODE_12_24 BIT(3) |
81 | #define OMAP_RTC_CTRL_AUTO_COMP (1<<2) | 81 | #define OMAP_RTC_CTRL_AUTO_COMP BIT(2) |
82 | #define OMAP_RTC_CTRL_ROUND_30S (1<<1) | 82 | #define OMAP_RTC_CTRL_ROUND_30S BIT(1) |
83 | #define OMAP_RTC_CTRL_STOP (1<<0) | 83 | #define OMAP_RTC_CTRL_STOP BIT(0) |
84 | 84 | ||
85 | /* OMAP_RTC_STATUS_REG bit fields: */ | 85 | /* OMAP_RTC_STATUS_REG bit fields: */ |
86 | #define OMAP_RTC_STATUS_POWER_UP (1<<7) | 86 | #define OMAP_RTC_STATUS_POWER_UP BIT(7) |
87 | #define OMAP_RTC_STATUS_ALARM (1<<6) | 87 | #define OMAP_RTC_STATUS_ALARM BIT(6) |
88 | #define OMAP_RTC_STATUS_1D_EVENT (1<<5) | 88 | #define OMAP_RTC_STATUS_1D_EVENT BIT(5) |
89 | #define OMAP_RTC_STATUS_1H_EVENT (1<<4) | 89 | #define OMAP_RTC_STATUS_1H_EVENT BIT(4) |
90 | #define OMAP_RTC_STATUS_1M_EVENT (1<<3) | 90 | #define OMAP_RTC_STATUS_1M_EVENT BIT(3) |
91 | #define OMAP_RTC_STATUS_1S_EVENT (1<<2) | 91 | #define OMAP_RTC_STATUS_1S_EVENT BIT(2) |
92 | #define OMAP_RTC_STATUS_RUN (1<<1) | 92 | #define OMAP_RTC_STATUS_RUN BIT(1) |
93 | #define OMAP_RTC_STATUS_BUSY (1<<0) | 93 | #define OMAP_RTC_STATUS_BUSY BIT(0) |
94 | 94 | ||
95 | /* OMAP_RTC_INTERRUPTS_REG bit fields: */ | 95 | /* OMAP_RTC_INTERRUPTS_REG bit fields: */ |
96 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 96 | #define OMAP_RTC_INTERRUPTS_IT_ALARM BIT(3) |
97 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 97 | #define OMAP_RTC_INTERRUPTS_IT_TIMER BIT(2) |
98 | |||
99 | /* OMAP_RTC_OSC_REG bit fields: */ | ||
100 | #define OMAP_RTC_OSC_32KCLK_EN BIT(6) | ||
98 | 101 | ||
99 | /* OMAP_RTC_IRQWAKEEN bit fields: */ | 102 | /* OMAP_RTC_IRQWAKEEN bit fields: */ |
100 | #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1) | 103 | #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1) |
101 | 104 | ||
102 | /* OMAP_RTC_KICKER values */ | 105 | /* OMAP_RTC_KICKER values */ |
103 | #define KICK0_VALUE 0x83e70b13 | 106 | #define KICK0_VALUE 0x83e70b13 |
104 | #define KICK1_VALUE 0x95a4f1e0 | 107 | #define KICK1_VALUE 0x95a4f1e0 |
105 | 108 | ||
106 | #define OMAP_RTC_HAS_KICKER 0x1 | 109 | #define OMAP_RTC_HAS_KICKER BIT(0) |
107 | 110 | ||
108 | /* | 111 | /* |
109 | * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup | 112 | * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup |
110 | * generation for event Alarm. | 113 | * generation for event Alarm. |
111 | */ | 114 | */ |
112 | #define OMAP_RTC_HAS_IRQWAKEEN 0x2 | 115 | #define OMAP_RTC_HAS_IRQWAKEEN BIT(1) |
116 | |||
117 | /* | ||
118 | * Some RTC IP revisions (like those in AM335x and DRA7x) need | ||
119 | * the 32KHz clock to be explicitly enabled. | ||
120 | */ | ||
121 | #define OMAP_RTC_HAS_32KCLK_EN BIT(2) | ||
113 | 122 | ||
114 | static void __iomem *rtc_base; | 123 | static void __iomem *rtc_base; |
115 | 124 | ||
@@ -162,17 +171,28 @@ static irqreturn_t rtc_irq(int irq, void *rtc) | |||
162 | 171 | ||
163 | static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 172 | static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
164 | { | 173 | { |
165 | u8 reg; | 174 | u8 reg, irqwake_reg = 0; |
175 | struct platform_device *pdev = to_platform_device(dev); | ||
176 | const struct platform_device_id *id_entry = | ||
177 | platform_get_device_id(pdev); | ||
166 | 178 | ||
167 | local_irq_disable(); | 179 | local_irq_disable(); |
168 | rtc_wait_not_busy(); | 180 | rtc_wait_not_busy(); |
169 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 181 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
170 | if (enabled) | 182 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) |
183 | irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
184 | |||
185 | if (enabled) { | ||
171 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | 186 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; |
172 | else | 187 | irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; |
188 | } else { | ||
173 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | 189 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; |
190 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
191 | } | ||
174 | rtc_wait_not_busy(); | 192 | rtc_wait_not_busy(); |
175 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); | 193 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); |
194 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) | ||
195 | rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); | ||
176 | local_irq_enable(); | 196 | local_irq_enable(); |
177 | 197 | ||
178 | return 0; | 198 | return 0; |
@@ -272,7 +292,10 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
272 | 292 | ||
273 | static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 293 | static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
274 | { | 294 | { |
275 | u8 reg; | 295 | u8 reg, irqwake_reg = 0; |
296 | struct platform_device *pdev = to_platform_device(dev); | ||
297 | const struct platform_device_id *id_entry = | ||
298 | platform_get_device_id(pdev); | ||
276 | 299 | ||
277 | if (tm2bcd(&alm->time) < 0) | 300 | if (tm2bcd(&alm->time) < 0) |
278 | return -EINVAL; | 301 | return -EINVAL; |
@@ -288,11 +311,19 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
288 | rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); | 311 | rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); |
289 | 312 | ||
290 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 313 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
291 | if (alm->enabled) | 314 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) |
315 | irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
316 | |||
317 | if (alm->enabled) { | ||
292 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | 318 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; |
293 | else | 319 | irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; |
320 | } else { | ||
294 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | 321 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; |
322 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
323 | } | ||
295 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); | 324 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); |
325 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) | ||
326 | rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); | ||
296 | 327 | ||
297 | local_irq_enable(); | 328 | local_irq_enable(); |
298 | 329 | ||
@@ -319,7 +350,8 @@ static struct platform_device_id omap_rtc_devtype[] = { | |||
319 | }, | 350 | }, |
320 | [OMAP_RTC_DATA_AM3352_IDX] = { | 351 | [OMAP_RTC_DATA_AM3352_IDX] = { |
321 | .name = "am3352-rtc", | 352 | .name = "am3352-rtc", |
322 | .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN, | 353 | .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN | |
354 | OMAP_RTC_HAS_32KCLK_EN, | ||
323 | }, | 355 | }, |
324 | [OMAP_RTC_DATA_DA830_IDX] = { | 356 | [OMAP_RTC_DATA_DA830_IDX] = { |
325 | .name = "da830-rtc", | 357 | .name = "da830-rtc", |
@@ -352,6 +384,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
352 | if (of_id) | 384 | if (of_id) |
353 | pdev->id_entry = of_id->data; | 385 | pdev->id_entry = of_id->data; |
354 | 386 | ||
387 | id_entry = platform_get_device_id(pdev); | ||
388 | if (!id_entry) { | ||
389 | dev_err(&pdev->dev, "no matching device entry\n"); | ||
390 | return -ENODEV; | ||
391 | } | ||
392 | |||
355 | omap_rtc_timer = platform_get_irq(pdev, 0); | 393 | omap_rtc_timer = platform_get_irq(pdev, 0); |
356 | if (omap_rtc_timer <= 0) { | 394 | if (omap_rtc_timer <= 0) { |
357 | pr_debug("%s: no update irq?\n", pdev->name); | 395 | pr_debug("%s: no update irq?\n", pdev->name); |
@@ -373,8 +411,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
373 | pm_runtime_enable(&pdev->dev); | 411 | pm_runtime_enable(&pdev->dev); |
374 | pm_runtime_get_sync(&pdev->dev); | 412 | pm_runtime_get_sync(&pdev->dev); |
375 | 413 | ||
376 | id_entry = platform_get_device_id(pdev); | 414 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) { |
377 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { | ||
378 | rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); | 415 | rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); |
379 | rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); | 416 | rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); |
380 | } | 417 | } |
@@ -393,6 +430,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
393 | */ | 430 | */ |
394 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 431 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
395 | 432 | ||
433 | /* enable RTC functional clock */ | ||
434 | if (id_entry->driver_data & OMAP_RTC_HAS_32KCLK_EN) | ||
435 | rtc_writel(OMAP_RTC_OSC_32KCLK_EN, OMAP_RTC_OSC_REG); | ||
436 | |||
396 | /* clear old status */ | 437 | /* clear old status */ |
397 | reg = rtc_read(OMAP_RTC_STATUS_REG); | 438 | reg = rtc_read(OMAP_RTC_STATUS_REG); |
398 | if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { | 439 | if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { |
@@ -452,7 +493,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
452 | return 0; | 493 | return 0; |
453 | 494 | ||
454 | fail0: | 495 | fail0: |
455 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | 496 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) |
456 | rtc_writel(0, OMAP_RTC_KICK0_REG); | 497 | rtc_writel(0, OMAP_RTC_KICK0_REG); |
457 | pm_runtime_put_sync(&pdev->dev); | 498 | pm_runtime_put_sync(&pdev->dev); |
458 | pm_runtime_disable(&pdev->dev); | 499 | pm_runtime_disable(&pdev->dev); |
@@ -469,7 +510,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
469 | /* leave rtc running, but disable irqs */ | 510 | /* leave rtc running, but disable irqs */ |
470 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 511 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
471 | 512 | ||
472 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | 513 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) |
473 | rtc_writel(0, OMAP_RTC_KICK0_REG); | 514 | rtc_writel(0, OMAP_RTC_KICK0_REG); |
474 | 515 | ||
475 | /* Disable the clock/module */ | 516 | /* Disable the clock/module */ |
@@ -484,28 +525,16 @@ static u8 irqstat; | |||
484 | 525 | ||
485 | static int omap_rtc_suspend(struct device *dev) | 526 | static int omap_rtc_suspend(struct device *dev) |
486 | { | 527 | { |
487 | u8 irqwake_stat; | ||
488 | struct platform_device *pdev = to_platform_device(dev); | ||
489 | const struct platform_device_id *id_entry = | ||
490 | platform_get_device_id(pdev); | ||
491 | |||
492 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 528 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
493 | 529 | ||
494 | /* FIXME the RTC alarm is not currently acting as a wakeup event | 530 | /* FIXME the RTC alarm is not currently acting as a wakeup event |
495 | * source on some platforms, and in fact this enable() call is just | 531 | * source on some platforms, and in fact this enable() call is just |
496 | * saving a flag that's never used... | 532 | * saving a flag that's never used... |
497 | */ | 533 | */ |
498 | if (device_may_wakeup(dev)) { | 534 | if (device_may_wakeup(dev)) |
499 | enable_irq_wake(omap_rtc_alarm); | 535 | enable_irq_wake(omap_rtc_alarm); |
500 | 536 | else | |
501 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { | ||
502 | irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
503 | irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
504 | rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); | ||
505 | } | ||
506 | } else { | ||
507 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 537 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
508 | } | ||
509 | 538 | ||
510 | /* Disable the clock/module */ | 539 | /* Disable the clock/module */ |
511 | pm_runtime_put_sync(dev); | 540 | pm_runtime_put_sync(dev); |
@@ -515,25 +544,14 @@ static int omap_rtc_suspend(struct device *dev) | |||
515 | 544 | ||
516 | static int omap_rtc_resume(struct device *dev) | 545 | static int omap_rtc_resume(struct device *dev) |
517 | { | 546 | { |
518 | u8 irqwake_stat; | ||
519 | struct platform_device *pdev = to_platform_device(dev); | ||
520 | const struct platform_device_id *id_entry = | ||
521 | platform_get_device_id(pdev); | ||
522 | |||
523 | /* Enable the clock/module so that we can access the registers */ | 547 | /* Enable the clock/module so that we can access the registers */ |
524 | pm_runtime_get_sync(dev); | 548 | pm_runtime_get_sync(dev); |
525 | 549 | ||
526 | if (device_may_wakeup(dev)) { | 550 | if (device_may_wakeup(dev)) |
527 | disable_irq_wake(omap_rtc_alarm); | 551 | disable_irq_wake(omap_rtc_alarm); |
528 | 552 | else | |
529 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { | ||
530 | irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
531 | irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
532 | rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); | ||
533 | } | ||
534 | } else { | ||
535 | rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); | 553 | rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); |
536 | } | 554 | |
537 | return 0; | 555 | return 0; |
538 | } | 556 | } |
539 | #endif | 557 | #endif |