diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 0963c9309c74..b0e4a3eb33c7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -647,6 +647,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
647 | int retval = 0; | 647 | int retval = 0; |
648 | unsigned char rtc_control; | 648 | unsigned char rtc_control; |
649 | unsigned address_space; | 649 | unsigned address_space; |
650 | u32 flags = 0; | ||
650 | 651 | ||
651 | /* there can be only one ... */ | 652 | /* there can be only one ... */ |
652 | if (cmos_rtc.dev) | 653 | if (cmos_rtc.dev) |
@@ -660,9 +661,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
660 | * REVISIT non-x86 systems may instead use memory space resources | 661 | * REVISIT non-x86 systems may instead use memory space resources |
661 | * (needing ioremap etc), not i/o space resources like this ... | 662 | * (needing ioremap etc), not i/o space resources like this ... |
662 | */ | 663 | */ |
663 | ports = request_region(ports->start, | 664 | if (RTC_IOMAPPED) |
664 | resource_size(ports), | 665 | ports = request_region(ports->start, resource_size(ports), |
665 | driver_name); | 666 | driver_name); |
667 | else | ||
668 | ports = request_mem_region(ports->start, resource_size(ports), | ||
669 | driver_name); | ||
666 | if (!ports) { | 670 | if (!ports) { |
667 | dev_dbg(dev, "i/o registers already in use\n"); | 671 | dev_dbg(dev, "i/o registers already in use\n"); |
668 | return -EBUSY; | 672 | return -EBUSY; |
@@ -699,6 +703,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
699 | * expect CMOS_READ and friends to handle. | 703 | * expect CMOS_READ and friends to handle. |
700 | */ | 704 | */ |
701 | if (info) { | 705 | if (info) { |
706 | if (info->flags) | ||
707 | flags = info->flags; | ||
708 | if (info->address_space) | ||
709 | address_space = info->address_space; | ||
710 | |||
702 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) | 711 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) |
703 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 712 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
704 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) | 713 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) |
@@ -726,18 +735,21 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
726 | 735 | ||
727 | spin_lock_irq(&rtc_lock); | 736 | spin_lock_irq(&rtc_lock); |
728 | 737 | ||
729 | /* force periodic irq to CMOS reset default of 1024Hz; | 738 | if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) { |
730 | * | 739 | /* force periodic irq to CMOS reset default of 1024Hz; |
731 | * REVISIT it's been reported that at least one x86_64 ALI mobo | 740 | * |
732 | * doesn't use 32KHz here ... for portability we might need to | 741 | * REVISIT it's been reported that at least one x86_64 ALI |
733 | * do something about other clock frequencies. | 742 | * mobo doesn't use 32KHz here ... for portability we might |
734 | */ | 743 | * need to do something about other clock frequencies. |
735 | cmos_rtc.rtc->irq_freq = 1024; | 744 | */ |
736 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); | 745 | cmos_rtc.rtc->irq_freq = 1024; |
737 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | 746 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); |
747 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
748 | } | ||
738 | 749 | ||
739 | /* disable irqs */ | 750 | /* disable irqs */ |
740 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | 751 | if (is_valid_irq(rtc_irq)) |
752 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | ||
741 | 753 | ||
742 | rtc_control = CMOS_READ(RTC_CONTROL); | 754 | rtc_control = CMOS_READ(RTC_CONTROL); |
743 | 755 | ||
@@ -802,14 +814,18 @@ cleanup1: | |||
802 | cmos_rtc.dev = NULL; | 814 | cmos_rtc.dev = NULL; |
803 | rtc_device_unregister(cmos_rtc.rtc); | 815 | rtc_device_unregister(cmos_rtc.rtc); |
804 | cleanup0: | 816 | cleanup0: |
805 | release_region(ports->start, resource_size(ports)); | 817 | if (RTC_IOMAPPED) |
818 | release_region(ports->start, resource_size(ports)); | ||
819 | else | ||
820 | release_mem_region(ports->start, resource_size(ports)); | ||
806 | return retval; | 821 | return retval; |
807 | } | 822 | } |
808 | 823 | ||
809 | static void cmos_do_shutdown(void) | 824 | static void cmos_do_shutdown(int rtc_irq) |
810 | { | 825 | { |
811 | spin_lock_irq(&rtc_lock); | 826 | spin_lock_irq(&rtc_lock); |
812 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); | 827 | if (is_valid_irq(rtc_irq)) |
828 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); | ||
813 | spin_unlock_irq(&rtc_lock); | 829 | spin_unlock_irq(&rtc_lock); |
814 | } | 830 | } |
815 | 831 | ||
@@ -818,7 +834,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
818 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 834 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
819 | struct resource *ports; | 835 | struct resource *ports; |
820 | 836 | ||
821 | cmos_do_shutdown(); | 837 | cmos_do_shutdown(cmos->irq); |
822 | 838 | ||
823 | sysfs_remove_bin_file(&dev->kobj, &nvram); | 839 | sysfs_remove_bin_file(&dev->kobj, &nvram); |
824 | 840 | ||
@@ -831,7 +847,10 @@ static void __exit cmos_do_remove(struct device *dev) | |||
831 | cmos->rtc = NULL; | 847 | cmos->rtc = NULL; |
832 | 848 | ||
833 | ports = cmos->iomem; | 849 | ports = cmos->iomem; |
834 | release_region(ports->start, resource_size(ports)); | 850 | if (RTC_IOMAPPED) |
851 | release_region(ports->start, resource_size(ports)); | ||
852 | else | ||
853 | release_mem_region(ports->start, resource_size(ports)); | ||
835 | cmos->iomem = NULL; | 854 | cmos->iomem = NULL; |
836 | 855 | ||
837 | cmos->dev = NULL; | 856 | cmos->dev = NULL; |
@@ -1065,10 +1084,13 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | |||
1065 | 1084 | ||
1066 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) | 1085 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) |
1067 | { | 1086 | { |
1068 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) | 1087 | struct device *dev = &pnp->dev; |
1088 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
1089 | |||
1090 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) | ||
1069 | return; | 1091 | return; |
1070 | 1092 | ||
1071 | cmos_do_shutdown(); | 1093 | cmos_do_shutdown(cmos->irq); |
1072 | } | 1094 | } |
1073 | 1095 | ||
1074 | static const struct pnp_device_id rtc_ids[] = { | 1096 | static const struct pnp_device_id rtc_ids[] = { |
@@ -1143,11 +1165,21 @@ static inline void cmos_of_init(struct platform_device *pdev) {} | |||
1143 | 1165 | ||
1144 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1166 | static int __init cmos_platform_probe(struct platform_device *pdev) |
1145 | { | 1167 | { |
1168 | struct resource *resource; | ||
1169 | int irq; | ||
1170 | |||
1146 | cmos_of_init(pdev); | 1171 | cmos_of_init(pdev); |
1147 | cmos_wake_setup(&pdev->dev); | 1172 | cmos_wake_setup(&pdev->dev); |
1148 | return cmos_do_probe(&pdev->dev, | 1173 | |
1149 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1174 | if (RTC_IOMAPPED) |
1150 | platform_get_irq(pdev, 0)); | 1175 | resource = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1176 | else | ||
1177 | resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1178 | irq = platform_get_irq(pdev, 0); | ||
1179 | if (irq < 0) | ||
1180 | irq = -1; | ||
1181 | |||
1182 | return cmos_do_probe(&pdev->dev, resource, irq); | ||
1151 | } | 1183 | } |
1152 | 1184 | ||
1153 | static int __exit cmos_platform_remove(struct platform_device *pdev) | 1185 | static int __exit cmos_platform_remove(struct platform_device *pdev) |
@@ -1158,10 +1190,13 @@ static int __exit cmos_platform_remove(struct platform_device *pdev) | |||
1158 | 1190 | ||
1159 | static void cmos_platform_shutdown(struct platform_device *pdev) | 1191 | static void cmos_platform_shutdown(struct platform_device *pdev) |
1160 | { | 1192 | { |
1161 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev)) | 1193 | struct device *dev = &pdev->dev; |
1194 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
1195 | |||
1196 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) | ||
1162 | return; | 1197 | return; |
1163 | 1198 | ||
1164 | cmos_do_shutdown(); | 1199 | cmos_do_shutdown(cmos->irq); |
1165 | } | 1200 | } |
1166 | 1201 | ||
1167 | /* work with hotplug and coldplug */ | 1202 | /* work with hotplug and coldplug */ |