|
@@ -647,6 +647,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|
|
int retval = 0;
|
|
|
unsigned char rtc_control;
|
|
|
unsigned address_space;
|
|
|
+ u32 flags = 0;
|
|
|
|
|
|
/* there can be only one ... */
|
|
|
if (cmos_rtc.dev)
|
|
@@ -660,9 +661,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|
|
* REVISIT non-x86 systems may instead use memory space resources
|
|
|
* (needing ioremap etc), not i/o space resources like this ...
|
|
|
*/
|
|
|
- ports = request_region(ports->start,
|
|
|
- resource_size(ports),
|
|
|
- driver_name);
|
|
|
+ if (RTC_IOMAPPED)
|
|
|
+ ports = request_region(ports->start, resource_size(ports),
|
|
|
+ driver_name);
|
|
|
+ else
|
|
|
+ ports = request_mem_region(ports->start, resource_size(ports),
|
|
|
+ driver_name);
|
|
|
if (!ports) {
|
|
|
dev_dbg(dev, "i/o registers already in use\n");
|
|
|
return -EBUSY;
|
|
@@ -699,6 +703,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|
|
* expect CMOS_READ and friends to handle.
|
|
|
*/
|
|
|
if (info) {
|
|
|
+ if (info->flags)
|
|
|
+ flags = info->flags;
|
|
|
+ if (info->address_space)
|
|
|
+ address_space = info->address_space;
|
|
|
+
|
|
|
if (info->rtc_day_alarm && info->rtc_day_alarm < 128)
|
|
|
cmos_rtc.day_alrm = info->rtc_day_alarm;
|
|
|
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)
|
|
|
|
|
|
spin_lock_irq(&rtc_lock);
|
|
|
|
|
|
- /* force periodic irq to CMOS reset default of 1024Hz;
|
|
|
- *
|
|
|
- * REVISIT it's been reported that at least one x86_64 ALI mobo
|
|
|
- * doesn't use 32KHz here ... for portability we might need to
|
|
|
- * do something about other clock frequencies.
|
|
|
- */
|
|
|
- cmos_rtc.rtc->irq_freq = 1024;
|
|
|
- hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
|
|
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
|
|
+ if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
|
|
|
+ /* force periodic irq to CMOS reset default of 1024Hz;
|
|
|
+ *
|
|
|
+ * REVISIT it's been reported that at least one x86_64 ALI
|
|
|
+ * mobo doesn't use 32KHz here ... for portability we might
|
|
|
+ * need to do something about other clock frequencies.
|
|
|
+ */
|
|
|
+ cmos_rtc.rtc->irq_freq = 1024;
|
|
|
+ hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
|
|
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
|
|
+ }
|
|
|
|
|
|
/* disable irqs */
|
|
|
- cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
|
|
|
+ if (is_valid_irq(rtc_irq))
|
|
|
+ cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
|
|
|
|
|
|
rtc_control = CMOS_READ(RTC_CONTROL);
|
|
|
|
|
@@ -802,14 +814,18 @@ cleanup1:
|
|
|
cmos_rtc.dev = NULL;
|
|
|
rtc_device_unregister(cmos_rtc.rtc);
|
|
|
cleanup0:
|
|
|
- release_region(ports->start, resource_size(ports));
|
|
|
+ if (RTC_IOMAPPED)
|
|
|
+ release_region(ports->start, resource_size(ports));
|
|
|
+ else
|
|
|
+ release_mem_region(ports->start, resource_size(ports));
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
-static void cmos_do_shutdown(void)
|
|
|
+static void cmos_do_shutdown(int rtc_irq)
|
|
|
{
|
|
|
spin_lock_irq(&rtc_lock);
|
|
|
- cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
|
|
|
+ if (is_valid_irq(rtc_irq))
|
|
|
+ cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
|
|
|
spin_unlock_irq(&rtc_lock);
|
|
|
}
|
|
|
|
|
@@ -818,7 +834,7 @@ static void __exit cmos_do_remove(struct device *dev)
|
|
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
|
|
struct resource *ports;
|
|
|
|
|
|
- cmos_do_shutdown();
|
|
|
+ cmos_do_shutdown(cmos->irq);
|
|
|
|
|
|
sysfs_remove_bin_file(&dev->kobj, &nvram);
|
|
|
|
|
@@ -831,7 +847,10 @@ static void __exit cmos_do_remove(struct device *dev)
|
|
|
cmos->rtc = NULL;
|
|
|
|
|
|
ports = cmos->iomem;
|
|
|
- release_region(ports->start, resource_size(ports));
|
|
|
+ if (RTC_IOMAPPED)
|
|
|
+ release_region(ports->start, resource_size(ports));
|
|
|
+ else
|
|
|
+ release_mem_region(ports->start, resource_size(ports));
|
|
|
cmos->iomem = NULL;
|
|
|
|
|
|
cmos->dev = NULL;
|
|
@@ -1065,10 +1084,13 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
|
|
|
|
|
|
static void cmos_pnp_shutdown(struct pnp_dev *pnp)
|
|
|
{
|
|
|
- if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
|
|
|
+ struct device *dev = &pnp->dev;
|
|
|
+ struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
|
|
|
return;
|
|
|
|
|
|
- cmos_do_shutdown();
|
|
|
+ cmos_do_shutdown(cmos->irq);
|
|
|
}
|
|
|
|
|
|
static const struct pnp_device_id rtc_ids[] = {
|
|
@@ -1143,11 +1165,21 @@ static inline void cmos_of_init(struct platform_device *pdev) {}
|
|
|
|
|
|
static int __init cmos_platform_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
+ struct resource *resource;
|
|
|
+ int irq;
|
|
|
+
|
|
|
cmos_of_init(pdev);
|
|
|
cmos_wake_setup(&pdev->dev);
|
|
|
- return cmos_do_probe(&pdev->dev,
|
|
|
- platform_get_resource(pdev, IORESOURCE_IO, 0),
|
|
|
- platform_get_irq(pdev, 0));
|
|
|
+
|
|
|
+ if (RTC_IOMAPPED)
|
|
|
+ resource = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
|
|
+ else
|
|
|
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
+ irq = platform_get_irq(pdev, 0);
|
|
|
+ if (irq < 0)
|
|
|
+ irq = -1;
|
|
|
+
|
|
|
+ return cmos_do_probe(&pdev->dev, resource, irq);
|
|
|
}
|
|
|
|
|
|
static int __exit cmos_platform_remove(struct platform_device *pdev)
|
|
@@ -1158,10 +1190,13 @@ static int __exit cmos_platform_remove(struct platform_device *pdev)
|
|
|
|
|
|
static void cmos_platform_shutdown(struct platform_device *pdev)
|
|
|
{
|
|
|
- if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev))
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
+ struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
|
|
|
return;
|
|
|
|
|
|
- cmos_do_shutdown();
|
|
|
+ cmos_do_shutdown(cmos->irq);
|
|
|
}
|
|
|
|
|
|
/* work with hotplug and coldplug */
|