diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 20 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/rtc/class.c | 65 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 55 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at32ap700x.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1286.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 1 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1511.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1742.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m48t35.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m48t59.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-mpc5121.c | 81 | ||||
| -rw-r--r-- | drivers/rtc/rtc-mrst.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pm8xxx.c | 550 | ||||
| -rw-r--r-- | drivers/rtc/rtc-puv3.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s3c.c | 32 | ||||
| -rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 153 | ||||
| -rw-r--r-- | drivers/rtc/rtc-tegra.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-twl.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-vt8500.c | 51 | 
21 files changed, 855 insertions, 186 deletions
| diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ce2aabf5c55..5a538fc1cc8 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -981,11 +981,11 @@ config RTC_DRV_COH901331  config RTC_DRV_STMP -	tristate "Freescale STMP3xxx RTC" -	depends on ARCH_STMP3XXX +	tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC" +	depends on ARCH_MXS  	help  	  If you say yes here you will get support for the onboard -	  STMP3xxx RTC. +	  STMP3xxx/i.MX23/i.MX28 RTC.  	  This driver can also be built as a module. If so, the module  	  will be called rtc-stmp3xxx. @@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX  config RTC_DRV_MPC5121  	tristate "Freescale MPC5121 built-in RTC" -	depends on PPC_MPC512x && RTC_CLASS +	depends on PPC_MPC512x || PPC_MPC52xx  	help  	  If you say yes here you will get support for the -	  built-in RTC MPC5121. +	  built-in RTC on MPC5121 or on MPC5200.  	  This driver can also be built as a module. If so, the module  	  will be called rtc-mpc5121. @@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX  	  This driver can also be buillt as a module. If so, the module  	  will be called rtc-lpc32xx. +config RTC_DRV_PM8XXX +	tristate "Qualcomm PMIC8XXX RTC" +	depends on MFD_PM8XXX +	help +	  If you say yes here you get support for the +	  Qualcomm PMIC8XXX RTC. + +	  To compile this driver as a module, choose M here: the +	  module will be called rtc-pm8xxx. +  config RTC_DRV_TEGRA  	tristate "NVIDIA Tegra Internal RTC driver"  	depends on RTC_CLASS && ARCH_TEGRA diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0ffefe877bf..6e6982335c1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o  obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o  obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o  obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o +obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o  obj-$(CONFIG_RTC_DRV_PS3)	+= rtc-ps3.o  obj-$(CONFIG_RTC_DRV_PUV3)	+= rtc-puv3.o  obj-$(CONFIG_RTC_DRV_PXA)	+= rtc-pxa.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14c..01a7df5317c 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev)   * system's wall clock; restore it on resume().   */ -static time_t		oldtime; -static struct timespec	oldts; +static struct timespec old_rtc, old_system, old_delta; +  static int rtc_suspend(struct device *dev, pm_message_t mesg)  {  	struct rtc_device	*rtc = to_rtc_device(dev);  	struct rtc_time		tm; - +	struct timespec		delta, delta_delta;  	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)  		return 0; +	/* snapshot the current RTC and system time at suspend*/  	rtc_read_time(rtc, &tm); -	ktime_get_ts(&oldts); -	rtc_tm_to_time(&tm, &oldtime); +	getnstimeofday(&old_system); +	rtc_tm_to_time(&tm, &old_rtc.tv_sec); + + +	/* +	 * To avoid drift caused by repeated suspend/resumes, +	 * which each can add ~1 second drift error, +	 * try to compensate so the difference in system time +	 * and rtc time stays close to constant. +	 */ +	delta = timespec_sub(old_system, old_rtc); +	delta_delta = timespec_sub(delta, old_delta); +	if (abs(delta_delta.tv_sec)  >= 2) { +		/* +		 * if delta_delta is too large, assume time correction +		 * has occured and set old_delta to the current delta. +		 */ +		old_delta = delta; +	} else { +		/* Otherwise try to adjust old_system to compensate */ +		old_system = timespec_sub(old_system, delta_delta); +	}  	return 0;  } @@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev)  {  	struct rtc_device	*rtc = to_rtc_device(dev);  	struct rtc_time		tm; -	time_t			newtime; -	struct timespec		time; -	struct timespec		newts; +	struct timespec		new_system, new_rtc; +	struct timespec		sleep_time;  	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)  		return 0; -	ktime_get_ts(&newts); +	/* snapshot the current rtc and system time at resume */ +	getnstimeofday(&new_system);  	rtc_read_time(rtc, &tm);  	if (rtc_valid_tm(&tm) != 0) {  		pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));  		return 0;  	} -	rtc_tm_to_time(&tm, &newtime); -	if (newtime <= oldtime) { -		if (newtime < oldtime) +	rtc_tm_to_time(&tm, &new_rtc.tv_sec); +	new_rtc.tv_nsec = 0; + +	if (new_rtc.tv_sec <= old_rtc.tv_sec) { +		if (new_rtc.tv_sec < old_rtc.tv_sec)  			pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));  		return 0;  	} -	/* calculate the RTC time delta */ -	set_normalized_timespec(&time, newtime - oldtime, 0); -	/* subtract kernel time between rtc_suspend to rtc_resume */ -	time = timespec_sub(time, timespec_sub(newts, oldts)); +	/* calculate the RTC time delta (sleep time)*/ +	sleep_time = timespec_sub(new_rtc, old_rtc); + +	/* +	 * Since these RTC suspend/resume handlers are not called +	 * at the very end of suspend or the start of resume, +	 * some run-time may pass on either sides of the sleep time +	 * so subtract kernel run-time between rtc_suspend to rtc_resume +	 * to keep things accurate. +	 */ +	sleep_time = timespec_sub(sleep_time, +			timespec_sub(new_system, old_system)); -	timekeeping_inject_sleeptime(&time); +	timekeeping_inject_sleeptime(&sleep_time);  	return 0;  } diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index df68618f6db..3195dbd3ec3 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -636,6 +636,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)  }  EXPORT_SYMBOL_GPL(rtc_irq_unregister); +static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) +{ +	/* +	 * We unconditionally cancel the timer here, because otherwise +	 * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); +	 * when we manage to start the timer before the callback +	 * returns HRTIMER_RESTART. +	 * +	 * We cannot use hrtimer_cancel() here as a running callback +	 * could be blocked on rtc->irq_task_lock and hrtimer_cancel() +	 * would spin forever. +	 */ +	if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0) +		return -1; + +	if (enabled) { +		ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq); + +		hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); +	} +	return 0; +} +  /**   * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs   * @rtc: the rtc device @@ -651,21 +674,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled  	int err = 0;  	unsigned long flags; +retry:  	spin_lock_irqsave(&rtc->irq_task_lock, flags);  	if (rtc->irq_task != NULL && task == NULL)  		err = -EBUSY;  	if (rtc->irq_task != task)  		err = -EACCES; - -	if (enabled) { -		ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); -		hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); -	} else { -		hrtimer_cancel(&rtc->pie_timer); +	if (!err) { +		if (rtc_update_hrtimer(rtc, enabled) < 0) { +			spin_unlock_irqrestore(&rtc->irq_task_lock, flags); +			cpu_relax(); +			goto retry; +		} +		rtc->pie_enabled = enabled;  	} -	rtc->pie_enabled = enabled;  	spin_unlock_irqrestore(&rtc->irq_task_lock, flags); -  	return err;  }  EXPORT_SYMBOL_GPL(rtc_irq_set_state); @@ -685,22 +708,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)  	int err = 0;  	unsigned long flags; -	if (freq <= 0) +	if (freq <= 0 || freq > 5000)  		return -EINVAL; - +retry:  	spin_lock_irqsave(&rtc->irq_task_lock, flags);  	if (rtc->irq_task != NULL && task == NULL)  		err = -EBUSY;  	if (rtc->irq_task != task)  		err = -EACCES; -	if (err == 0) { +	if (!err) {  		rtc->irq_freq = freq; -		if (rtc->pie_enabled) { -			ktime_t period; -			hrtimer_cancel(&rtc->pie_timer); -			period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); -			hrtimer_start(&rtc->pie_timer, period, -					HRTIMER_MODE_REL); +		if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { +			spin_unlock_irqrestore(&rtc->irq_task_lock, flags); +			cpu_relax(); +			goto retry;  		}  	}  	spin_unlock_irqrestore(&rtc->irq_task_lock, flags); diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index e725d51e773..8dd08305aae 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c @@ -223,7 +223,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)  	}  	rtc->irq = irq; -	rtc->regs = ioremap(regs->start, regs->end - regs->start + 1); +	rtc->regs = ioremap(regs->start, resource_size(regs));  	if (!rtc->regs) {  		ret = -ENOMEM;  		dev_dbg(&pdev->dev, "could not map I/O memory\n"); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 911e75cdc12..05beb6c1ca7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -606,7 +606,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)  	 * (needing ioremap etc), not i/o space resources like this ...  	 */  	ports = request_region(ports->start, -			ports->end + 1 - ports->start, +			resource_size(ports),  			driver_name);  	if (!ports) {  		dev_dbg(dev, "i/o registers already in use\n"); @@ -750,7 +750,7 @@ cleanup1:  	cmos_rtc.dev = NULL;  	rtc_device_unregister(cmos_rtc.rtc);  cleanup0: -	release_region(ports->start, ports->end + 1 - ports->start); +	release_region(ports->start, resource_size(ports));  	return retval;  } @@ -779,7 +779,7 @@ static void __exit cmos_do_remove(struct device *dev)  	cmos->rtc = NULL;  	ports = cmos->iomem; -	release_region(ports->start, ports->end + 1 - ports->start); +	release_region(ports->start, resource_size(ports));  	cmos->iomem = NULL;  	cmos->dev = NULL; diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 47e681df31e..68e6caf2549 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -343,7 +343,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev)  	if (!priv)  		return -ENOMEM; -	priv->size = res->end - res->start + 1; +	priv->size = resource_size(res);  	if (!request_mem_region(res->start, priv->size, pdev->name)) {  		ret = -EBUSY;  		goto out; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4724ba3acf1..b2005b44e4f 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -149,6 +149,7 @@ static const struct i2c_device_id ds1307_id[] = {  	{ "ds1340", ds_1340 },  	{ "ds3231", ds_3231 },  	{ "m41t00", m41t00 }, +	{ "pt7c4338", ds_1307 },  	{ "rx8025", rx_8025 },  	{ }  }; diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index fbabc773dde..568ad30617e 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -490,7 +490,7 @@ ds1511_rtc_probe(struct platform_device *pdev)  	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);  	if (!pdata)  		return -ENOMEM; -	pdata->size = res->end - res->start + 1; +	pdata->size = resource_size(res);  	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,  			pdev->name))  		return -EBUSY; diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 042630c90dd..d84a448dd75 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -173,7 +173,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev)  	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);  	if (!pdata)  		return -ENOMEM; -	pdata->size = res->end - res->start + 1; +	pdata->size = resource_size(res);  	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,  		pdev->name))  		return -EBUSY; diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 7410875e583..8e2a24e33ed 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -154,7 +154,7 @@ static int __devinit m48t35_probe(struct platform_device *pdev)  	if (!priv)  		return -ENOMEM; -	priv->size = res->end - res->start + 1; +	priv->size = resource_size(res);  	/*  	 * kludge: remove the #ifndef after ioc3 resource  	 * conflicts are resolved diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 3978f4caf72..28365388fb6 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -433,7 +433,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)  	if (!m48t59->ioaddr) {  		/* ioaddr not mapped externally */ -		m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); +		m48t59->ioaddr = ioremap(res->start, resource_size(res));  		if (!m48t59->ioaddr)  			goto out;  	} diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2..da60915818b 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -3,6 +3,7 @@   *   * Copyright 2007, Domen Puncer <domen.puncer@telargo.com>   * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. + * Copyright 2011, Dmitry Eremin-Solenikov   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 as @@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return 0;  } +static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs; +	int tmp; + +	tm->tm_sec = in_8(®s->second); +	tm->tm_min = in_8(®s->minute); + +	/* 12 hour format? */ +	if (in_8(®s->hour) & 0x20) +		tm->tm_hour = (in_8(®s->hour) >> 1) + +			(in_8(®s->hour) & 1 ? 12 : 0); +	else +		tm->tm_hour = in_8(®s->hour); + +	tmp = in_8(®s->wday_mday); +	tm->tm_mday = tmp & 0x1f; +	tm->tm_mon = in_8(®s->month) - 1; +	tm->tm_year = in_be16(®s->year) - 1900; +	tm->tm_wday = (tmp >> 5) % 7; +	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); +	tm->tm_isdst = 0; + +	return 0; +} + +static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs; + +	mpc5121_rtc_update_smh(regs, tm); + +	/* date */ +	out_8(®s->month_set, tm->tm_mon + 1); +	out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); +	out_8(®s->date_set, tm->tm_mday); +	out_be16(®s->year_set, tm->tm_year + 1900); + +	/* set date sequence */ +	out_8(®s->set_date, 0x1); +	out_8(®s->set_date, 0x3); +	out_8(®s->set_date, 0x1); +	out_8(®s->set_date, 0x0); + +	return 0; +} +  static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)  {  	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); @@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = {  	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,  }; +static const struct rtc_class_ops mpc5200_rtc_ops = { +	.read_time = mpc5200_rtc_read_time, +	.set_time = mpc5200_rtc_set_time, +	.read_alarm = mpc5121_rtc_read_alarm, +	.set_alarm = mpc5121_rtc_set_alarm, +	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, +}; +  static int __devinit mpc5121_rtc_probe(struct platform_device *op)  {  	struct mpc5121_rtc_data *rtc;  	int err = 0; -	u32 ka;  	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);  	if (!rtc) @@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)  		goto out_dispose2;  	} -	ka = in_be32(&rtc->regs->keep_alive); -	if (ka & 0x02) { -		dev_warn(&op->dev, -			"mpc5121-rtc: Battery or oscillator failure!\n"); -		out_be32(&rtc->regs->keep_alive, ka); +	if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { +		u32 ka; +		ka = in_be32(&rtc->regs->keep_alive); +		if (ka & 0x02) { +			dev_warn(&op->dev, +				"mpc5121-rtc: Battery or oscillator failure!\n"); +			out_be32(&rtc->regs->keep_alive, ka); +		} + +		rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, +						&mpc5121_rtc_ops, THIS_MODULE); +	} else { +		rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, +						&mpc5200_rtc_ops, THIS_MODULE);  	} -	rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, -					&mpc5121_rtc_ops, THIS_MODULE);  	if (IS_ERR(rtc->rtc)) {  		err = PTR_ERR(rtc->rtc);  		goto out_free_irq; @@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)  static struct of_device_id mpc5121_rtc_match[] __devinitdata = {  	{ .compatible = "fsl,mpc5121-rtc", }, +	{ .compatible = "fsl,mpc5200-rtc", },  	{},  }; diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 0cec5650d56..d33544802a2 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -332,9 +332,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)  	if (!iomem)  		return -ENODEV; -	iomem = request_mem_region(iomem->start, -			iomem->end + 1 - iomem->start, -			driver_name); +	iomem = request_mem_region(iomem->start, resource_size(iomem), +				   driver_name);  	if (!iomem) {  		dev_dbg(dev, "i/o mem already in use.\n");  		return -EBUSY; diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c new file mode 100644 index 00000000000..d420e9d877e --- /dev/null +++ b/drivers/rtc/rtc-pm8xxx.c @@ -0,0 +1,550 @@ +/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/rtc.h> +#include <linux/pm.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include <linux/mfd/pm8xxx/core.h> +#include <linux/mfd/pm8xxx/rtc.h> + + +/* RTC Register offsets from RTC CTRL REG */ +#define PM8XXX_ALARM_CTRL_OFFSET	0x01 +#define PM8XXX_RTC_WRITE_OFFSET		0x02 +#define PM8XXX_RTC_READ_OFFSET		0x06 +#define PM8XXX_ALARM_RW_OFFSET		0x0A + +/* RTC_CTRL register bit fields */ +#define PM8xxx_RTC_ENABLE		BIT(7) +#define PM8xxx_RTC_ALARM_ENABLE		BIT(1) +#define PM8xxx_RTC_ALARM_CLEAR		BIT(0) + +#define NUM_8_BIT_RTC_REGS		0x4 + +/** + * struct pm8xxx_rtc -  rtc driver internal structure + * @rtc:		rtc device for this driver. + * @rtc_alarm_irq:	rtc alarm irq number. + * @rtc_base:		address of rtc control register. + * @rtc_read_base:	base address of read registers. + * @rtc_write_base:	base address of write registers. + * @alarm_rw_base:	base address of alarm registers. + * @ctrl_reg:		rtc control register. + * @rtc_dev:		device structure. + * @ctrl_reg_lock:	spinlock protecting access to ctrl_reg. + */ +struct pm8xxx_rtc { +	struct rtc_device *rtc; +	int rtc_alarm_irq; +	int rtc_base; +	int rtc_read_base; +	int rtc_write_base; +	int alarm_rw_base; +	u8  ctrl_reg; +	struct device *rtc_dev; +	spinlock_t ctrl_reg_lock; +}; + +/* + * The RTC registers need to be read/written one byte at a time. This is a + * hardware limitation. + */ +static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, +		int base, int count) +{ +	int i, rc; +	struct device *parent = rtc_dd->rtc_dev->parent; + +	for (i = 0; i < count; i++) { +		rc = pm8xxx_readb(parent, base + i, &rtc_val[i]); +		if (rc < 0) { +			dev_err(rtc_dd->rtc_dev, "PMIC read failed\n"); +			return rc; +		} +	} + +	return 0; +} + +static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, +		int base, int count) +{ +	int i, rc; +	struct device *parent = rtc_dd->rtc_dev->parent; + +	for (i = 0; i < count; i++) { +		rc = pm8xxx_writeb(parent, base + i, rtc_val[i]); +		if (rc < 0) { +			dev_err(rtc_dd->rtc_dev, "PMIC write failed\n"); +			return rc; +		} +	} + +	return 0; +} + +/* + * Steps to write the RTC registers. + * 1. Disable alarm if enabled. + * 2. Write 0x00 to LSB. + * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. + * 4. Enable alarm if disabled in step 1. + */ +static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	int rc, i; +	unsigned long secs, irq_flags; +	u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg; +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	rtc_tm_to_time(tm, &secs); + +	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { +		value[i] = secs & 0xFF; +		secs >>= 8; +	} + +	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); + +	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); +	ctrl_reg = rtc_dd->ctrl_reg; + +	if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) { +		alarm_enabled = 1; +		ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; +		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, +				1); +		if (rc < 0) { +			dev_err(dev, "Write to RTC control register " +								"failed\n"); +			goto rtc_rw_fail; +		} +		rtc_dd->ctrl_reg = ctrl_reg; +	} else +		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); + +	/* Write 0 to Byte[0] */ +	reg = 0; +	rc = pm8xxx_write_wrapper(rtc_dd, ®, rtc_dd->rtc_write_base, 1); +	if (rc < 0) { +		dev_err(dev, "Write to RTC write data register failed\n"); +		goto rtc_rw_fail; +	} + +	/* Write Byte[1], Byte[2], Byte[3] */ +	rc = pm8xxx_write_wrapper(rtc_dd, value + 1, +					rtc_dd->rtc_write_base + 1, 3); +	if (rc < 0) { +		dev_err(dev, "Write to RTC write data register failed\n"); +		goto rtc_rw_fail; +	} + +	/* Write Byte[0] */ +	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1); +	if (rc < 0) { +		dev_err(dev, "Write to RTC write data register failed\n"); +		goto rtc_rw_fail; +	} + +	if (alarm_enabled) { +		ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE; +		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, +									1); +		if (rc < 0) { +			dev_err(dev, "Write to RTC control register " +								"failed\n"); +			goto rtc_rw_fail; +		} +		rtc_dd->ctrl_reg = ctrl_reg; +	} + +rtc_rw_fail: +	if (alarm_enabled) +		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); + +	return rc; +} + +static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	int rc; +	u8 value[NUM_8_BIT_RTC_REGS], reg; +	unsigned long secs; +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base, +							NUM_8_BIT_RTC_REGS); +	if (rc < 0) { +		dev_err(dev, "RTC read data register failed\n"); +		return rc; +	} + +	/* +	 * Read the LSB again and check if there has been a carry over. +	 * If there is, redo the read operation. +	 */ +	rc = pm8xxx_read_wrapper(rtc_dd, ®, rtc_dd->rtc_read_base, 1); +	if (rc < 0) { +		dev_err(dev, "RTC read data register failed\n"); +		return rc; +	} + +	if (unlikely(reg < value[0])) { +		rc = pm8xxx_read_wrapper(rtc_dd, value, +				rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS); +		if (rc < 0) { +			dev_err(dev, "RTC read data register failed\n"); +			return rc; +		} +	} + +	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); + +	rtc_time_to_tm(secs, tm); + +	rc = rtc_valid_tm(tm); +	if (rc < 0) { +		dev_err(dev, "Invalid time read from RTC\n"); +		return rc; +	} + +	dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", +				secs, tm->tm_hour, tm->tm_min, tm->tm_sec, +				tm->tm_mday, tm->tm_mon, tm->tm_year); + +	return 0; +} + +static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	int rc, i; +	u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg; +	unsigned long secs, irq_flags; +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	rtc_tm_to_time(&alarm->time, &secs); + +	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { +		value[i] = secs & 0xFF; +		secs >>= 8; +	} + +	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); + +	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, +							NUM_8_BIT_RTC_REGS); +	if (rc < 0) { +		dev_err(dev, "Write to RTC ALARM register failed\n"); +		goto rtc_rw_fail; +	} + +	ctrl_reg = rtc_dd->ctrl_reg; +	ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : +					(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); + +	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); +	if (rc < 0) { +		dev_err(dev, "Write to RTC control register failed\n"); +		goto rtc_rw_fail; +	} + +	rtc_dd->ctrl_reg = ctrl_reg; + +	dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", +				alarm->time.tm_hour, alarm->time.tm_min, +				alarm->time.tm_sec, alarm->time.tm_mday, +				alarm->time.tm_mon, alarm->time.tm_year); +rtc_rw_fail: +	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); +	return rc; +} + +static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	int rc; +	u8 value[NUM_8_BIT_RTC_REGS]; +	unsigned long secs; +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, +			NUM_8_BIT_RTC_REGS); +	if (rc < 0) { +		dev_err(dev, "RTC alarm time read failed\n"); +		return rc; +	} + +	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); + +	rtc_time_to_tm(secs, &alarm->time); + +	rc = rtc_valid_tm(&alarm->time); +	if (rc < 0) { +		dev_err(dev, "Invalid alarm time read from RTC\n"); +		return rc; +	} + +	dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", +				alarm->time.tm_hour, alarm->time.tm_min, +				alarm->time.tm_sec, alarm->time.tm_mday, +				alarm->time.tm_mon, alarm->time.tm_year); + +	return 0; +} + +static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ +	int rc; +	unsigned long irq_flags; +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); +	u8 ctrl_reg; + +	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); +	ctrl_reg = rtc_dd->ctrl_reg; +	ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : +				(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); + +	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); +	if (rc < 0) { +		dev_err(dev, "Write to RTC control register failed\n"); +		goto rtc_rw_fail; +	} + +	rtc_dd->ctrl_reg = ctrl_reg; + +rtc_rw_fail: +	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); +	return rc; +} + +static struct rtc_class_ops pm8xxx_rtc_ops = { +	.read_time	= pm8xxx_rtc_read_time, +	.set_alarm	= pm8xxx_rtc_set_alarm, +	.read_alarm	= pm8xxx_rtc_read_alarm, +	.alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, +}; + +static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) +{ +	struct pm8xxx_rtc *rtc_dd = dev_id; +	u8 ctrl_reg; +	int rc; +	unsigned long irq_flags; + +	rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); + +	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); + +	/* Clear the alarm enable bit */ +	ctrl_reg = rtc_dd->ctrl_reg; +	ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; + +	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); +	if (rc < 0) { +		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); +		dev_err(rtc_dd->rtc_dev, "Write to RTC control register " +								"failed\n"); +		goto rtc_alarm_handled; +	} + +	rtc_dd->ctrl_reg = ctrl_reg; +	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); + +	/* Clear RTC alarm register */ +	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + +						PM8XXX_ALARM_CTRL_OFFSET, 1); +	if (rc < 0) { +		dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read " +								"failed\n"); +		goto rtc_alarm_handled; +	} + +	ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR; +	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + +						PM8XXX_ALARM_CTRL_OFFSET, 1); +	if (rc < 0) +		dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register" +								" failed\n"); + +rtc_alarm_handled: +	return IRQ_HANDLED; +} + +static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) +{ +	int rc; +	u8 ctrl_reg; +	bool rtc_write_enable = false; +	struct pm8xxx_rtc *rtc_dd; +	struct resource *rtc_resource; +	const struct pm8xxx_rtc_platform_data *pdata = +						dev_get_platdata(&pdev->dev); + +	if (pdata != NULL) +		rtc_write_enable = pdata->rtc_write_enable; + +	rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL); +	if (rtc_dd == NULL) { +		dev_err(&pdev->dev, "Unable to allocate memory!\n"); +		return -ENOMEM; +	} + +	/* Initialise spinlock to protect RTC control register */ +	spin_lock_init(&rtc_dd->ctrl_reg_lock); + +	rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); +	if (rtc_dd->rtc_alarm_irq < 0) { +		dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); +		rc = -ENXIO; +		goto fail_rtc_enable; +	} + +	rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO, +							"pmic_rtc_base"); +	if (!(rtc_resource && rtc_resource->start)) { +		dev_err(&pdev->dev, "RTC IO resource absent!\n"); +		rc = -ENXIO; +		goto fail_rtc_enable; +	} + +	rtc_dd->rtc_base = rtc_resource->start; + +	/* Setup RTC register addresses */ +	rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET; +	rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET; +	rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET; + +	rtc_dd->rtc_dev = &pdev->dev; + +	/* Check if the RTC is on, else turn it on */ +	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); +	if (rc < 0) { +		dev_err(&pdev->dev, "RTC control register read failed!\n"); +		goto fail_rtc_enable; +	} + +	if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) { +		ctrl_reg |= PM8xxx_RTC_ENABLE; +		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, +									1); +		if (rc < 0) { +			dev_err(&pdev->dev, "Write to RTC control register " +								"failed\n"); +			goto fail_rtc_enable; +		} +	} + +	rtc_dd->ctrl_reg = ctrl_reg; +	if (rtc_write_enable == true) +		pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time; + +	platform_set_drvdata(pdev, rtc_dd); + +	/* Register the RTC device */ +	rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev, +				&pm8xxx_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc_dd->rtc)) { +		dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", +					__func__, PTR_ERR(rtc_dd->rtc)); +		rc = PTR_ERR(rtc_dd->rtc); +		goto fail_rtc_enable; +	} + +	/* Request the alarm IRQ */ +	rc = request_any_context_irq(rtc_dd->rtc_alarm_irq, +				 pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING, +				 "pm8xxx_rtc_alarm", rtc_dd); +	if (rc < 0) { +		dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc); +		goto fail_req_irq; +	} + +	device_init_wakeup(&pdev->dev, 1); + +	dev_dbg(&pdev->dev, "Probe success !!\n"); + +	return 0; + +fail_req_irq: +	rtc_device_unregister(rtc_dd->rtc); +fail_rtc_enable: +	platform_set_drvdata(pdev, NULL); +	kfree(rtc_dd); +	return rc; +} + +static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) +{ +	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); + +	device_init_wakeup(&pdev->dev, 0); +	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd); +	rtc_device_unregister(rtc_dd->rtc); +	platform_set_drvdata(pdev, NULL); +	kfree(rtc_dd); + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pm8xxx_rtc_resume(struct device *dev) +{ +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		disable_irq_wake(rtc_dd->rtc_alarm_irq); + +	return 0; +} + +static int pm8xxx_rtc_suspend(struct device *dev) +{ +	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		enable_irq_wake(rtc_dd->rtc_alarm_irq); + +	return 0; +} +#endif + +SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); + +static struct platform_driver pm8xxx_rtc_driver = { +	.probe		= pm8xxx_rtc_probe, +	.remove		= __devexit_p(pm8xxx_rtc_remove), +	.driver	= { +		.name	= PM8XXX_RTC_DEV_NAME, +		.owner	= THIS_MODULE, +		.pm	= &pm8xxx_rtc_pm_ops, +	}, +}; + +static int __init pm8xxx_rtc_init(void) +{ +	return platform_driver_register(&pm8xxx_rtc_driver); +} +module_init(pm8xxx_rtc_init); + +static void __exit pm8xxx_rtc_exit(void) +{ +	platform_driver_unregister(&pm8xxx_rtc_driver); +} +module_exit(pm8xxx_rtc_exit); + +MODULE_ALIAS("platform:rtc-pm8xxx"); +MODULE_DESCRIPTION("PMIC8xxx RTC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>"); diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 46f14b82f3a..b3eba3cddd4 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -267,9 +267,8 @@ static int puv3_rtc_probe(struct platform_device *pdev)  		return -ENOENT;  	} -	puv3_rtc_mem = request_mem_region(res->start, -					 res->end-res->start+1, -					 pdev->name); +	puv3_rtc_mem = request_mem_region(res->start, resource_size(res), +					  pdev->name);  	if (puv3_rtc_mem == NULL) {  		dev_err(&pdev->dev, "failed to reserve memory region\n"); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 16512ecae31..9329dbb9eba 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)  {  	struct rtc_device *rdev = id; +	clk_enable(rtc_clk);  	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);  	if (s3c_rtc_cpu_type == TYPE_S3C64XX)  		writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); +	clk_disable(rtc_clk);  	return IRQ_HANDLED;  } @@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)  {  	struct rtc_device *rdev = id; +	clk_enable(rtc_clk);  	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);  	if (s3c_rtc_cpu_type == TYPE_S3C64XX)  		writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); +	clk_disable(rtc_clk);  	return IRQ_HANDLED;  } @@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)  	pr_debug("%s: aie=%d\n", __func__, enabled); +	clk_enable(rtc_clk);  	tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;  	if (enabled)  		tmp |= S3C2410_RTCALM_ALMEN;  	writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); +	clk_disable(rtc_clk);  	return 0;  } @@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)  	if (!is_power_of_2(freq))  		return -EINVAL; +	clk_enable(rtc_clk);  	spin_lock_irq(&s3c_rtc_pie_lock);  	if (s3c_rtc_cpu_type == TYPE_S3C2410) { @@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)  	writel(tmp, s3c_rtc_base + S3C2410_TICNT);  	spin_unlock_irq(&s3c_rtc_pie_lock); +	clk_disable(rtc_clk);  	return 0;  } @@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  	unsigned int have_retried = 0;  	void __iomem *base = s3c_rtc_base; +	clk_enable(rtc_clk);   retry_get_time:  	rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);  	rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); @@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  	rtc_tm->tm_year += 100;  	rtc_tm->tm_mon -= 1; +	clk_disable(rtc_clk);  	return rtc_valid_tm(rtc_tm);  } @@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)  	void __iomem *base = s3c_rtc_base;  	int year = tm->tm_year - 100; +	clk_enable(rtc_clk);  	pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",  		 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,  		 tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)  	writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);  	writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);  	writeb(bin2bcd(year), base + S3C2410_RTCYEAR); +	clk_disable(rtc_clk);  	return 0;  } @@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)  	void __iomem *base = s3c_rtc_base;  	unsigned int alm_en; +	clk_enable(rtc_clk);  	alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);  	alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);  	alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); @@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)  	else  		alm_tm->tm_year = -1; +	clk_disable(rtc_clk);  	return 0;  } @@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  	void __iomem *base = s3c_rtc_base;  	unsigned int alrm_en; +	clk_enable(rtc_clk);  	pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",  		 alrm->enabled,  		 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, @@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  	s3c_rtc_setaie(dev, alrm->enabled); +	clk_disable(rtc_clk);  	return 0;  } @@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)  {  	unsigned int ticnt; +	clk_enable(rtc_clk);  	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {  		ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);  		ticnt &= S3C64XX_RTCCON_TICEN; @@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)  	}  	seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no"); +	clk_disable(rtc_clk);  	return 0;  } @@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)  	if (s3c_rtc_base == NULL)  		return; +	clk_enable(rtc_clk);  	if (!en) {  		tmp = readw(base + S3C2410_RTCCON);  		if (s3c_rtc_cpu_type == TYPE_S3C64XX) @@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)  				base + S3C2410_RTCCON);  		}  	} +	clk_disable(rtc_clk);  }  static int __devexit s3c_rtc_remove(struct platform_device *dev) @@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)  	s3c_rtc_setaie(&dev->dev, 0); -	clk_disable(rtc_clk);  	clk_put(rtc_clk);  	rtc_clk = NULL; @@ -455,8 +474,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)  		return -ENOENT;  	} -	s3c_rtc_mem = request_mem_region(res->start, -					 res->end-res->start+1, +	s3c_rtc_mem = request_mem_region(res->start, resource_size(res),  					 pdev->name);  	if (s3c_rtc_mem == NULL) { @@ -465,7 +483,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)  		goto err_nores;  	} -	s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); +	s3c_rtc_base = ioremap(res->start, resource_size(res));  	if (s3c_rtc_base == NULL) {  		dev_err(&pdev->dev, "failed ioremap()\n");  		ret = -EINVAL; @@ -530,6 +548,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)  	s3c_rtc_setfreq(&pdev->dev, 1); +	clk_disable(rtc_clk); +  	return 0;   err_nortc: @@ -555,6 +575,7 @@ static int ticnt_save, ticnt_en_save;  static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)  { +	clk_enable(rtc_clk);  	/* save TICNT for anyone using periodic interrupts */  	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);  	if (s3c_rtc_cpu_type == TYPE_S3C64XX) { @@ -569,6 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)  		else  			dev_err(&pdev->dev, "enable_irq_wake failed\n");  	} +	clk_disable(rtc_clk);  	return 0;  } @@ -577,6 +599,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)  {  	unsigned int tmp; +	clk_enable(rtc_clk);  	s3c_rtc_enable(pdev, 1);  	writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);  	if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { @@ -588,6 +611,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)  		disable_irq_wake(s3c_rtc_alarmno);  		wake_en = false;  	} +	clk_disable(rtc_clk);  	return 0;  } diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 572e9534b59..7315068daa5 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -6,6 +6,7 @@   *   * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.   * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + * Copyright 2011 Wolfram Sang, Pengutronix e.K.   */  /* @@ -18,21 +19,41 @@   */  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/io.h>  #include <linux/init.h>  #include <linux/platform_device.h>  #include <linux/interrupt.h>  #include <linux/rtc.h>  #include <linux/slab.h> -#include <mach/platform.h> -#include <mach/stmp3xxx.h> -#include <mach/regs-rtc.h> +#include <mach/common.h> + +#define STMP3XXX_RTC_CTRL			0x0 +#define STMP3XXX_RTC_CTRL_SET			0x4 +#define STMP3XXX_RTC_CTRL_CLR			0x8 +#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN		0x00000001 +#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002 +#define STMP3XXX_RTC_CTRL_ALARM_IRQ		0x00000004 + +#define STMP3XXX_RTC_STAT			0x10 +#define STMP3XXX_RTC_STAT_STALE_SHIFT		16 +#define STMP3XXX_RTC_STAT_RTC_PRESENT		0x80000000 + +#define STMP3XXX_RTC_SECONDS			0x30 + +#define STMP3XXX_RTC_ALARM			0x40 + +#define STMP3XXX_RTC_PERSISTENT0		0x60 +#define STMP3XXX_RTC_PERSISTENT0_SET		0x64 +#define STMP3XXX_RTC_PERSISTENT0_CLR		0x68 +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002 +#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN	0x00000004 +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE	0x00000080  struct stmp3xxx_rtc_data {  	struct rtc_device *rtc; -	unsigned irq_count;  	void __iomem *io; -	int irq_alarm, irq_1msec; +	int irq_alarm;  };  static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) @@ -42,8 +63,8 @@ static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)  	 * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,  	 * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS  	 */ -	while (__raw_readl(rtc_data->io + HW_RTC_STAT) & -			BF(0x80, RTC_STAT_STALE_REGS)) +	while (readl(rtc_data->io + STMP3XXX_RTC_STAT) & +			(0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))  		cpu_relax();  } @@ -53,7 +74,7 @@ static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);  	stmp3xxx_wait_time(rtc_data); -	rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm); +	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);  	return 0;  } @@ -61,7 +82,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)  {  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); -	__raw_writel(t, rtc_data->io + HW_RTC_SECONDS); +	writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);  	stmp3xxx_wait_time(rtc_data);  	return 0;  } @@ -70,47 +91,34 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)  static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)  {  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); -	u32 status; -	u32 events = 0; - -	status = __raw_readl(rtc_data->io + HW_RTC_CTRL) & -			(BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ); +	u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL); -	if (status & BM_RTC_CTRL_ALARM_IRQ) { -		stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ, -				rtc_data->io + HW_RTC_CTRL); -		events |= RTC_AF | RTC_IRQF; +	if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) { +		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ, +				rtc_data->io + STMP3XXX_RTC_CTRL_CLR); +		rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF); +		return IRQ_HANDLED;  	} -	if (status & BM_RTC_CTRL_ONEMSEC_IRQ) { -		stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ, -				rtc_data->io + HW_RTC_CTRL); -		if (++rtc_data->irq_count % 1000 == 0) { -			events |= RTC_UF | RTC_IRQF; -			rtc_data->irq_count = 0; -		} -	} - -	if (events) -		rtc_update_irq(rtc_data->rtc, 1, events); - -	return IRQ_HANDLED; +	return IRQ_NONE;  }  static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)  {  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); -	void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0, -		     *ctl = rtc_data->io + HW_RTC_CTRL;  	if (enabled) { -		stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN | -			      BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); -		stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); +		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | +				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, +				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); +		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, +				rtc_data->io + STMP3XXX_RTC_CTRL_SET);  	} else { -		stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | -			      BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); -		stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); +		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | +				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, +				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); +		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, +				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);  	}  	return 0;  } @@ -119,7 +127,7 @@ static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  {  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); -	rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time); +	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);  	return 0;  } @@ -129,7 +137,10 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);  	rtc_tm_to_time(&alm->time, &t); -	__raw_writel(t, rtc_data->io + HW_RTC_ALARM); +	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM); + +	stmp3xxx_alarm_irq_enable(dev, alm->enabled); +  	return 0;  } @@ -149,11 +160,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)  	if (!rtc_data)  		return 0; -	stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, -			rtc_data->io + HW_RTC_CTRL); +	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, +			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);  	free_irq(rtc_data->irq_alarm, &pdev->dev); -	free_irq(rtc_data->irq_1msec, &pdev->dev);  	rtc_device_unregister(rtc_data->rtc); +	platform_set_drvdata(pdev, NULL);  	iounmap(rtc_data->io);  	kfree(rtc_data); @@ -185,20 +196,26 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)  	}  	rtc_data->irq_alarm = platform_get_irq(pdev, 0); -	rtc_data->irq_1msec = platform_get_irq(pdev, 1); -	if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) & -			BM_RTC_STAT_RTC_PRESENT)) { +	if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & +			STMP3XXX_RTC_STAT_RTC_PRESENT)) {  		dev_err(&pdev->dev, "no device onboard\n");  		err = -ENODEV;  		goto out_remap;  	} -	stmp3xxx_reset_block(rtc_data->io, true); -	stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | -			BM_RTC_PERSISTENT0_ALARM_WAKE_EN | -			BM_RTC_PERSISTENT0_ALARM_WAKE, -			rtc_data->io + HW_RTC_PERSISTENT0); +	platform_set_drvdata(pdev, rtc_data); + +	mxs_reset_block(rtc_data->io); +	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | +			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | +			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); + +	writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | +			STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, +			rtc_data->io + STMP3XXX_RTC_CTRL_CLR); +  	rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,  				&stmp3xxx_rtc_ops, THIS_MODULE);  	if (IS_ERR(rtc_data->rtc)) { @@ -206,33 +223,20 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)  		goto out_remap;  	} -	rtc_data->irq_count = 0; -	err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, -			IRQF_DISABLED, "RTC alarm", &pdev->dev); +	err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0, +			"RTC alarm", &pdev->dev);  	if (err) {  		dev_err(&pdev->dev, "Cannot claim IRQ%d\n",  			rtc_data->irq_alarm);  		goto out_irq_alarm;  	} -	err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt, -			IRQF_DISABLED, "RTC tick", &pdev->dev); -	if (err) { -		dev_err(&pdev->dev, "Cannot claim IRQ%d\n", -			rtc_data->irq_1msec); -		goto out_irq1; -	} - -	platform_set_drvdata(pdev, rtc_data);  	return 0; -out_irq1: -	free_irq(rtc_data->irq_alarm, &pdev->dev);  out_irq_alarm: -	stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, -			rtc_data->io + HW_RTC_CTRL);  	rtc_device_unregister(rtc_data->rtc);  out_remap: +	platform_set_drvdata(pdev, NULL);  	iounmap(rtc_data->io);  out_free:  	kfree(rtc_data); @@ -249,11 +253,11 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)  {  	struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); -	stmp3xxx_reset_block(rtc_data->io, true); -	stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | -			BM_RTC_PERSISTENT0_ALARM_WAKE_EN | -			BM_RTC_PERSISTENT0_ALARM_WAKE, -			rtc_data->io + HW_RTC_PERSISTENT0); +	mxs_reset_block(rtc_data->io); +	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | +			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | +			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);  	return 0;  }  #else @@ -286,5 +290,6 @@ module_init(stmp3xxx_rtc_init);  module_exit(stmp3xxx_rtc_exit);  MODULE_DESCRIPTION("STMP3xxx RTC Driver"); -MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>"); +MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " +		"Wolfram Sang <w.sang@pengutronix.de>");  MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 2fc31aac3f4..75259fe3860 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)  	/* set context info. */  	info->pdev = pdev; -	info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock); +	spin_lock_init(&info->tegra_rtc_lock);  	platform_set_drvdata(pdev, info); diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index f9a2799c44d..9a81f778d6b 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)  		goto out;  	save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; -	twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); +	ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);  	if (ret < 0)  		goto out; diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index b8bc862903a..f93f412423c 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -74,11 +74,12 @@  #define VT8500_RTC_CR_SM_SEC	(1 << 3)	/* 0: 1Hz/60, 1: 1Hz */  #define VT8500_RTC_CR_CALIB	(1 << 4)	/* Enable calibration */ +#define VT8500_RTC_IS_ALARM	(1 << 0)	/* Alarm interrupt status */ +  struct vt8500_rtc {  	void __iomem		*regbase;  	struct resource		*res;  	int			irq_alarm; -	int			irq_hz;  	struct rtc_device	*rtc;  	spinlock_t		lock;		/* Protects this structure */  }; @@ -97,13 +98,9 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)  	spin_unlock(&vt8500_rtc->lock); -	if (isr & 1) +	if (isr & VT8500_RTC_IS_ALARM)  		events |= RTC_AF | RTC_IRQF; -	/* Only second/minute interrupts are supported */ -	if (isr & 2) -		events |= RTC_UF | RTC_IRQF; -  	rtc_update_irq(vt8500_rtc->rtc, 1, events);  	return IRQ_HANDLED; @@ -166,8 +163,8 @@ static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)  	alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK));  	alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; +	alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0; -	alrm->pending = (isr & 1) ? 1 : 0;  	return rtc_valid_tm(&alrm->time);  } @@ -199,27 +196,12 @@ static int vt8500_alarm_irq_enable(struct device *dev, unsigned int enabled)  	return 0;  } -static int vt8500_update_irq_enable(struct device *dev, unsigned int enabled) -{ -	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); -	unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR); - -	if (enabled) -		tmp |= VT8500_RTC_CR_SM_SEC | VT8500_RTC_CR_SM_ENABLE; -	else -		tmp &= ~VT8500_RTC_CR_SM_ENABLE; - -	writel(tmp, vt8500_rtc->regbase + VT8500_RTC_CR); -	return 0; -} -  static const struct rtc_class_ops vt8500_rtc_ops = {  	.read_time = vt8500_rtc_read_time,  	.set_time = vt8500_rtc_set_time,  	.read_alarm = vt8500_rtc_read_alarm,  	.set_alarm = vt8500_rtc_set_alarm,  	.alarm_irq_enable = vt8500_alarm_irq_enable, -	.update_irq_enable = vt8500_update_irq_enable,  };  static int __devinit vt8500_rtc_probe(struct platform_device *pdev) @@ -248,13 +230,6 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)  		goto err_free;  	} -	vt8500_rtc->irq_hz = platform_get_irq(pdev, 1); -	if (vt8500_rtc->irq_hz < 0) { -		dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); -		ret = -ENXIO; -		goto err_free; -	} -  	vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start,  					     resource_size(vt8500_rtc->res),  					     "vt8500-rtc"); @@ -272,9 +247,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)  		goto err_release;  	} -	/* Enable the second/minute interrupt generation and enable RTC */ -	writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H -		| VT8500_RTC_CR_SM_ENABLE | VT8500_RTC_CR_SM_SEC, +	/* Enable RTC and set it to 24-hour mode */ +	writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H,  	       vt8500_rtc->regbase + VT8500_RTC_CR);  	vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, @@ -286,26 +260,16 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)  		goto err_unmap;  	} -	ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, 0, -			  "rtc 1Hz", vt8500_rtc); -	if (ret < 0) { -		dev_err(&pdev->dev, "can't get irq %i, err %d\n", -			vt8500_rtc->irq_hz, ret); -		goto err_unreg; -	} -  	ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0,  			  "rtc alarm", vt8500_rtc);  	if (ret < 0) {  		dev_err(&pdev->dev, "can't get irq %i, err %d\n",  			vt8500_rtc->irq_alarm, ret); -		goto err_free_hz; +		goto err_unreg;  	}  	return 0; -err_free_hz: -	free_irq(vt8500_rtc->irq_hz, vt8500_rtc);  err_unreg:  	rtc_device_unregister(vt8500_rtc->rtc);  err_unmap: @@ -323,7 +287,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev)  	struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);  	free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); -	free_irq(vt8500_rtc->irq_hz, vt8500_rtc);  	rtc_device_unregister(vt8500_rtc->rtc); | 
