diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 111 |
1 files changed, 45 insertions, 66 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index c7ff8df347e..911e75cdc12 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
| 38 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
| 39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
| 40 | #include <linux/of.h> | ||
| 41 | #include <linux/of_platform.h> | ||
| 40 | 42 | ||
| 41 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
| 42 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
| @@ -375,50 +377,6 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 375 | return 0; | 377 | return 0; |
| 376 | } | 378 | } |
| 377 | 379 | ||
| 378 | static int cmos_irq_set_freq(struct device *dev, int freq) | ||
| 379 | { | ||
| 380 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
| 381 | int f; | ||
| 382 | unsigned long flags; | ||
| 383 | |||
| 384 | if (!is_valid_irq(cmos->irq)) | ||
| 385 | return -ENXIO; | ||
| 386 | |||
| 387 | if (!is_power_of_2(freq)) | ||
| 388 | return -EINVAL; | ||
| 389 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ | ||
| 390 | f = ffs(freq); | ||
| 391 | if (f-- > 16) | ||
| 392 | return -EINVAL; | ||
| 393 | f = 16 - f; | ||
| 394 | |||
| 395 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 396 | hpet_set_periodic_freq(freq); | ||
| 397 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | ||
| 398 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 399 | |||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int cmos_irq_set_state(struct device *dev, int enabled) | ||
| 404 | { | ||
| 405 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
| 406 | unsigned long flags; | ||
| 407 | |||
| 408 | if (!is_valid_irq(cmos->irq)) | ||
| 409 | return -ENXIO; | ||
| 410 | |||
| 411 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 412 | |||
| 413 | if (enabled) | ||
| 414 | cmos_irq_enable(cmos, RTC_PIE); | ||
| 415 | else | ||
| 416 | cmos_irq_disable(cmos, RTC_PIE); | ||
| 417 | |||
| 418 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | 380 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| 423 | { | 381 | { |
| 424 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 382 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| @@ -438,25 +396,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
| 438 | return 0; | 396 | return 0; |
| 439 | } | 397 | } |
| 440 | 398 | ||
| 441 | static int cmos_update_irq_enable(struct device *dev, unsigned int enabled) | ||
| 442 | { | ||
| 443 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
| 444 | unsigned long flags; | ||
| 445 | |||
| 446 | if (!is_valid_irq(cmos->irq)) | ||
| 447 | return -EINVAL; | ||
| 448 | |||
| 449 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 450 | |||
| 451 | if (enabled) | ||
| 452 | cmos_irq_enable(cmos, RTC_UIE); | ||
| 453 | else | ||
| 454 | cmos_irq_disable(cmos, RTC_UIE); | ||
| 455 | |||
| 456 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | 399 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) |
| 461 | 400 | ||
| 462 | static int cmos_procfs(struct device *dev, struct seq_file *seq) | 401 | static int cmos_procfs(struct device *dev, struct seq_file *seq) |
| @@ -501,10 +440,7 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
| 501 | .read_alarm = cmos_read_alarm, | 440 | .read_alarm = cmos_read_alarm, |
| 502 | .set_alarm = cmos_set_alarm, | 441 | .set_alarm = cmos_set_alarm, |
| 503 | .proc = cmos_procfs, | 442 | .proc = cmos_procfs, |
| 504 | .irq_set_freq = cmos_irq_set_freq, | ||
| 505 | .irq_set_state = cmos_irq_set_state, | ||
| 506 | .alarm_irq_enable = cmos_alarm_irq_enable, | 443 | .alarm_irq_enable = cmos_alarm_irq_enable, |
| 507 | .update_irq_enable = cmos_update_irq_enable, | ||
| 508 | }; | 444 | }; |
| 509 | 445 | ||
| 510 | /*----------------------------------------------------------------*/ | 446 | /*----------------------------------------------------------------*/ |
| @@ -1123,6 +1059,47 @@ static struct pnp_driver cmos_pnp_driver = { | |||
| 1123 | 1059 | ||
| 1124 | #endif /* CONFIG_PNP */ | 1060 | #endif /* CONFIG_PNP */ |
| 1125 | 1061 | ||
| 1062 | #ifdef CONFIG_OF | ||
| 1063 | static const struct of_device_id of_cmos_match[] = { | ||
| 1064 | { | ||
| 1065 | .compatible = "motorola,mc146818", | ||
| 1066 | }, | ||
| 1067 | { }, | ||
| 1068 | }; | ||
| 1069 | MODULE_DEVICE_TABLE(of, of_cmos_match); | ||
| 1070 | |||
| 1071 | static __init void cmos_of_init(struct platform_device *pdev) | ||
| 1072 | { | ||
| 1073 | struct device_node *node = pdev->dev.of_node; | ||
| 1074 | struct rtc_time time; | ||
| 1075 | int ret; | ||
| 1076 | const __be32 *val; | ||
| 1077 | |||
| 1078 | if (!node) | ||
| 1079 | return; | ||
| 1080 | |||
| 1081 | val = of_get_property(node, "ctrl-reg", NULL); | ||
| 1082 | if (val) | ||
| 1083 | CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL); | ||
| 1084 | |||
| 1085 | val = of_get_property(node, "freq-reg", NULL); | ||
| 1086 | if (val) | ||
| 1087 | CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); | ||
| 1088 | |||
| 1089 | get_rtc_time(&time); | ||
| 1090 | ret = rtc_valid_tm(&time); | ||
| 1091 | if (ret) { | ||
| 1092 | struct rtc_time def_time = { | ||
| 1093 | .tm_year = 1, | ||
| 1094 | .tm_mday = 1, | ||
| 1095 | }; | ||
| 1096 | set_rtc_time(&def_time); | ||
| 1097 | } | ||
| 1098 | } | ||
| 1099 | #else | ||
| 1100 | static inline void cmos_of_init(struct platform_device *pdev) {} | ||
| 1101 | #define of_cmos_match NULL | ||
| 1102 | #endif | ||
| 1126 | /*----------------------------------------------------------------*/ | 1103 | /*----------------------------------------------------------------*/ |
| 1127 | 1104 | ||
| 1128 | /* Platform setup should have set up an RTC device, when PNP is | 1105 | /* Platform setup should have set up an RTC device, when PNP is |
| @@ -1131,6 +1108,7 @@ static struct pnp_driver cmos_pnp_driver = { | |||
| 1131 | 1108 | ||
| 1132 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1109 | static int __init cmos_platform_probe(struct platform_device *pdev) |
| 1133 | { | 1110 | { |
| 1111 | cmos_of_init(pdev); | ||
| 1134 | cmos_wake_setup(&pdev->dev); | 1112 | cmos_wake_setup(&pdev->dev); |
| 1135 | return cmos_do_probe(&pdev->dev, | 1113 | return cmos_do_probe(&pdev->dev, |
| 1136 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1114 | platform_get_resource(pdev, IORESOURCE_IO, 0), |
| @@ -1162,6 +1140,7 @@ static struct platform_driver cmos_platform_driver = { | |||
| 1162 | #ifdef CONFIG_PM | 1140 | #ifdef CONFIG_PM |
| 1163 | .pm = &cmos_pm_ops, | 1141 | .pm = &cmos_pm_ops, |
| 1164 | #endif | 1142 | #endif |
| 1143 | .of_match_table = of_cmos_match, | ||
| 1165 | } | 1144 | } |
| 1166 | }; | 1145 | }; |
| 1167 | 1146 | ||
