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)  	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 */  |