aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-omap.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2014-12-10 18:53:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:14 -0500
commit2153f94943ca6c47df585205bfde0c5f1311f84b (patch)
treef9bd4be441536bd2d35848adf4173b924cf34518 /drivers/rtc/rtc-omap.c
parenta430ca22676e270508edb8d74d6fb895cf74584b (diff)
rtc: omap: add structured device-type info
Add structured device-type info to encode IP-block revision differences. Signed-off-by: Johan Hovold <johan@kernel.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Tony Lindgren <tony@atomide.com> Cc: Benot Cousson <bcousson@baylibre.com> Cc: Lokesh Vutla <lokeshvutla@ti.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Tero Kristo <t-kristo@ti.com> Cc: Keerthy J <j-keerthy@ti.com> Tested-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-omap.c')
-rw-r--r--drivers/rtc/rtc-omap.c103
1 files changed, 51 insertions, 52 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index f70ae660368b..1abd88e24c22 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -102,19 +102,11 @@
102#define KICK0_VALUE 0x83e70b13 102#define KICK0_VALUE 0x83e70b13
103#define KICK1_VALUE 0x95a4f1e0 103#define KICK1_VALUE 0x95a4f1e0
104 104
105#define OMAP_RTC_HAS_KICKER BIT(0) 105struct omap_rtc_device_type {
106 106 bool has_32kclk_en;
107/* 107 bool has_kicker;
108 * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup 108 bool has_irqwakeen;
109 * generation for event Alarm. 109};
110 */
111#define OMAP_RTC_HAS_IRQWAKEEN BIT(1)
112
113/*
114 * Some RTC IP revisions (like those in AM335x and DRA7x) need
115 * the 32KHz clock to be explicitly enabled.
116 */
117#define OMAP_RTC_HAS_32KCLK_EN BIT(2)
118 110
119struct omap_rtc { 111struct omap_rtc {
120 struct rtc_device *rtc; 112 struct rtc_device *rtc;
@@ -122,7 +114,7 @@ struct omap_rtc {
122 int irq_alarm; 114 int irq_alarm;
123 int irq_timer; 115 int irq_timer;
124 u8 interrupts_reg; 116 u8 interrupts_reg;
125 unsigned long flags; 117 const struct omap_rtc_device_type *type;
126}; 118};
127 119
128static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg) 120static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg)
@@ -190,7 +182,7 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
190 local_irq_disable(); 182 local_irq_disable();
191 rtc_wait_not_busy(rtc); 183 rtc_wait_not_busy(rtc);
192 reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); 184 reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
193 if (rtc->flags & OMAP_RTC_HAS_IRQWAKEEN) 185 if (rtc->type->has_irqwakeen)
194 irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN); 186 irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN);
195 187
196 if (enabled) { 188 if (enabled) {
@@ -202,7 +194,7 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
202 } 194 }
203 rtc_wait_not_busy(rtc); 195 rtc_wait_not_busy(rtc);
204 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); 196 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
205 if (rtc->flags & OMAP_RTC_HAS_IRQWAKEEN) 197 if (rtc->type->has_irqwakeen)
206 rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); 198 rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
207 local_irq_enable(); 199 local_irq_enable();
208 200
@@ -326,7 +318,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
326 rtc_write(rtc, OMAP_RTC_ALARM_SECONDS_REG, alm->time.tm_sec); 318 rtc_write(rtc, OMAP_RTC_ALARM_SECONDS_REG, alm->time.tm_sec);
327 319
328 reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); 320 reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
329 if (rtc->flags & OMAP_RTC_HAS_IRQWAKEEN) 321 if (rtc->type->has_irqwakeen)
330 irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN); 322 irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN);
331 323
332 if (alm->enabled) { 324 if (alm->enabled) {
@@ -337,7 +329,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
337 irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 329 irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
338 } 330 }
339 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); 331 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
340 if (rtc->flags & OMAP_RTC_HAS_IRQWAKEEN) 332 if (rtc->type->has_irqwakeen)
341 rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); 333 rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
342 334
343 local_irq_enable(); 335 local_irq_enable();
@@ -353,34 +345,45 @@ static struct rtc_class_ops omap_rtc_ops = {
353 .alarm_irq_enable = omap_rtc_alarm_irq_enable, 345 .alarm_irq_enable = omap_rtc_alarm_irq_enable,
354}; 346};
355 347
356#define OMAP_RTC_DATA_AM3352_IDX 1 348static const struct omap_rtc_device_type omap_rtc_default_type = {
357#define OMAP_RTC_DATA_DA830_IDX 2 349};
350
351static const struct omap_rtc_device_type omap_rtc_am3352_type = {
352 .has_32kclk_en = true,
353 .has_kicker = true,
354 .has_irqwakeen = true,
355};
356
357static const struct omap_rtc_device_type omap_rtc_da830_type = {
358 .has_kicker = true,
359};
358 360
359static const struct platform_device_id omap_rtc_devtype[] = { 361static const struct platform_device_id omap_rtc_id_table[] = {
360 { 362 {
361 .name = "omap_rtc", 363 .name = "omap_rtc",
362 }, 364 .driver_data = (kernel_ulong_t)&omap_rtc_default_type,
363 [OMAP_RTC_DATA_AM3352_IDX] = { 365 }, {
364 .name = "am3352-rtc", 366 .name = "am3352-rtc",
365 .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN | 367 .driver_data = (kernel_ulong_t)&omap_rtc_am3352_type,
366 OMAP_RTC_HAS_32KCLK_EN, 368 }, {
367 },
368 [OMAP_RTC_DATA_DA830_IDX] = {
369 .name = "da830-rtc", 369 .name = "da830-rtc",
370 .driver_data = OMAP_RTC_HAS_KICKER, 370 .driver_data = (kernel_ulong_t)&omap_rtc_da830_type,
371 }, 371 }, {
372 {}, 372 /* sentinel */
373 }
373}; 374};
374MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); 375MODULE_DEVICE_TABLE(platform, omap_rtc_id_table);
375 376
376static const struct of_device_id omap_rtc_of_match[] = { 377static const struct of_device_id omap_rtc_of_match[] = {
377 { .compatible = "ti,da830-rtc", 378 {
378 .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], 379 .compatible = "ti,am3352-rtc",
379 }, 380 .data = &omap_rtc_am3352_type,
380 { .compatible = "ti,am3352-rtc", 381 }, {
381 .data = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX], 382 .compatible = "ti,da830-rtc",
382 }, 383 .data = &omap_rtc_da830_type,
383 {}, 384 }, {
385 /* sentinel */
386 }
384}; 387};
385MODULE_DEVICE_TABLE(of, omap_rtc_of_match); 388MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
386 389
@@ -398,17 +401,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
398 return -ENOMEM; 401 return -ENOMEM;
399 402
400 of_id = of_match_device(omap_rtc_of_match, &pdev->dev); 403 of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
401 if (of_id) 404 if (of_id) {
402 pdev->id_entry = of_id->data; 405 rtc->type = of_id->data;
403 406 } else {
404 id_entry = platform_get_device_id(pdev); 407 id_entry = platform_get_device_id(pdev);
405 if (!id_entry) { 408 rtc->type = (void *)id_entry->driver_data;
406 dev_err(&pdev->dev, "no matching device entry\n");
407 return -ENODEV;
408 } 409 }
409 410
410 rtc->flags = id_entry->driver_data;
411
412 rtc->irq_timer = platform_get_irq(pdev, 0); 411 rtc->irq_timer = platform_get_irq(pdev, 0);
413 if (rtc->irq_timer <= 0) 412 if (rtc->irq_timer <= 0)
414 return -ENOENT; 413 return -ENOENT;
@@ -428,7 +427,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
428 pm_runtime_enable(&pdev->dev); 427 pm_runtime_enable(&pdev->dev);
429 pm_runtime_get_sync(&pdev->dev); 428 pm_runtime_get_sync(&pdev->dev);
430 429
431 if (rtc->flags & OMAP_RTC_HAS_KICKER) { 430 if (rtc->type->has_kicker) {
432 rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); 431 rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE);
433 rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); 432 rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE);
434 } 433 }
@@ -441,7 +440,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
441 rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, 0); 440 rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
442 441
443 /* enable RTC functional clock */ 442 /* enable RTC functional clock */
444 if (rtc->flags & OMAP_RTC_HAS_32KCLK_EN) { 443 if (rtc->type->has_32kclk_en) {
445 reg = rtc_read(rtc, OMAP_RTC_OSC_REG); 444 reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
446 rtc_writel(rtc, OMAP_RTC_OSC_REG, 445 rtc_writel(rtc, OMAP_RTC_OSC_REG,
447 reg | OMAP_RTC_OSC_32KCLK_EN); 446 reg | OMAP_RTC_OSC_32KCLK_EN);
@@ -511,7 +510,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
511 510
512err: 511err:
513 device_init_wakeup(&pdev->dev, false); 512 device_init_wakeup(&pdev->dev, false);
514 if (rtc->flags & OMAP_RTC_HAS_KICKER) 513 if (rtc->type->has_kicker)
515 rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); 514 rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0);
516 pm_runtime_put_sync(&pdev->dev); 515 pm_runtime_put_sync(&pdev->dev);
517 pm_runtime_disable(&pdev->dev); 516 pm_runtime_disable(&pdev->dev);
@@ -528,7 +527,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
528 /* leave rtc running, but disable irqs */ 527 /* leave rtc running, but disable irqs */
529 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); 528 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
530 529
531 if (rtc->flags & OMAP_RTC_HAS_KICKER) 530 if (rtc->type->has_kicker)
532 rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); 531 rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0);
533 532
534 /* Disable the clock/module */ 533 /* Disable the clock/module */
@@ -594,7 +593,7 @@ static struct platform_driver omap_rtc_driver = {
594 .pm = &omap_rtc_pm_ops, 593 .pm = &omap_rtc_pm_ops,
595 .of_match_table = omap_rtc_of_match, 594 .of_match_table = omap_rtc_of_match,
596 }, 595 },
597 .id_table = omap_rtc_devtype, 596 .id_table = omap_rtc_id_table,
598}; 597};
599 598
600module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); 599module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);