aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2014-06-06 17:35:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:08:07 -0400
commit31632dbdba85aafc8a6772d578c5c14f84a1fe17 (patch)
treeda8e9658492bbd13eaadf29e238ee857fca15b8a /drivers/rtc
parent809d9627087e1db63b8672c1f264af73b13116fb (diff)
drivers/rtc/rtc-cmos.c: drivers/char/rtc.c features for DECstation support
This brings in drivers/char/rtc.c functionality required for DECstation and, should the maintainers decide to switch, Alpha systems to use rtc-cmos. Specifically these features are made available: * RTC iomem rather than x86/PCI port I/O mapping, controlled with the RTC_IOMAPPED macro as with the original driver. The DS1287A chip in all DECstation systems is mapped in the host bus address space as a contiguous block of 64 32-bit words of which the least significant byte accesses the RTC chip for both reads and writes. All the address and data window register accesses are made transparently by the chipset glue logic so that the device appears directly mapped on the host bus. * A way to set the size of the address space explicitly with the newly-added `address_space' member of the platform part of the RTC device structure. This avoids the unreliable heuristics that does not work in a setup where the RTC is not explicitly accessed with the usual address and data window register pair. * The ability to use the RTC periodic interrupt as a system clock device, which is implemented by arch/mips/kernel/cevt-ds1287.c for DECstation systems and takes the RTC interrupt away from the RTC driver. Eventually hooking back to the clock device's interrupt handler should be possible for the purpose of the alarm clock and possibly also update-in-progress interrupt, but this is not done by this change. o To avoid interfering with the clock interrupt all the places where the RTC interrupt mask is fiddled with are only executed if and IRQ has been assigned to the RTC driver. o To avoid changing the clock setup Register A is not fiddled with if CMOS_RTC_FLAGS_NOFREQ is set in the newly-added `flags' member of the platform part of the RTC device structure. Originally, in drivers/char/rtc.c, this was keyed with the absence of the RTC interrupt, just like the interrupt mask, but there only the periodic interrupt frequency is set, whereas rtc-cmos also sets the divider bits. Therefore a new flag is introduced so that systems where the RTC interrupt is not usable rather than used as a system clock device can fully initialise the RTC. * A small clean-up is made to the IRQ assignment code that makes the IRQ number hardcoded to -1 rather than arbitrary -ENXIO (or whatever error happens to be returned by platform_get_irq) where no IRQ has been assigned to the RTC driver (NO_IRQ might be another candidate, but it looks like this macro has inconsistent or missing definitions and limited use and might therefore be unsafe). Verified to work correctly with a DECstation 5000/240 system. [akpm@linux-foundation.org: fix weird code layout] Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-cmos.c85
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);
804cleanup0: 816cleanup0:
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
809static void cmos_do_shutdown(void) 824static 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
1066static void cmos_pnp_shutdown(struct pnp_dev *pnp) 1085static 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
1074static const struct pnp_device_id rtc_ids[] = { 1096static const struct pnp_device_id rtc_ids[] = {
@@ -1143,11 +1165,21 @@ static inline void cmos_of_init(struct platform_device *pdev) {}
1143 1165
1144static int __init cmos_platform_probe(struct platform_device *pdev) 1166static 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
1153static int __exit cmos_platform_remove(struct platform_device *pdev) 1185static 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
1159static void cmos_platform_shutdown(struct platform_device *pdev) 1191static 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 */