diff options
author | Johan Hovold <johan@kernel.org> | 2014-12-10 18:53:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 20:41:14 -0500 |
commit | 2153f94943ca6c47df585205bfde0c5f1311f84b (patch) | |
tree | f9bd4be441536bd2d35848adf4173b924cf34518 /drivers/rtc/rtc-omap.c | |
parent | a430ca22676e270508edb8d74d6fb895cf74584b (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.c | 103 |
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) | 105 | struct 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 | ||
119 | struct omap_rtc { | 111 | struct 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 | ||
128 | static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg) | 120 | static 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 | 348 | static const struct omap_rtc_device_type omap_rtc_default_type = { |
357 | #define OMAP_RTC_DATA_DA830_IDX 2 | 349 | }; |
350 | |||
351 | static 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 | |||
357 | static const struct omap_rtc_device_type omap_rtc_da830_type = { | ||
358 | .has_kicker = true, | ||
359 | }; | ||
358 | 360 | ||
359 | static const struct platform_device_id omap_rtc_devtype[] = { | 361 | static 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 | }; |
374 | MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); | 375 | MODULE_DEVICE_TABLE(platform, omap_rtc_id_table); |
375 | 376 | ||
376 | static const struct of_device_id omap_rtc_of_match[] = { | 377 | static 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 | }; |
385 | MODULE_DEVICE_TABLE(of, omap_rtc_of_match); | 388 | MODULE_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 | ||
512 | err: | 511 | err: |
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 | ||
600 | module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); | 599 | module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); |