diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 130 |
1 files changed, 56 insertions, 74 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5856167a0c9..911e75cdc12 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
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> | ||
40 | #include <linux/of.h> | ||
41 | #include <linux/of_platform.h> | ||
39 | 42 | ||
40 | /* 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 */ |
41 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
@@ -374,50 +377,6 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
374 | return 0; | 377 | return 0; |
375 | } | 378 | } |
376 | 379 | ||
377 | static int cmos_irq_set_freq(struct device *dev, int freq) | ||
378 | { | ||
379 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
380 | int f; | ||
381 | unsigned long flags; | ||
382 | |||
383 | if (!is_valid_irq(cmos->irq)) | ||
384 | return -ENXIO; | ||
385 | |||
386 | if (!is_power_of_2(freq)) | ||
387 | return -EINVAL; | ||
388 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ | ||
389 | f = ffs(freq); | ||
390 | if (f-- > 16) | ||
391 | return -EINVAL; | ||
392 | f = 16 - f; | ||
393 | |||
394 | spin_lock_irqsave(&rtc_lock, flags); | ||
395 | hpet_set_periodic_freq(freq); | ||
396 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | ||
397 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int cmos_irq_set_state(struct device *dev, int enabled) | ||
403 | { | ||
404 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
405 | unsigned long flags; | ||
406 | |||
407 | if (!is_valid_irq(cmos->irq)) | ||
408 | return -ENXIO; | ||
409 | |||
410 | spin_lock_irqsave(&rtc_lock, flags); | ||
411 | |||
412 | if (enabled) | ||
413 | cmos_irq_enable(cmos, RTC_PIE); | ||
414 | else | ||
415 | cmos_irq_disable(cmos, RTC_PIE); | ||
416 | |||
417 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | 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) |
422 | { | 381 | { |
423 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 382 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
@@ -437,25 +396,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
437 | return 0; | 396 | return 0; |
438 | } | 397 | } |
439 | 398 | ||
440 | static int cmos_update_irq_enable(struct device *dev, unsigned int enabled) | ||
441 | { | ||
442 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
443 | unsigned long flags; | ||
444 | |||
445 | if (!is_valid_irq(cmos->irq)) | ||
446 | return -EINVAL; | ||
447 | |||
448 | spin_lock_irqsave(&rtc_lock, flags); | ||
449 | |||
450 | if (enabled) | ||
451 | cmos_irq_enable(cmos, RTC_UIE); | ||
452 | else | ||
453 | cmos_irq_disable(cmos, RTC_UIE); | ||
454 | |||
455 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | #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) |
460 | 400 | ||
461 | static int cmos_procfs(struct device *dev, struct seq_file *seq) | 401 | static int cmos_procfs(struct device *dev, struct seq_file *seq) |
@@ -500,10 +440,7 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
500 | .read_alarm = cmos_read_alarm, | 440 | .read_alarm = cmos_read_alarm, |
501 | .set_alarm = cmos_set_alarm, | 441 | .set_alarm = cmos_set_alarm, |
502 | .proc = cmos_procfs, | 442 | .proc = cmos_procfs, |
503 | .irq_set_freq = cmos_irq_set_freq, | ||
504 | .irq_set_state = cmos_irq_set_state, | ||
505 | .alarm_irq_enable = cmos_alarm_irq_enable, | 443 | .alarm_irq_enable = cmos_alarm_irq_enable, |
506 | .update_irq_enable = cmos_update_irq_enable, | ||
507 | }; | 444 | }; |
508 | 445 | ||
509 | /*----------------------------------------------------------------*/ | 446 | /*----------------------------------------------------------------*/ |
@@ -687,7 +624,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
687 | #if defined(CONFIG_ATARI) | 624 | #if defined(CONFIG_ATARI) |
688 | address_space = 64; | 625 | address_space = 64; |
689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ | 626 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) | 627 | || defined(__sparc__) || defined(__mips__) \ |
628 | || defined(__powerpc__) | ||
691 | address_space = 128; | 629 | address_space = 128; |
692 | #else | 630 | #else |
693 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 631 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
@@ -850,7 +788,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
850 | 788 | ||
851 | #ifdef CONFIG_PM | 789 | #ifdef CONFIG_PM |
852 | 790 | ||
853 | static int cmos_suspend(struct device *dev, pm_message_t mesg) | 791 | static int cmos_suspend(struct device *dev) |
854 | { | 792 | { |
855 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 793 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
856 | unsigned char tmp; | 794 | unsigned char tmp; |
@@ -898,7 +836,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
898 | */ | 836 | */ |
899 | static inline int cmos_poweroff(struct device *dev) | 837 | static inline int cmos_poweroff(struct device *dev) |
900 | { | 838 | { |
901 | return cmos_suspend(dev, PMSG_HIBERNATE); | 839 | return cmos_suspend(dev); |
902 | } | 840 | } |
903 | 841 | ||
904 | static int cmos_resume(struct device *dev) | 842 | static int cmos_resume(struct device *dev) |
@@ -945,9 +883,9 @@ static int cmos_resume(struct device *dev) | |||
945 | return 0; | 883 | return 0; |
946 | } | 884 | } |
947 | 885 | ||
886 | static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); | ||
887 | |||
948 | #else | 888 | #else |
949 | #define cmos_suspend NULL | ||
950 | #define cmos_resume NULL | ||
951 | 889 | ||
952 | static inline int cmos_poweroff(struct device *dev) | 890 | static inline int cmos_poweroff(struct device *dev) |
953 | { | 891 | { |
@@ -1077,7 +1015,7 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | |||
1077 | 1015 | ||
1078 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) | 1016 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) |
1079 | { | 1017 | { |
1080 | return cmos_suspend(&pnp->dev, mesg); | 1018 | return cmos_suspend(&pnp->dev); |
1081 | } | 1019 | } |
1082 | 1020 | ||
1083 | static int cmos_pnp_resume(struct pnp_dev *pnp) | 1021 | static int cmos_pnp_resume(struct pnp_dev *pnp) |
@@ -1121,6 +1059,47 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1121 | 1059 | ||
1122 | #endif /* CONFIG_PNP */ | 1060 | #endif /* CONFIG_PNP */ |
1123 | 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 | ||
1124 | /*----------------------------------------------------------------*/ | 1103 | /*----------------------------------------------------------------*/ |
1125 | 1104 | ||
1126 | /* 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 |
@@ -1129,6 +1108,7 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1129 | 1108 | ||
1130 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1109 | static int __init cmos_platform_probe(struct platform_device *pdev) |
1131 | { | 1110 | { |
1111 | cmos_of_init(pdev); | ||
1132 | cmos_wake_setup(&pdev->dev); | 1112 | cmos_wake_setup(&pdev->dev); |
1133 | return cmos_do_probe(&pdev->dev, | 1113 | return cmos_do_probe(&pdev->dev, |
1134 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1114 | platform_get_resource(pdev, IORESOURCE_IO, 0), |
@@ -1157,8 +1137,10 @@ static struct platform_driver cmos_platform_driver = { | |||
1157 | .shutdown = cmos_platform_shutdown, | 1137 | .shutdown = cmos_platform_shutdown, |
1158 | .driver = { | 1138 | .driver = { |
1159 | .name = (char *) driver_name, | 1139 | .name = (char *) driver_name, |
1160 | .suspend = cmos_suspend, | 1140 | #ifdef CONFIG_PM |
1161 | .resume = cmos_resume, | 1141 | .pm = &cmos_pm_ops, |
1142 | #endif | ||
1143 | .of_match_table = of_cmos_match, | ||
1162 | } | 1144 | } |
1163 | }; | 1145 | }; |
1164 | 1146 | ||