diff options
Diffstat (limited to 'drivers/rtc')
47 files changed, 2829 insertions, 253 deletions
| diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 923a9da9c829..e6ab071fb6fd 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -20,14 +20,24 @@ if RTC_CLASS  config RTC_HCTOSYS  	bool "Set system time from RTC on startup and resume"  	default y +	depends on !ALWAYS_USE_PERSISTENT_CLOCK  	help  	  If you say yes here, the system time (wall clock) will be set using  	  the value read from a specified RTC device. This is useful to avoid  	  unnecessary fsck runs at boot time, and to network better. +config RTC_SYSTOHC +	bool "Set the RTC time based on NTP synchronization" +	default y +	depends on !ALWAYS_USE_PERSISTENT_CLOCK +	help +	  If you say yes here, the system time (wall clock) will be stored +	  in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11 +	  minutes if userspace reports synchronized NTP status. +  config RTC_HCTOSYS_DEVICE  	string "RTC used to set the system time" -	depends on RTC_HCTOSYS = y +	depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y  	default "rtc0"  	help  	  The RTC device that will be used to (re)initialize the system @@ -194,6 +204,12 @@ config RTC_DRV_DS3232  	  This driver can also be built as a module.  If so, the module  	  will be called rtc-ds3232. +config RTC_DRV_LP8788 +	tristate "TI LP8788 RTC driver" +	depends on MFD_LP8788 +	help +	  Say Y to enable support for the LP8788 RTC/ALARM driver. +  config RTC_DRV_MAX6900  	tristate "Maxim MAX6900"  	help @@ -233,6 +249,26 @@ config RTC_DRV_MAX8998  	  This driver can also be built as a module. If so, the module  	  will be called rtc-max8998. +config RTC_DRV_MAX8997 +	tristate "Maxim MAX8997" +	depends on MFD_MAX8997 +	help +	  If you say yes here you will get support for the +	  RTC of Maxim MAX8997 PMIC. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-max8997. + +config RTC_DRV_MAX77686 +	tristate "Maxim MAX77686" +	depends on MFD_MAX77686 +	help +	  If you say yes here you will get support for the +	  RTC of Maxim MAX77686 PMIC. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-max77686. +  config RTC_DRV_RS5C372  	tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"  	help @@ -370,6 +406,14 @@ config RTC_DRV_TPS65910  	  This driver can also be built as a module. If so, the module  	  will be called rtc-tps65910. +config RTC_DRV_TPS80031 +	tristate "TI TPS80031/TPS80032 RTC driver" +	depends on MFD_TPS80031 +	help +	  TI Power Managment IC TPS80031 supports RTC functionality +	  along with alarm. This driver supports the RTC driver for +	  the TPS80031 RTC module. +  config RTC_DRV_RC5T583  	tristate "RICOH 5T583 RTC driver"  	depends on MFD_RC5T583 @@ -527,6 +571,14 @@ config RTC_DRV_PCF2123  	  This driver can also be built as a module. If so, the module  	  will be called rtc-pcf2123. +config RTC_DRV_RX4581 +	tristate "Epson RX-4581" +	help +	  If you say yes here you will get support for the Epson RX-4581. + +	  This driver can also be built as a module. If so the module +	  will be called rtc-rx4581. +  endif # SPI_MASTER  comment "Platform RTC drivers" @@ -1023,7 +1075,7 @@ config RTC_DRV_TX4939  config RTC_DRV_MV  	tristate "Marvell SoC RTC" -	depends on ARCH_KIRKWOOD || ARCH_DOVE +	depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU  	help  	  If you say yes here you will get support for the in-chip RTC  	  that can be found in some of Marvell's SoC devices, such as @@ -1173,4 +1225,20 @@ config RTC_DRV_SNVS  	   This driver can also be built as a module, if so, the module  	   will be called "rtc-snvs". +comment "HID Sensor RTC drivers" + +config RTC_DRV_HID_SENSOR_TIME +	tristate "HID Sensor Time" +	depends on USB_HID +	select IIO +	select HID_SENSOR_HUB +	select HID_SENSOR_IIO_COMMON +	help +	  Say yes here to build support for the HID Sensors of type Time. +	  This drivers makes such sensors available as RTCs. + +	  If this driver is compiled as a module, it will be named +	  rtc-hid-sensor-time. + +  endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 4418ef3f9ecc..e8f2e2fee06f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG)	:= -DDEBUG  obj-$(CONFIG_RTC_LIB)		+= rtc-lib.o  obj-$(CONFIG_RTC_HCTOSYS)	+= hctosys.o +obj-$(CONFIG_RTC_SYSTOHC)	+= systohc.o  obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o  rtc-core-y			:= class.o interface.o @@ -52,10 +53,12 @@ obj-$(CONFIG_RTC_DRV_EM3027)	+= rtc-em3027.o  obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o  obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o  obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o +obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o  obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o  obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o  obj-$(CONFIG_RTC_DRV_ISL12022)	+= rtc-isl12022.o  obj-$(CONFIG_RTC_DRV_JZ4740)	+= rtc-jz4740.o +obj-$(CONFIG_RTC_DRV_LP8788)	+= rtc-lp8788.o  obj-$(CONFIG_RTC_DRV_LPC32XX)	+= rtc-lpc32xx.o  obj-$(CONFIG_RTC_DRV_LOONGSON1)	+= rtc-ls1x.o  obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o @@ -69,7 +72,9 @@ obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o  obj-$(CONFIG_RTC_DRV_MAX8907)	+= rtc-max8907.o  obj-$(CONFIG_RTC_DRV_MAX8925)	+= rtc-max8925.o  obj-$(CONFIG_RTC_DRV_MAX8998)	+= rtc-max8998.o +obj-$(CONFIG_RTC_DRV_MAX8997)	+= rtc-max8997.o  obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o +obj-$(CONFIG_RTC_DRV_MAX77686)	+= rtc-max77686.o  obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o  obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o  obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o @@ -95,6 +100,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o  obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o  obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o  obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o +obj-$(CONFIG_RTC_DRV_RX4581)	+= rtc-rx4581.o  obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o  obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o  obj-$(CONFIG_RTC_DRV_S35390A)	+= rtc-s35390a.o @@ -113,6 +119,7 @@ obj-$(CONFIG_RTC_DRV_TILE)	+= rtc-tile.o  obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o  obj-$(CONFIG_RTC_DRV_TPS6586X)	+= rtc-tps6586x.o  obj-$(CONFIG_RTC_DRV_TPS65910)	+= rtc-tps65910.o +obj-$(CONFIG_RTC_DRV_TPS80031)	+= rtc-tps80031.o  obj-$(CONFIG_RTC_DRV_TX4939)	+= rtc-tx4939.o  obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o  obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 5143629dedbd..9b742d3ffb94 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -11,6 +11,8 @@   * published by the Free Software Foundation.  */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/rtc.h>  #include <linux/kdev_t.h> @@ -50,6 +52,10 @@ 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 (has_persistent_clock()) +		return 0; +  	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)  		return 0; @@ -88,6 +94,9 @@ static int rtc_resume(struct device *dev)  	struct timespec		new_system, new_rtc;  	struct timespec		sleep_time; +	if (has_persistent_clock()) +		return 0; +  	rtc_hctosys_ret = -ENODEV;  	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)  		return 0; @@ -254,7 +263,7 @@ static int __init rtc_init(void)  {  	rtc_class = class_create(THIS_MODULE, "rtc");  	if (IS_ERR(rtc_class)) { -		printk(KERN_ERR "%s: couldn't create class\n", __FILE__); +		pr_err("couldn't create class\n");  		return PTR_ERR(rtc_class);  	}  	rtc_class->suspend = rtc_suspend; diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9592b936b71b..42bd57da239d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -587,16 +587,16 @@ void rtc_update_irq(struct rtc_device *rtc,  }  EXPORT_SYMBOL_GPL(rtc_update_irq); -static int __rtc_match(struct device *dev, void *data) +static int __rtc_match(struct device *dev, const void *data)  { -	char *name = (char *)data; +	const char *name = data;  	if (strcmp(dev_name(dev), name) == 0)  		return 1;  	return 0;  } -struct rtc_device *rtc_class_open(char *name) +struct rtc_device *rtc_class_open(const char *name)  {  	struct device *dev;  	struct rtc_device *rtc = NULL; diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index b6469e2cae89..434ebc3a99dc 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -86,7 +86,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)  	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);  	tm->tm_year = tm->tm_year - 1900; -	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, +	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,  		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,  		tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -100,7 +100,7 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)  {  	unsigned long cr; -	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, +	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,  		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,  		tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -145,7 +145,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)  	alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM)  			? 1 : 0; -	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, +	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,  		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,  		tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -183,7 +183,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  		at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM);  	} -	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, +	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,  		at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,  		tm.tm_min, tm.tm_sec); @@ -192,7 +192,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)  { -	pr_debug("%s(): cmd=%08x\n", __func__, enabled); +	dev_dbg(dev, "%s(): cmd=%08x\n", __func__, enabled);  	if (enabled) {  		at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); @@ -240,7 +240,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)  		rtc_update_irq(rtc, 1, events); -		pr_debug("%s(): num=%ld, events=0x%02lx\n", __func__, +		dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n", __func__,  			events >> 8, events & 0x000000FF);  		return IRQ_HANDLED; @@ -296,8 +296,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)  				IRQF_SHARED,  				"at91_rtc", pdev);  	if (ret) { -		printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", -				irq); +		dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);  		return ret;  	} @@ -315,7 +314,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)  	}  	platform_set_drvdata(pdev, rtc); -	printk(KERN_INFO "AT91 Real Time Clock driver.\n"); +	dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");  	return 0;  } diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 16630aa87f45..af97c94e8a3a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -706,7 +706,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)  			rtc_cmos_int_handler = hpet_rtc_interrupt;  			err = hpet_register_irq_handler(cmos_interrupt);  			if (err != 0) { -				printk(KERN_WARNING "hpet_register_irq_handler " +				dev_warn(dev, "hpet_register_irq_handler "  						" failed in rtc_init().");  				goto cleanup1;  			} @@ -731,8 +731,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)  		goto cleanup2;  	} -	pr_info("%s: %s%s, %zd bytes nvram%s\n", -		dev_name(&cmos_rtc.rtc->dev), +	dev_info(dev, "%s%s, %zd bytes nvram%s\n",  		!is_valid_irq(rtc_irq) ? "no alarms" :  			cmos_rtc.mon_alrm ? "alarms up to one year" :  			cmos_rtc.day_alrm ? "alarms up to one month" : @@ -820,8 +819,7 @@ static int cmos_suspend(struct device *dev)  			enable_irq_wake(cmos->irq);  	} -	pr_debug("%s: suspend%s, ctrl %02x\n", -			dev_name(&cmos_rtc.rtc->dev), +	dev_dbg(dev, "suspend%s, ctrl %02x\n",  			(tmp & RTC_AIE) ? ", alarm may wake" : "",  			tmp); @@ -876,9 +874,7 @@ static int cmos_resume(struct device *dev)  		spin_unlock_irq(&rtc_lock);  	} -	pr_debug("%s: resume, ctrl %02x\n", -			dev_name(&cmos_rtc.rtc->dev), -			tmp); +	dev_dbg(dev, "resume, ctrl %02x\n", tmp);  	return 0;  } @@ -1098,7 +1094,6 @@ static __init void cmos_of_init(struct platform_device *pdev)  }  #else  static inline void cmos_of_init(struct platform_device *pdev) {} -#define of_cmos_match NULL  #endif  /*----------------------------------------------------------------*/ @@ -1140,7 +1135,7 @@ static struct platform_driver cmos_platform_driver = {  #ifdef CONFIG_PM  		.pm		= &cmos_pm_ops,  #endif -		.of_match_table = of_cmos_match, +		.of_match_table = of_match_ptr(of_cmos_match),  	}  }; diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index c8115b83e5ab..2d28ec1aa1cd 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -157,7 +157,6 @@ static int __exit coh901331_remove(struct platform_device *pdev)  	if (rtap) {  		rtc_device_unregister(rtap->rtc);  		clk_unprepare(rtap->clk); -		clk_put(rtap->clk);  		platform_set_drvdata(pdev, NULL);  	} @@ -196,7 +195,7 @@ static int __init coh901331_probe(struct platform_device *pdev)  			     "RTC COH 901 331 Alarm", rtap))  		return -EIO; -	rtap->clk = clk_get(&pdev->dev, NULL); +	rtap->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(rtap->clk)) {  		ret = PTR_ERR(rtap->clk);  		dev_err(&pdev->dev, "could not get clock\n"); @@ -207,7 +206,7 @@ static int __init coh901331_probe(struct platform_device *pdev)  	ret = clk_prepare_enable(rtap->clk);  	if (ret) {  		dev_err(&pdev->dev, "could not enable clock\n"); -		goto out_no_clk_prepenable; +		return ret;  	}  	clk_disable(rtap->clk); @@ -224,8 +223,6 @@ static int __init coh901331_probe(struct platform_device *pdev)   out_no_rtc:  	platform_set_drvdata(pdev, NULL);  	clk_unprepare(rtap->clk); - out_no_clk_prepenable: -	clk_put(rtap->clk);  	return ret;  } diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 60b826e520e2..0dde688ca09b 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -240,9 +240,10 @@ static int da9052_rtc_probe(struct platform_device *pdev)  	rtc->da9052 = dev_get_drvdata(pdev->dev.parent);  	platform_set_drvdata(pdev, rtc);  	rtc->irq = platform_get_irq_byname(pdev, "ALM"); -	ret = request_threaded_irq(rtc->irq, NULL, da9052_rtc_irq, -				   IRQF_TRIGGER_LOW | IRQF_ONESHOT, -				   "ALM", rtc); +	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, +				da9052_rtc_irq, +				IRQF_TRIGGER_LOW | IRQF_ONESHOT, +				"ALM", rtc);  	if (ret != 0) {  		rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);  		return ret; @@ -250,16 +251,10 @@ static int da9052_rtc_probe(struct platform_device *pdev)  	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,  				       &da9052_rtc_ops, THIS_MODULE); -	if (IS_ERR(rtc->rtc)) { -		ret = PTR_ERR(rtc->rtc); -		goto err_free_irq; -	} +	if (IS_ERR(rtc->rtc)) +		return PTR_ERR(rtc->rtc);  	return 0; - -err_free_irq: -	free_irq(rtc->irq, rtc); -	return ret;  }  static int da9052_rtc_remove(struct platform_device *pdev) @@ -267,7 +262,6 @@ static int da9052_rtc_remove(struct platform_device *pdev)  	struct da9052_rtc *rtc = pdev->dev.platform_data;  	rtc_device_unregister(rtc->rtc); -	free_irq(rtc->irq, rtc);  	platform_set_drvdata(pdev, NULL);  	return 0; diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 5f7982f7c1b5..56b73089bb29 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -506,19 +506,19 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	davinci_rtc->pbase = res->start;  	davinci_rtc->base_size = resource_size(res); -	mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size, -				 pdev->name); +	mem = devm_request_mem_region(dev, davinci_rtc->pbase, +				davinci_rtc->base_size, pdev->name);  	if (!mem) {  		dev_err(dev, "RTC registers at %08x are not free\n",  			davinci_rtc->pbase);  		return -EBUSY;  	} -	davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); +	davinci_rtc->base = devm_ioremap(dev, davinci_rtc->pbase, +					davinci_rtc->base_size);  	if (!davinci_rtc->base) {  		dev_err(dev, "unable to ioremap MEM resource\n"); -		ret = -ENOMEM; -		goto fail2; +		return -ENOMEM;  	}  	platform_set_drvdata(pdev, davinci_rtc); @@ -529,7 +529,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  		ret = PTR_ERR(davinci_rtc->rtc);  		dev_err(dev, "unable to register RTC device, err %d\n",  				ret); -		goto fail3; +		goto fail1;  	}  	rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); @@ -539,11 +539,11 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL);  	rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); -	ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, +	ret = devm_request_irq(dev, davinci_rtc->irq, davinci_rtc_interrupt,  			  0, "davinci_rtc", davinci_rtc);  	if (ret < 0) {  		dev_err(dev, "unable to register davinci RTC interrupt\n"); -		goto fail4; +		goto fail2;  	}  	/* Enable interrupts */ @@ -557,13 +557,10 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	return 0; -fail4: +fail2:  	rtc_device_unregister(davinci_rtc->rtc); -fail3: +fail1:  	platform_set_drvdata(pdev, NULL); -	iounmap(davinci_rtc->base); -fail2: -	release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);  	return ret;  } @@ -575,13 +572,8 @@ static int davinci_rtc_remove(struct platform_device *pdev)  	rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); -	free_irq(davinci_rtc->irq, davinci_rtc); -  	rtc_device_unregister(davinci_rtc->rtc); -	iounmap(davinci_rtc->base); -	release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); -  	platform_set_drvdata(pdev, NULL);  	return 0; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 9a86b4bd8699..d04939369251 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -11,6 +11,8 @@   * published by the Free Software Foundation.  */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/rtc.h>  #include <linux/sched.h> @@ -462,7 +464,7 @@ void rtc_dev_prepare(struct rtc_device *rtc)  		return;  	if (rtc->id >= RTC_DEV_MAX) { -		pr_debug("%s: too many RTC devices\n", rtc->name); +		dev_dbg(&rtc->dev, "%s: too many RTC devices\n", rtc->name);  		return;  	} @@ -480,10 +482,10 @@ void rtc_dev_prepare(struct rtc_device *rtc)  void rtc_dev_add_device(struct rtc_device *rtc)  {  	if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1)) -		printk(KERN_WARNING "%s: failed to add char device %d:%d\n", +		dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",  			rtc->name, MAJOR(rtc_devt), rtc->id);  	else -		pr_debug("%s: dev (%d:%d)\n", rtc->name, +		dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,  			MAJOR(rtc_devt), rtc->id);  } @@ -499,8 +501,7 @@ void __init rtc_dev_init(void)  	err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");  	if (err < 0) -		printk(KERN_ERR "%s: failed to allocate char dev region\n", -			__FILE__); +		pr_err("failed to allocate char dev region\n");  }  void __exit rtc_dev_exit(void) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index d578773f5ce2..b05a6dc96405 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -635,9 +635,7 @@ static int ds1305_probe(struct spi_device *spi)  		goto fail0;  	} -	dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", -			"read", ds1305->ctrl[0], -			ds1305->ctrl[1], ds1305->ctrl[2]); +	dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "read", ds1305->ctrl);  	/* Sanity check register values ... partially compensating for the  	 * fact that SPI has no device handshake.  A pullup on MISO would @@ -723,9 +721,7 @@ static int ds1305_probe(struct spi_device *spi)  			goto fail0;  		} -		dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", -				"write", ds1305->ctrl[0], -				ds1305->ctrl[1], ds1305->ctrl[2]); +		dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "write", ds1305->ctrl);  	}  	/* see if non-Linux software set up AM/PM mode */ diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index e0d0ba4de03f..970a236b147a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -322,12 +322,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)  		return -EIO;  	} -	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", -			"read", -			ds1307->regs[0], ds1307->regs[1], -			ds1307->regs[2], ds1307->regs[3], -			ds1307->regs[4], ds1307->regs[5], -			ds1307->regs[6]); +	dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);  	t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);  	t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); @@ -398,9 +393,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)  		break;  	} -	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", -		"write", buf[0], buf[1], buf[2], buf[3], -		buf[4], buf[5], buf[6]); +	dev_dbg(dev, "%s: %7ph\n", "write", buf);  	result = ds1307->write_block_data(ds1307->client,  		ds1307->offset, 7, buf); diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 5ea9df7c8c31..b04fc4272fb3 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -70,7 +70,7 @@ static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev,  	for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) {  		err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name);  		if (err) { -			printk(KERN_ERR "error mapping gpio %s: %d\n", +			dev_err(&pdev->dev, "error mapping gpio %s: %d\n",  				ds2404_gpio[i].name, err);  			goto err_request;  		} @@ -177,7 +177,7 @@ static void ds2404_write_memory(struct device *dev, u16 offset,  	for (i = 0; i < length; i++) {  		if (out[i] != ds2404_read_byte(dev)) { -			printk(KERN_ERR "read invalid data\n"); +			dev_err(dev, "read invalid data\n");  			return;  		}  	} @@ -283,19 +283,7 @@ static struct platform_driver rtc_device_driver = {  		.owner	= THIS_MODULE,  	},  }; - -static __init int ds2404_init(void) -{ -	return platform_driver_register(&rtc_device_driver); -} - -static __exit void ds2404_exit(void) -{ -	platform_driver_unregister(&rtc_device_driver); -} - -module_init(ds2404_init); -module_exit(ds2404_exit); +module_platform_driver(rtc_device_driver);  MODULE_DESCRIPTION("DS2404 RTC");  MODULE_AUTHOR("Sven Schnelle"); diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index c9f890b088da..1a0c37c9152b 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -13,6 +13,8 @@   *   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/time.h> @@ -47,7 +49,7 @@ compute_wday(efi_time_t *eft)  	int ndays = 0;  	if (eft->year < 1998) { -		printk(KERN_ERR "efirtc: EFI year < 1998, invalid date\n"); +		pr_err("EFI year < 1998, invalid date\n");  		return -1;  	} @@ -70,7 +72,7 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft)  	eft->day	= wtime->tm_mday;  	eft->hour	= wtime->tm_hour;  	eft->minute	= wtime->tm_min; -	eft->second 	= wtime->tm_sec; +	eft->second	= wtime->tm_sec;  	eft->nanosecond = 0;  	eft->daylight	= wtime->tm_isdst ? EFI_ISDST : 0;  	eft->timezone	= EFI_UNSPECIFIED_TIMEZONE; @@ -142,7 +144,7 @@ static int efi_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)  	 */  	status = efi.set_wakeup_time((efi_bool_t)wkalrm->enabled, &eft); -	printk(KERN_WARNING "write status is %d\n", (int)status); +	dev_warn(dev, "write status is %d\n", (int)status);  	return status == EFI_SUCCESS ? 0 : -EINVAL;  } @@ -157,7 +159,7 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm)  	if (status != EFI_SUCCESS) {  		/* should never happen */ -		printk(KERN_ERR "efitime: can't read time\n"); +		dev_err(dev, "can't read time\n");  		return -EINVAL;  	} diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 04e93c6597f8..bff3cdc5140e 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -116,17 +116,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)  	fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); -	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x" -			"%02x %02x %02x %02x %02x %02x %02x\n", -			"read", -			fm3130->regs[0], fm3130->regs[1], -			fm3130->regs[2], fm3130->regs[3], -			fm3130->regs[4], fm3130->regs[5], -			fm3130->regs[6], fm3130->regs[7], -			fm3130->regs[8], fm3130->regs[9], -			fm3130->regs[0xa], fm3130->regs[0xb], -			fm3130->regs[0xc], fm3130->regs[0xd], -			fm3130->regs[0xe]); +	dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs);  	t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);  	t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); @@ -175,12 +165,7 @@ static int fm3130_set_time(struct device *dev, struct rtc_time *t)  	tmp = t->tm_year - 100;  	buf[FM3130_RTC_YEARS] = bin2bcd(tmp); -	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" -		"%02x %02x %02x %02x %02x %02x %02x %02x\n", -		"write", buf[0], buf[1], buf[2], buf[3], -		buf[4], buf[5], buf[6], buf[7], -		buf[8], buf[9], buf[0xa], buf[0xb], -		buf[0xc], buf[0xd], buf[0xe]); +	dev_dbg(dev, "%s: %15ph\n", "write", buf);  	fm3130_rtc_mode(dev, FM3130_MODE_WRITE); @@ -517,18 +502,8 @@ bad_alarm:  bad_clock:  	if (!fm3130->data_valid || !fm3130->alarm_valid) -		dev_dbg(&client->dev, -				"%s: %02x %02x %02x %02x %02x %02x %02x %02x" -				"%02x %02x %02x %02x %02x %02x %02x\n", -			"bogus registers", -			fm3130->regs[0], fm3130->regs[1], -			fm3130->regs[2], fm3130->regs[3], -			fm3130->regs[4], fm3130->regs[5], -			fm3130->regs[6], fm3130->regs[7], -			fm3130->regs[8], fm3130->regs[9], -			fm3130->regs[0xa], fm3130->regs[0xb], -			fm3130->regs[0xc], fm3130->regs[0xd], -			fm3130->regs[0xe]); +		dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers", +			fm3130->regs);  	/* We won't bail out here because we just got invalid data.  	   Time setting from u-boot doesn't work anyway */ diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c new file mode 100644 index 000000000000..31c5728ef629 --- /dev/null +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -0,0 +1,292 @@ +/* + * HID Sensor Time Driver + * Copyright (c) 2012, Alexander Holler. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/hid-sensor-hub.h> +#include <linux/iio/iio.h> +#include <linux/rtc.h> + +/* Format: HID-SENSOR-usage_id_in_hex */ +/* Usage ID from spec for Time: 0x2000A0 */ +#define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */ + +enum hid_time_channel { +	CHANNEL_SCAN_INDEX_YEAR, +	CHANNEL_SCAN_INDEX_MONTH, +	CHANNEL_SCAN_INDEX_DAY, +	CHANNEL_SCAN_INDEX_HOUR, +	CHANNEL_SCAN_INDEX_MINUTE, +	CHANNEL_SCAN_INDEX_SECOND, +	TIME_RTC_CHANNEL_MAX, +}; + +struct hid_time_state { +	struct hid_sensor_hub_callbacks callbacks; +	struct hid_sensor_common common_attributes; +	struct hid_sensor_hub_attribute_info info[TIME_RTC_CHANNEL_MAX]; +	struct rtc_time last_time; +	spinlock_t lock_last_time; +	struct completion comp_last_time; +	struct rtc_time time_buf; +	struct rtc_device *rtc; +}; + +static const u32 hid_time_addresses[TIME_RTC_CHANNEL_MAX] = { +	HID_USAGE_SENSOR_TIME_YEAR, +	HID_USAGE_SENSOR_TIME_MONTH, +	HID_USAGE_SENSOR_TIME_DAY, +	HID_USAGE_SENSOR_TIME_HOUR, +	HID_USAGE_SENSOR_TIME_MINUTE, +	HID_USAGE_SENSOR_TIME_SECOND, +}; + +/* Channel names for verbose error messages */ +static const char * const hid_time_channel_names[TIME_RTC_CHANNEL_MAX] = { +	"year", "month", "day", "hour", "minute", "second", +}; + +/* Callback handler to send event after all samples are received and captured */ +static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev, +				unsigned usage_id, void *priv) +{ +	unsigned long flags; +	struct hid_time_state *time_state = platform_get_drvdata(priv); + +	spin_lock_irqsave(&time_state->lock_last_time, flags); +	time_state->last_time = time_state->time_buf; +	spin_unlock_irqrestore(&time_state->lock_last_time, flags); +	complete(&time_state->comp_last_time); +	return 0; +} + +static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev, +				unsigned usage_id, size_t raw_len, +				char *raw_data, void *priv) +{ +	struct hid_time_state *time_state = platform_get_drvdata(priv); +	struct rtc_time *time_buf = &time_state->time_buf; + +	switch (usage_id) { +	case HID_USAGE_SENSOR_TIME_YEAR: +		time_buf->tm_year = *(u8 *)raw_data; +		if (time_buf->tm_year < 70) +			/* assume we are in 1970...2069 */ +			time_buf->tm_year += 100; +		break; +	case HID_USAGE_SENSOR_TIME_MONTH: +		/* sensor sending the month as 1-12, we need 0-11 */ +		time_buf->tm_mon = *(u8 *)raw_data-1; +		break; +	case HID_USAGE_SENSOR_TIME_DAY: +		time_buf->tm_mday = *(u8 *)raw_data; +		break; +	case HID_USAGE_SENSOR_TIME_HOUR: +		time_buf->tm_hour = *(u8 *)raw_data; +		break; +	case HID_USAGE_SENSOR_TIME_MINUTE: +		time_buf->tm_min = *(u8 *)raw_data; +		break; +	case HID_USAGE_SENSOR_TIME_SECOND: +		time_buf->tm_sec = *(u8 *)raw_data; +		break; +	default: +		return -EINVAL; +	} +	return 0; +} + +/* small helper, haven't found any other way */ +static const char *hid_time_attrib_name(u32 attrib_id) +{ +	static const char unknown[] = "unknown"; +	unsigned i; + +	for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) { +		if (hid_time_addresses[i] == attrib_id) +			return hid_time_channel_names[i]; +	} +	return unknown; /* should never happen */ +} + +static int hid_time_parse_report(struct platform_device *pdev, +				struct hid_sensor_hub_device *hsdev, +				unsigned usage_id, +				struct hid_time_state *time_state) +{ +	int report_id, i; + +	for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) +		if (sensor_hub_input_get_attribute_info(hsdev, +				HID_INPUT_REPORT, usage_id, +				hid_time_addresses[i], +				&time_state->info[i]) < 0) +			return -EINVAL; +	/* Check the (needed) attributes for sanity */ +	report_id = time_state->info[0].report_id; +	if (report_id < 0) { +		dev_err(&pdev->dev, "bad report ID!\n"); +		return -EINVAL; +	} +	for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) { +		if (time_state->info[i].report_id != report_id) { +			dev_err(&pdev->dev, +				"not all needed attributes inside the same report!\n"); +			return -EINVAL; +		} +		if (time_state->info[i].size != 1) { +			dev_err(&pdev->dev, +				"attribute '%s' not 8 bits wide!\n", +				hid_time_attrib_name( +					time_state->info[i].attrib_id)); +			return -EINVAL; +		} +		if (time_state->info[i].units != +				HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED && +				/* allow attribute seconds with unit seconds */ +				!(time_state->info[i].attrib_id == +				HID_USAGE_SENSOR_TIME_SECOND && +				time_state->info[i].units == +				HID_USAGE_SENSOR_UNITS_SECOND)) { +			dev_err(&pdev->dev, +				"attribute '%s' hasn't a unit of type 'none'!\n", +				hid_time_attrib_name( +					time_state->info[i].attrib_id)); +			return -EINVAL; +		} +		if (time_state->info[i].unit_expo) { +			dev_err(&pdev->dev, +				"attribute '%s' hasn't a unit exponent of 1!\n", +				hid_time_attrib_name( +					time_state->info[i].attrib_id)); +			return -EINVAL; +		} +	} + +	return 0; +} + +static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	unsigned long flags; +	struct hid_time_state *time_state = +		platform_get_drvdata(to_platform_device(dev)); +	int ret; + +	INIT_COMPLETION(time_state->comp_last_time); +	/* get a report with all values through requesting one value */ +	sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev, +			HID_USAGE_SENSOR_TIME, hid_time_addresses[0], +			time_state->info[0].report_id); +	/* wait for all values (event) */ +	ret = wait_for_completion_killable_timeout( +			&time_state->comp_last_time, HZ*6); +	if (ret > 0) { +		/* no error */ +		spin_lock_irqsave(&time_state->lock_last_time, flags); +		*tm = time_state->last_time; +		spin_unlock_irqrestore(&time_state->lock_last_time, flags); +		return 0; +	} +	if (!ret) +		return -EIO; /* timeouted */ +	return ret; /* killed (-ERESTARTSYS) */ +} + +static const struct rtc_class_ops hid_time_rtc_ops = { +	.read_time = hid_rtc_read_time, +}; + +static int hid_time_probe(struct platform_device *pdev) +{ +	int ret = 0; +	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; +	struct hid_time_state *time_state = devm_kzalloc(&pdev->dev, +		sizeof(struct hid_time_state), GFP_KERNEL); + +	if (time_state == NULL) +		return -ENOMEM; + +	platform_set_drvdata(pdev, time_state); + +	spin_lock_init(&time_state->lock_last_time); +	init_completion(&time_state->comp_last_time); +	time_state->common_attributes.hsdev = hsdev; +	time_state->common_attributes.pdev = pdev; + +	ret = hid_sensor_parse_common_attributes(hsdev, +				HID_USAGE_SENSOR_TIME, +				&time_state->common_attributes); +	if (ret) { +		dev_err(&pdev->dev, "failed to setup common attributes!\n"); +		return ret; +	} + +	ret = hid_time_parse_report(pdev, hsdev, HID_USAGE_SENSOR_TIME, +					time_state); +	if (ret) { +		dev_err(&pdev->dev, "failed to setup attributes!\n"); +		return ret; +	} + +	time_state->callbacks.send_event = hid_time_proc_event; +	time_state->callbacks.capture_sample = hid_time_capture_sample; +	time_state->callbacks.pdev = pdev; +	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TIME, +					&time_state->callbacks); +	if (ret < 0) { +		dev_err(&pdev->dev, "register callback failed!\n"); +		return ret; +	} + +	time_state->rtc = rtc_device_register("hid-sensor-time", +				&pdev->dev, &hid_time_rtc_ops, THIS_MODULE); + +	if (IS_ERR(time_state->rtc)) { +		dev_err(&pdev->dev, "rtc device register failed!\n"); +		return PTR_ERR(time_state->rtc); +	} + +	return ret; +} + +static int hid_time_remove(struct platform_device *pdev) +{ +	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; +	struct hid_time_state *time_state = platform_get_drvdata(pdev); + +	rtc_device_unregister(time_state->rtc); +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); + +	return 0; +} + +static struct platform_driver hid_time_platform_driver = { +	.driver = { +		.name	= DRIVER_NAME, +		.owner	= THIS_MODULE, +	}, +	.probe		= hid_time_probe, +	.remove		= hid_time_remove, +}; +module_platform_driver(hid_time_platform_driver); + +MODULE_DESCRIPTION("HID Sensor Time"); +MODULE_AUTHOR("Alexander Holler <[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 75d307ab37f4..82aad695979e 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -406,7 +406,7 @@ static int dryice_rtc_probe(struct platform_device *pdev)  	mutex_init(&imxdi->write_mutex); -	imxdi->clk = clk_get(&pdev->dev, NULL); +	imxdi->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(imxdi->clk))  		return PTR_ERR(imxdi->clk);  	clk_prepare_enable(imxdi->clk); @@ -475,7 +475,6 @@ static int dryice_rtc_probe(struct platform_device *pdev)  err:  	clk_disable_unprepare(imxdi->clk); -	clk_put(imxdi->clk);  	return rc;  } @@ -492,7 +491,6 @@ static int dryice_rtc_remove(struct platform_device *pdev)  	rtc_device_unregister(imxdi->rtc);  	clk_disable_unprepare(imxdi->clk); -	clk_put(imxdi->clk);  	return 0;  } diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 1850104705c0..6b4298ea683d 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -227,7 +227,7 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)  					 buf[ISL12022_REG_SC + i]);  		if (ret)  			return -EIO; -	}; +	}  	return 0;  } diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index afb7cfa85ccc..c016ad81767a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -506,6 +506,7 @@ isl1208_rtc_interrupt(int irq, void *data)  {  	unsigned long timeout = jiffies + msecs_to_jiffies(1000);  	struct i2c_client *client = data; +	struct rtc_device *rtc = i2c_get_clientdata(client);  	int handled = 0, sr, err;  	/* @@ -528,6 +529,8 @@ isl1208_rtc_interrupt(int irq, void *data)  	if (sr & ISL1208_REG_SR_ALM) {  		dev_dbg(&client->dev, "alarm!\n"); +		rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); +  		/* Clear the alarm */  		sr &= ~ISL1208_REG_SR_ALM;  		sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c new file mode 100644 index 000000000000..9a4631218f41 --- /dev/null +++ b/drivers/rtc/rtc-lp8788.c @@ -0,0 +1,338 @@ +/* + * TI LP8788 MFD - rtc driver + * + * Copyright 2012 Texas Instruments + * + * Author: Milo(Woogyom) Kim <[email protected]> + * + * 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 + * published by the Free Software Foundation. + * + */ + +#include <linux/err.h> +#include <linux/irqdomain.h> +#include <linux/mfd/lp8788.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/slab.h> + +/* register address */ +#define LP8788_INTEN_3			0x05 +#define LP8788_RTC_UNLOCK		0x64 +#define LP8788_RTC_SEC			0x70 +#define LP8788_ALM1_SEC			0x77 +#define LP8788_ALM1_EN			0x7D +#define LP8788_ALM2_SEC			0x7E +#define LP8788_ALM2_EN			0x84 + +/* mask/shift bits */ +#define LP8788_INT_RTC_ALM1_M		BIT(1)	/* Addr 05h */ +#define LP8788_INT_RTC_ALM1_S		1 +#define LP8788_INT_RTC_ALM2_M		BIT(2)	/* Addr 05h */ +#define LP8788_INT_RTC_ALM2_S		2 +#define LP8788_ALM_EN_M			BIT(7)	/* Addr 7Dh or 84h */ +#define LP8788_ALM_EN_S			7 + +#define DEFAULT_ALARM_SEL		LP8788_ALARM_1 +#define LP8788_MONTH_OFFSET		1 +#define LP8788_BASE_YEAR		2000 +#define MAX_WDAY_BITS			7 +#define LP8788_WDAY_SET			1 +#define RTC_UNLOCK			0x1 +#define RTC_LATCH			0x2 +#define ALARM_IRQ_FLAG			(RTC_IRQF | RTC_AF) + +enum lp8788_time { +	LPTIME_SEC, +	LPTIME_MIN, +	LPTIME_HOUR, +	LPTIME_MDAY, +	LPTIME_MON, +	LPTIME_YEAR, +	LPTIME_WDAY, +	LPTIME_MAX, +}; + +struct lp8788_rtc { +	struct lp8788 *lp; +	struct rtc_device *rdev; +	enum lp8788_alarm_sel alarm; +	int irq; +}; + +static const u8 addr_alarm_sec[LP8788_ALARM_MAX] = { +	LP8788_ALM1_SEC, +	LP8788_ALM2_SEC, +}; + +static const u8 addr_alarm_en[LP8788_ALARM_MAX] = { +	LP8788_ALM1_EN, +	LP8788_ALM2_EN, +}; + +static const u8 mask_alarm_en[LP8788_ALARM_MAX] = { +	LP8788_INT_RTC_ALM1_M, +	LP8788_INT_RTC_ALM2_M, +}; + +static const u8 shift_alarm_en[LP8788_ALARM_MAX] = { +	LP8788_INT_RTC_ALM1_S, +	LP8788_INT_RTC_ALM2_S, +}; + +static int _to_tm_wday(u8 lp8788_wday) +{ +	int i; + +	if (lp8788_wday == 0) +		return 0; + +	/* lookup defined weekday from read register value */ +	for (i = 0; i < MAX_WDAY_BITS; i++) { +		if ((lp8788_wday >> i) == LP8788_WDAY_SET) +			break; +	} + +	return i + 1; +} + +static inline int _to_lp8788_wday(int tm_wday) +{ +	return LP8788_WDAY_SET << (tm_wday - 1); +} + +static void lp8788_rtc_unlock(struct lp8788 *lp) +{ +	lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_UNLOCK); +	lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_LATCH); +} + +static int lp8788_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct lp8788_rtc *rtc = dev_get_drvdata(dev); +	struct lp8788 *lp = rtc->lp; +	u8 data[LPTIME_MAX]; +	int ret; + +	lp8788_rtc_unlock(lp); + +	ret = lp8788_read_multi_bytes(lp, LP8788_RTC_SEC, data,	LPTIME_MAX); +	if (ret) +		return ret; + +	tm->tm_sec  = data[LPTIME_SEC]; +	tm->tm_min  = data[LPTIME_MIN]; +	tm->tm_hour = data[LPTIME_HOUR]; +	tm->tm_mday = data[LPTIME_MDAY]; +	tm->tm_mon  = data[LPTIME_MON] - LP8788_MONTH_OFFSET; +	tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900; +	tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]); + +	return 0; +} + +static int lp8788_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct lp8788_rtc *rtc = dev_get_drvdata(dev); +	struct lp8788 *lp = rtc->lp; +	u8 data[LPTIME_MAX - 1]; +	int ret, i, year; + +	year = tm->tm_year + 1900 - LP8788_BASE_YEAR; +	if (year < 0) { +		dev_err(lp->dev, "invalid year: %d\n", year); +		return -EINVAL; +	} + +	/* because rtc weekday is a readonly register, do not update */ +	data[LPTIME_SEC]  = tm->tm_sec; +	data[LPTIME_MIN]  = tm->tm_min; +	data[LPTIME_HOUR] = tm->tm_hour; +	data[LPTIME_MDAY] = tm->tm_mday; +	data[LPTIME_MON]  = tm->tm_mon + LP8788_MONTH_OFFSET; +	data[LPTIME_YEAR] = year; + +	for (i = 0; i < ARRAY_SIZE(data); i++) { +		ret = lp8788_write_byte(lp, LP8788_RTC_SEC + i, data[i]); +		if (ret) +			return ret; +	} + +	return 0; +} + +static int lp8788_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	struct lp8788_rtc *rtc = dev_get_drvdata(dev); +	struct lp8788 *lp = rtc->lp; +	struct rtc_time *tm = &alarm->time; +	u8 addr, data[LPTIME_MAX]; +	int ret; + +	addr = addr_alarm_sec[rtc->alarm]; +	ret = lp8788_read_multi_bytes(lp, addr, data, LPTIME_MAX); +	if (ret) +		return ret; + +	tm->tm_sec  = data[LPTIME_SEC]; +	tm->tm_min  = data[LPTIME_MIN]; +	tm->tm_hour = data[LPTIME_HOUR]; +	tm->tm_mday = data[LPTIME_MDAY]; +	tm->tm_mon  = data[LPTIME_MON] - LP8788_MONTH_OFFSET; +	tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900; +	tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]); +	alarm->enabled = data[LPTIME_WDAY] & LP8788_ALM_EN_M; + +	return 0; +} + +static int lp8788_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	struct lp8788_rtc *rtc = dev_get_drvdata(dev); +	struct lp8788 *lp = rtc->lp; +	struct rtc_time *tm = &alarm->time; +	u8 addr, data[LPTIME_MAX]; +	int ret, i, year; + +	year = tm->tm_year + 1900 - LP8788_BASE_YEAR; +	if (year < 0) { +		dev_err(lp->dev, "invalid year: %d\n", year); +		return -EINVAL; +	} + +	data[LPTIME_SEC]  = tm->tm_sec; +	data[LPTIME_MIN]  = tm->tm_min; +	data[LPTIME_HOUR] = tm->tm_hour; +	data[LPTIME_MDAY] = tm->tm_mday; +	data[LPTIME_MON]  = tm->tm_mon + LP8788_MONTH_OFFSET; +	data[LPTIME_YEAR] = year; +	data[LPTIME_WDAY] = _to_lp8788_wday(tm->tm_wday); + +	for (i = 0; i < ARRAY_SIZE(data); i++) { +		addr = addr_alarm_sec[rtc->alarm] + i; +		ret = lp8788_write_byte(lp, addr, data[i]); +		if (ret) +			return ret; +	} + +	alarm->enabled = 1; +	addr = addr_alarm_en[rtc->alarm]; + +	return lp8788_update_bits(lp, addr, LP8788_ALM_EN_M, +				alarm->enabled << LP8788_ALM_EN_S); +} + +static int lp8788_alarm_irq_enable(struct device *dev, unsigned int enable) +{ +	struct lp8788_rtc *rtc = dev_get_drvdata(dev); +	struct lp8788 *lp = rtc->lp; +	u8 mask, shift; + +	if (!rtc->irq) +		return -EIO; + +	mask = mask_alarm_en[rtc->alarm]; +	shift = shift_alarm_en[rtc->alarm]; + +	return lp8788_update_bits(lp, LP8788_INTEN_3, mask, enable << shift); +} + +static const struct rtc_class_ops lp8788_rtc_ops = { +	.read_time = lp8788_rtc_read_time, +	.set_time = lp8788_rtc_set_time, +	.read_alarm = lp8788_read_alarm, +	.set_alarm = lp8788_set_alarm, +	.alarm_irq_enable = lp8788_alarm_irq_enable, +}; + +static irqreturn_t lp8788_alarm_irq_handler(int irq, void *ptr) +{ +	struct lp8788_rtc *rtc = ptr; + +	rtc_update_irq(rtc->rdev, 1, ALARM_IRQ_FLAG); +	return IRQ_HANDLED; +} + +static int lp8788_alarm_irq_register(struct platform_device *pdev, +				struct lp8788_rtc *rtc) +{ +	struct resource *r; +	struct lp8788 *lp = rtc->lp; +	struct irq_domain *irqdm = lp->irqdm; +	int irq; + +	rtc->irq = 0; + +	/* even the alarm IRQ number is not specified, rtc time should work */ +	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, LP8788_ALM_IRQ); +	if (!r) +		return 0; + +	if (rtc->alarm == LP8788_ALARM_1) +		irq = r->start; +	else +		irq = r->end; + +	rtc->irq = irq_create_mapping(irqdm, irq); + +	return devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, +				lp8788_alarm_irq_handler, +				0, LP8788_ALM_IRQ, rtc); +} + +static int lp8788_rtc_probe(struct platform_device *pdev) +{ +	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); +	struct lp8788_rtc *rtc; +	struct device *dev = &pdev->dev; + +	rtc = devm_kzalloc(dev, sizeof(struct lp8788_rtc), GFP_KERNEL); +	if (!rtc) +		return -ENOMEM; + +	rtc->lp = lp; +	rtc->alarm = lp->pdata ? lp->pdata->alarm_sel : DEFAULT_ALARM_SEL; +	platform_set_drvdata(pdev, rtc); + +	device_init_wakeup(dev, 1); + +	rtc->rdev = rtc_device_register("lp8788_rtc", dev, +					&lp8788_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc->rdev)) { +		dev_err(dev, "can not register rtc device\n"); +		return PTR_ERR(rtc->rdev); +	} + +	if (lp8788_alarm_irq_register(pdev, rtc)) +		dev_warn(lp->dev, "no rtc irq handler\n"); + +	return 0; +} + +static int lp8788_rtc_remove(struct platform_device *pdev) +{ +	struct lp8788_rtc *rtc = platform_get_drvdata(pdev); + +	rtc_device_unregister(rtc->rdev); +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +static struct platform_driver lp8788_rtc_driver = { +	.probe = lp8788_rtc_probe, +	.remove = lp8788_rtc_remove, +	.driver = { +		.name = LP8788_DEV_RTC, +		.owner = THIS_MODULE, +	}, +}; +module_platform_driver(lp8788_rtc_driver); + +MODULE_DESCRIPTION("Texas Instruments LP8788 RTC Driver"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp8788-rtc"); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c new file mode 100644 index 000000000000..6b1337f9baf4 --- /dev/null +++ b/drivers/rtc/rtc-max77686.c @@ -0,0 +1,641 @@ +/* + * RTC driver for Maxim MAX77686 + * + * Copyright (C) 2012 Samsung Electronics Co.Ltd + * + *  based on rtc-max8997.c + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + */ + +#include <linux/slab.h> +#include <linux/rtc.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/mfd/max77686-private.h> +#include <linux/irqdomain.h> +#include <linux/regmap.h> + +/* RTC Control Register */ +#define BCD_EN_SHIFT			0 +#define BCD_EN_MASK				(1 << BCD_EN_SHIFT) +#define MODEL24_SHIFT			1 +#define MODEL24_MASK			(1 << MODEL24_SHIFT) +/* RTC Update Register1 */ +#define RTC_UDR_SHIFT			0 +#define RTC_UDR_MASK			(1 << RTC_UDR_SHIFT) +#define RTC_RBUDR_SHIFT			4 +#define RTC_RBUDR_MASK			(1 << RTC_RBUDR_SHIFT) +/* WTSR and SMPL Register */ +#define WTSRT_SHIFT				0 +#define SMPLT_SHIFT				2 +#define WTSR_EN_SHIFT			6 +#define SMPL_EN_SHIFT			7 +#define WTSRT_MASK				(3 << WTSRT_SHIFT) +#define SMPLT_MASK				(3 << SMPLT_SHIFT) +#define WTSR_EN_MASK			(1 << WTSR_EN_SHIFT) +#define SMPL_EN_MASK			(1 << SMPL_EN_SHIFT) +/* RTC Hour register */ +#define HOUR_PM_SHIFT			6 +#define HOUR_PM_MASK			(1 << HOUR_PM_SHIFT) +/* RTC Alarm Enable */ +#define ALARM_ENABLE_SHIFT		7 +#define ALARM_ENABLE_MASK		(1 << ALARM_ENABLE_SHIFT) + +#define MAX77686_RTC_UPDATE_DELAY	16 +#undef MAX77686_RTC_WTSR_SMPL + +enum { +	RTC_SEC = 0, +	RTC_MIN, +	RTC_HOUR, +	RTC_WEEKDAY, +	RTC_MONTH, +	RTC_YEAR, +	RTC_DATE, +	RTC_NR_TIME +}; + +struct max77686_rtc_info { +	struct device		*dev; +	struct max77686_dev	*max77686; +	struct i2c_client	*rtc; +	struct rtc_device	*rtc_dev; +	struct mutex		lock; + +	struct regmap		*regmap; + +	int virq; +	int rtc_24hr_mode; +}; + +enum MAX77686_RTC_OP { +	MAX77686_RTC_WRITE, +	MAX77686_RTC_READ, +}; + +static inline int max77686_rtc_calculate_wday(u8 shifted) +{ +	int counter = -1; +	while (shifted) { +		shifted >>= 1; +		counter++; +	} +	return counter; +} + +static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, +				   int rtc_24hr_mode) +{ +	tm->tm_sec = data[RTC_SEC] & 0x7f; +	tm->tm_min = data[RTC_MIN] & 0x7f; +	if (rtc_24hr_mode) +		tm->tm_hour = data[RTC_HOUR] & 0x1f; +	else { +		tm->tm_hour = data[RTC_HOUR] & 0x0f; +		if (data[RTC_HOUR] & HOUR_PM_MASK) +			tm->tm_hour += 12; +	} + +	tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f); +	tm->tm_mday = data[RTC_DATE] & 0x1f; +	tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; +	tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; +	tm->tm_yday = 0; +	tm->tm_isdst = 0; +} + +static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) +{ +	data[RTC_SEC] = tm->tm_sec; +	data[RTC_MIN] = tm->tm_min; +	data[RTC_HOUR] = tm->tm_hour; +	data[RTC_WEEKDAY] = 1 << tm->tm_wday; +	data[RTC_DATE] = tm->tm_mday; +	data[RTC_MONTH] = tm->tm_mon + 1; +	data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0 ; + +	if (tm->tm_year < 100) { +		pr_warn("%s: MAX77686 RTC cannot handle the year %d." +			"Assume it's 2000.\n", __func__, 1900 + tm->tm_year); +		return -EINVAL; +	} +	return 0; +} + +static int max77686_rtc_update(struct max77686_rtc_info *info, +	enum MAX77686_RTC_OP op) +{ +	int ret; +	unsigned int data; + +	if (op == MAX77686_RTC_WRITE) +		data = 1 << RTC_UDR_SHIFT; +	else +		data = 1 << RTC_RBUDR_SHIFT; + +	ret = regmap_update_bits(info->max77686->rtc_regmap, +				 MAX77686_RTC_UPDATE0, data, data); +	if (ret < 0) +		dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", +				__func__, ret, data); +	else { +		/* Minimum 16ms delay required before RTC update. */ +		msleep(MAX77686_RTC_UPDATE_DELAY); +	} + +	return ret; +} + +static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct max77686_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	mutex_lock(&info->lock); + +	ret = max77686_rtc_update(info, MAX77686_RTC_READ); +	if (ret < 0) +		goto out; + +	ret = regmap_bulk_read(info->max77686->rtc_regmap, +				MAX77686_RTC_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,	ret); +		goto out; +	} + +	max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); + +	ret = rtc_valid_tm(tm); + +out: +	mutex_unlock(&info->lock); +	return ret; +} + +static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct max77686_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	ret = max77686_rtc_tm_to_data(tm, data); +	if (ret < 0) +		return ret; + +	mutex_lock(&info->lock); + +	ret = regmap_bulk_write(info->max77686->rtc_regmap, +				 MAX77686_RTC_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, +				ret); +		goto out; +	} + +	ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); + +out: +	mutex_unlock(&info->lock); +	return ret; +} + +static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct max77686_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	unsigned int val; +	int i, ret; + +	mutex_lock(&info->lock); + +	ret = max77686_rtc_update(info, MAX77686_RTC_READ); +	if (ret < 0) +		goto out; + +	ret = regmap_bulk_read(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", +				__func__, __LINE__, ret); +		goto out; +	} + +	max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); + +	alrm->enabled = 0; +	for (i = 0; i < RTC_NR_TIME; i++) { +		if (data[i] & ALARM_ENABLE_MASK) { +			alrm->enabled = 1; +			break; +		} +	} + +	alrm->pending = 0; +	ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS1, &val); +	if (ret < 0) { +		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", +				__func__, __LINE__, ret); +		goto out; +	} + +	if (val & (1 << 4)) /* RTCA1 */ +		alrm->pending = 1; + +out: +	mutex_unlock(&info->lock); +	return 0; +} + +static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) +{ +	u8 data[RTC_NR_TIME]; +	int ret, i; +	struct rtc_time tm; + +	if (!mutex_is_locked(&info->lock)) +		dev_warn(info->dev, "%s: should have mutex locked\n", __func__); + +	ret = max77686_rtc_update(info, MAX77686_RTC_READ); +	if (ret < 0) +		goto out; + +	ret = regmap_bulk_read(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + +	for (i = 0; i < RTC_NR_TIME; i++) +		data[i] &= ~ALARM_ENABLE_MASK; + +	ret = regmap_bulk_write(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); +out: +	return ret; +} + +static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) +{ +	u8 data[RTC_NR_TIME]; +	int ret; +	struct rtc_time tm; + +	if (!mutex_is_locked(&info->lock)) +		dev_warn(info->dev, "%s: should have mutex locked\n", __func__); + +	ret = max77686_rtc_update(info, MAX77686_RTC_READ); +	if (ret < 0) +		goto out; + +	ret = regmap_bulk_read(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + +	data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; +	if (data[RTC_MONTH] & 0xf) +		data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); +	if (data[RTC_YEAR] & 0x7f) +		data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); +	if (data[RTC_DATE] & 0x1f) +		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + +	ret = regmap_bulk_write(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); +out: +	return ret; +} + +static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct max77686_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	ret = max77686_rtc_tm_to_data(&alrm->time, data); +	if (ret < 0) +		return ret; + +	mutex_lock(&info->lock); + +	ret = max77686_rtc_stop_alarm(info); +	if (ret < 0) +		goto out; + +	ret = regmap_bulk_write(info->max77686->rtc_regmap, +				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); +	if (ret < 0) +		goto out; + +	if (alrm->enabled) +		ret = max77686_rtc_start_alarm(info); +out: +	mutex_unlock(&info->lock); +	return ret; +} + +static int max77686_rtc_alarm_irq_enable(struct device *dev, +					unsigned int enabled) +{ +	struct max77686_rtc_info *info = dev_get_drvdata(dev); +	int ret; + +	mutex_lock(&info->lock); +	if (enabled) +		ret = max77686_rtc_start_alarm(info); +	else +		ret = max77686_rtc_stop_alarm(info); +	mutex_unlock(&info->lock); + +	return ret; +} + +static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data) +{ +	struct max77686_rtc_info *info = data; + +	dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); + +	rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); + +	return IRQ_HANDLED; +} + +static const struct rtc_class_ops max77686_rtc_ops = { +	.read_time = max77686_rtc_read_time, +	.set_time = max77686_rtc_set_time, +	.read_alarm = max77686_rtc_read_alarm, +	.set_alarm = max77686_rtc_set_alarm, +	.alarm_irq_enable = max77686_rtc_alarm_irq_enable, +}; + +#ifdef MAX77686_RTC_WTSR_SMPL +static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable) +{ +	int ret; +	unsigned int val, mask; + +	if (enable) +		val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); +	else +		val = 0; + +	mask = WTSR_EN_MASK | WTSRT_MASK; + +	dev_info(info->dev, "%s: %s WTSR\n", __func__, +			enable ? "enable" : "disable"); + +	ret = regmap_update_bits(info->max77686->rtc_regmap, +				 MAX77686_WTSR_SMPL_CNTL, mask, val); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", +				__func__, ret); +		return; +	} + +	max77686_rtc_update(info, MAX77686_RTC_WRITE); +} + +static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable) +{ +	int ret; +	unsigned int val, mask; + +	if (enable) +		val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); +	else +		val = 0; + +	mask = SMPL_EN_MASK | SMPLT_MASK; + +	dev_info(info->dev, "%s: %s SMPL\n", __func__, +			enable ? "enable" : "disable"); + +	ret = regmap_update_bits(info->max77686->rtc_regmap, +				 MAX77686_WTSR_SMPL_CNTL, mask, val); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", +				__func__, ret); +		return; +	} + +	max77686_rtc_update(info, MAX77686_RTC_WRITE); + +	val = 0; +	regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); +	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); +} +#endif /* MAX77686_RTC_WTSR_SMPL */ + +static int max77686_rtc_init_reg(struct max77686_rtc_info *info) +{ +	u8 data[2]; +	int ret; + +	/* Set RTC control register : Binary mode, 24hour mdoe */ +	data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); +	data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); + +	info->rtc_24hr_mode = 1; + +	ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", +				__func__, ret); +		return ret; +	} + +	ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); +	return ret; +} + +static struct regmap_config max77686_rtc_regmap_config = { +	.reg_bits = 8, +	.val_bits = 8, +}; + +static int max77686_rtc_probe(struct platform_device *pdev) +{ +	struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); +	struct max77686_rtc_info *info; +	int ret, virq; + +	dev_info(&pdev->dev, "%s\n", __func__); + +	info = kzalloc(sizeof(struct max77686_rtc_info), GFP_KERNEL); +	if (!info) +		return -ENOMEM; + +	mutex_init(&info->lock); +	info->dev = &pdev->dev; +	info->max77686 = max77686; +	info->rtc = max77686->rtc; +	info->max77686->rtc_regmap = regmap_init_i2c(info->max77686->rtc, +					 &max77686_rtc_regmap_config); +	if (IS_ERR(info->max77686->rtc_regmap)) { +		ret = PTR_ERR(info->max77686->rtc_regmap); +		dev_err(info->max77686->dev, "Failed to allocate register map: %d\n", +				ret); +		kfree(info); +		return ret; +	} +	platform_set_drvdata(pdev, info); + +	ret = max77686_rtc_init_reg(info); + +	if (ret < 0) { +		dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); +		goto err_rtc; +	} + +#ifdef MAX77686_RTC_WTSR_SMPL +	max77686_rtc_enable_wtsr(info, true); +	max77686_rtc_enable_smpl(info, true); +#endif + +	device_init_wakeup(&pdev->dev, 1); + +	info->rtc_dev = rtc_device_register("max77686-rtc", &pdev->dev, +			&max77686_rtc_ops, THIS_MODULE); + +	if (IS_ERR(info->rtc_dev)) { +		dev_info(&pdev->dev, "%s: fail\n", __func__); + +		ret = PTR_ERR(info->rtc_dev); +		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); +		if (ret == 0) +			ret = -EINVAL; +		goto err_rtc; +	} +	virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1); +	if (!virq) +		goto err_rtc; +	info->virq = virq; + +	ret = request_threaded_irq(virq, NULL, max77686_rtc_alarm_irq, 0, +			"rtc-alarm0", info); +	if (ret < 0) { +		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", +			info->virq, ret); +		goto err_rtc; +	} + +	goto out; +err_rtc: +	kfree(info); +	return ret; +out: +	return ret; +} + +static int max77686_rtc_remove(struct platform_device *pdev) +{ +	struct max77686_rtc_info *info = platform_get_drvdata(pdev); + +	if (info) { +		free_irq(info->virq, info); +		rtc_device_unregister(info->rtc_dev); +		kfree(info); +	} + +	return 0; +} + +static void max77686_rtc_shutdown(struct platform_device *pdev) +{ +#ifdef MAX77686_RTC_WTSR_SMPL +	struct max77686_rtc_info *info = platform_get_drvdata(pdev); +	int i; +	u8 val = 0; + +	for (i = 0; i < 3; i++) { +		max77686_rtc_enable_wtsr(info, false); +		regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); +		pr_info("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val); +		if (val & WTSR_EN_MASK) +			pr_emerg("%s: fail to disable WTSR\n", __func__); +		else { +			pr_info("%s: success to disable WTSR\n", __func__); +			break; +		} +	} + +	/* Disable SMPL when power off */ +	max77686_rtc_enable_smpl(info, false); +#endif /* MAX77686_RTC_WTSR_SMPL */ +} + +static const struct platform_device_id rtc_id[] = { +	{ "max77686-rtc", 0 }, +	{}, +}; + +static struct platform_driver max77686_rtc_driver = { +	.driver		= { +		.name	= "max77686-rtc", +		.owner	= THIS_MODULE, +	}, +	.probe		= max77686_rtc_probe, +	.remove		= max77686_rtc_remove, +	.shutdown	= max77686_rtc_shutdown, +	.id_table	= rtc_id, +}; + +static int __init max77686_rtc_init(void) +{ +	return platform_driver_register(&max77686_rtc_driver); +} +module_init(max77686_rtc_init); + +static void __exit max77686_rtc_exit(void) +{ +	platform_driver_unregister(&max77686_rtc_driver); +} +module_exit(max77686_rtc_exit); + +MODULE_DESCRIPTION("Maxim MAX77686 RTC driver"); +MODULE_AUTHOR("<[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index 1d049da16c85..31ca8faf9f05 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c @@ -205,8 +205,9 @@ static int max8907_rtc_probe(struct platform_device *pdev)  		goto err_unregister;  	} -	ret = request_threaded_irq(rtc->irq, NULL, max8907_irq_handler, -				   IRQF_ONESHOT, "max8907-alarm0", rtc); +	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, +				max8907_irq_handler, +				IRQF_ONESHOT, "max8907-alarm0", rtc);  	if (ret < 0) {  		dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n",  			rtc->irq, ret); @@ -224,7 +225,6 @@ static int max8907_rtc_remove(struct platform_device *pdev)  {  	struct max8907_rtc *rtc = platform_get_drvdata(pdev); -	free_irq(rtc->irq, rtc);  	rtc_device_unregister(rtc->rtc_dev);  	return 0; diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c new file mode 100644 index 000000000000..00e505b6bee3 --- /dev/null +++ b/drivers/rtc/rtc-max8997.c @@ -0,0 +1,552 @@ +/* + * RTC driver for Maxim MAX8997 + * + * Copyright (C) 2013 Samsung Electronics Co.Ltd + * + *  based on rtc-max8998.c + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + */ + +#include <linux/slab.h> +#include <linux/rtc.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/mfd/max8997-private.h> +#include <linux/irqdomain.h> + +/* Module parameter for WTSR function control */ +static int wtsr_en = 1; +module_param(wtsr_en, int, 0444); +MODULE_PARM_DESC(wtsr_en, "Wachdog Timeout & Sofware Reset (default=on)"); +/* Module parameter for SMPL function control */ +static int smpl_en = 1; +module_param(smpl_en, int, 0444); +MODULE_PARM_DESC(smpl_en, "Sudden Momentary Power Loss (default=on)"); + +/* RTC Control Register */ +#define BCD_EN_SHIFT			0 +#define BCD_EN_MASK			(1 << BCD_EN_SHIFT) +#define MODEL24_SHIFT			1 +#define MODEL24_MASK			(1 << MODEL24_SHIFT) +/* RTC Update Register1 */ +#define RTC_UDR_SHIFT			0 +#define RTC_UDR_MASK			(1 << RTC_UDR_SHIFT) +/* WTSR and SMPL Register */ +#define WTSRT_SHIFT			0 +#define SMPLT_SHIFT			2 +#define WTSR_EN_SHIFT			6 +#define SMPL_EN_SHIFT			7 +#define WTSRT_MASK			(3 << WTSRT_SHIFT) +#define SMPLT_MASK			(3 << SMPLT_SHIFT) +#define WTSR_EN_MASK			(1 << WTSR_EN_SHIFT) +#define SMPL_EN_MASK			(1 << SMPL_EN_SHIFT) +/* RTC Hour register */ +#define HOUR_PM_SHIFT			6 +#define HOUR_PM_MASK			(1 << HOUR_PM_SHIFT) +/* RTC Alarm Enable */ +#define ALARM_ENABLE_SHIFT		7 +#define ALARM_ENABLE_MASK		(1 << ALARM_ENABLE_SHIFT) + +enum { +	RTC_SEC = 0, +	RTC_MIN, +	RTC_HOUR, +	RTC_WEEKDAY, +	RTC_MONTH, +	RTC_YEAR, +	RTC_DATE, +	RTC_NR_TIME +}; + +struct max8997_rtc_info { +	struct device		*dev; +	struct max8997_dev	*max8997; +	struct i2c_client	*rtc; +	struct rtc_device	*rtc_dev; +	struct mutex		lock; +	int virq; +	int rtc_24hr_mode; +}; + +static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm, +				   int rtc_24hr_mode) +{ +	tm->tm_sec = data[RTC_SEC] & 0x7f; +	tm->tm_min = data[RTC_MIN] & 0x7f; +	if (rtc_24hr_mode) +		tm->tm_hour = data[RTC_HOUR] & 0x1f; +	else { +		tm->tm_hour = data[RTC_HOUR] & 0x0f; +		if (data[RTC_HOUR] & HOUR_PM_MASK) +			tm->tm_hour += 12; +	} + +	tm->tm_wday = fls(data[RTC_WEEKDAY] & 0x7f) - 1; +	tm->tm_mday = data[RTC_DATE] & 0x1f; +	tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; +	tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; +	tm->tm_yday = 0; +	tm->tm_isdst = 0; +} + +static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data) +{ +	data[RTC_SEC] = tm->tm_sec; +	data[RTC_MIN] = tm->tm_min; +	data[RTC_HOUR] = tm->tm_hour; +	data[RTC_WEEKDAY] = 1 << tm->tm_wday; +	data[RTC_DATE] = tm->tm_mday; +	data[RTC_MONTH] = tm->tm_mon + 1; +	data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0 ; + +	if (tm->tm_year < 100) { +		pr_warn("%s: MAX8997 RTC cannot handle the year %d." +			"Assume it's 2000.\n", __func__, 1900 + tm->tm_year); +		return -EINVAL; +	} +	return 0; +} + +static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info) +{ +	int ret; + +	ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1, +						RTC_UDR_MASK); +	if (ret < 0) +		dev_err(info->dev, "%s: fail to write update reg(%d)\n", +				__func__, ret); +	else { +		/* Minimum 16ms delay required before RTC update. +		 * Otherwise, we may read and update based on out-of-date +		 * value */ +		msleep(20); +	} + +	return ret; +} + +static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct max8997_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	mutex_lock(&info->lock); +	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); +	mutex_unlock(&info->lock); + +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, +				ret); +		return ret; +	} + +	max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); + +	return rtc_valid_tm(tm); +} + +static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct max8997_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	ret = max8997_rtc_tm_to_data(tm, data); +	if (ret < 0) +		return ret; + +	mutex_lock(&info->lock); + +	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, +				ret); +		goto out; +	} + +	ret = max8997_rtc_set_update_reg(info); +out: +	mutex_unlock(&info->lock); +	return ret; +} + +static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct max8997_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	u8 val; +	int i, ret; + +	mutex_lock(&info->lock); + +	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +			data); +	if (ret < 0) { +		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", +				__func__, __LINE__, ret); +		goto out; +	} + +	max8997_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); + +	alrm->enabled = 0; +	for (i = 0; i < RTC_NR_TIME; i++) { +		if (data[i] & ALARM_ENABLE_MASK) { +			alrm->enabled = 1; +			break; +		} +	} + +	alrm->pending = 0; +	ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val); +	if (ret < 0) { +		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", +				__func__, __LINE__, ret); +		goto out; +	} + +	if (val & (1 << 4)) /* RTCA1 */ +		alrm->pending = 1; + +out: +	mutex_unlock(&info->lock); +	return 0; +} + +static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info) +{ +	u8 data[RTC_NR_TIME]; +	int ret, i; + +	if (!mutex_is_locked(&info->lock)) +		dev_warn(info->dev, "%s: should have mutex locked\n", __func__); + +	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +				data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	for (i = 0; i < RTC_NR_TIME; i++) +		data[i] &= ~ALARM_ENABLE_MASK; + +	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +				 data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max8997_rtc_set_update_reg(info); +out: +	return ret; +} + +static int max8997_rtc_start_alarm(struct max8997_rtc_info *info) +{ +	u8 data[RTC_NR_TIME]; +	int ret; + +	if (!mutex_is_locked(&info->lock)) +		dev_warn(info->dev, "%s: should have mutex locked\n", __func__); + +	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +				data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); +	data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; +	if (data[RTC_MONTH] & 0xf) +		data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); +	if (data[RTC_YEAR] & 0x7f) +		data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); +	if (data[RTC_DATE] & 0x1f) +		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + +	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +				 data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max8997_rtc_set_update_reg(info); +out: +	return ret; +} +static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct max8997_rtc_info *info = dev_get_drvdata(dev); +	u8 data[RTC_NR_TIME]; +	int ret; + +	ret = max8997_rtc_tm_to_data(&alrm->time, data); +	if (ret < 0) +		return ret; + +	dev_info(info->dev, "%s: %d-%02d-%02d %02d:%02d:%02d\n", __func__, +			data[RTC_YEAR] + 2000, data[RTC_MONTH], data[RTC_DATE], +			data[RTC_HOUR], data[RTC_MIN], data[RTC_SEC]); + +	mutex_lock(&info->lock); + +	ret = max8997_rtc_stop_alarm(info); +	if (ret < 0) +		goto out; + +	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, +				data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", +				__func__, ret); +		goto out; +	} + +	ret = max8997_rtc_set_update_reg(info); +	if (ret < 0) +		goto out; + +	if (alrm->enabled) +		ret = max8997_rtc_start_alarm(info); +out: +	mutex_unlock(&info->lock); +	return ret; +} + +static int max8997_rtc_alarm_irq_enable(struct device *dev, +					unsigned int enabled) +{ +	struct max8997_rtc_info *info = dev_get_drvdata(dev); +	int ret; + +	mutex_lock(&info->lock); +	if (enabled) +		ret = max8997_rtc_start_alarm(info); +	else +		ret = max8997_rtc_stop_alarm(info); +	mutex_unlock(&info->lock); + +	return ret; +} + +static irqreturn_t max8997_rtc_alarm_irq(int irq, void *data) +{ +	struct max8997_rtc_info *info = data; + +	dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); + +	rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); + +	return IRQ_HANDLED; +} + +static const struct rtc_class_ops max8997_rtc_ops = { +	.read_time = max8997_rtc_read_time, +	.set_time = max8997_rtc_set_time, +	.read_alarm = max8997_rtc_read_alarm, +	.set_alarm = max8997_rtc_set_alarm, +	.alarm_irq_enable = max8997_rtc_alarm_irq_enable, +}; + +static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable) +{ +	int ret; +	u8 val, mask; + +	if (!wtsr_en) +		return; + +	if (enable) +		val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); +	else +		val = 0; + +	mask = WTSR_EN_MASK | WTSRT_MASK; + +	dev_info(info->dev, "%s: %s WTSR\n", __func__, +			enable ? "enable" : "disable"); + +	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", +				__func__, ret); +		return; +	} + +	max8997_rtc_set_update_reg(info); +} + +static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable) +{ +	int ret; +	u8 val, mask; + +	if (!smpl_en) +		return; + +	if (enable) +		val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); +	else +		val = 0; + +	mask = SMPL_EN_MASK | SMPLT_MASK; + +	dev_info(info->dev, "%s: %s SMPL\n", __func__, +			enable ? "enable" : "disable"); + +	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", +				__func__, ret); +		return; +	} + +	max8997_rtc_set_update_reg(info); + +	val = 0; +	max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val); +	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); +} + +static int max8997_rtc_init_reg(struct max8997_rtc_info *info) +{ +	u8 data[2]; +	int ret; + +	/* Set RTC control register : Binary mode, 24hour mdoe */ +	data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); +	data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); + +	info->rtc_24hr_mode = 1; + +	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data); +	if (ret < 0) { +		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", +				__func__, ret); +		return ret; +	} + +	ret = max8997_rtc_set_update_reg(info); +	return ret; +} + +static int max8997_rtc_probe(struct platform_device *pdev) +{ +	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); +	struct max8997_rtc_info *info; +	int ret, virq; + +	info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_rtc_info), +			GFP_KERNEL); +	if (!info) +		return -ENOMEM; + +	mutex_init(&info->lock); +	info->dev = &pdev->dev; +	info->max8997 = max8997; +	info->rtc = max8997->rtc; + +	platform_set_drvdata(pdev, info); + +	ret = max8997_rtc_init_reg(info); + +	if (ret < 0) { +		dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); +		return ret; +	} + +	max8997_rtc_enable_wtsr(info, true); +	max8997_rtc_enable_smpl(info, true); + +	device_init_wakeup(&pdev->dev, 1); + +	info->rtc_dev = rtc_device_register("max8997-rtc", &pdev->dev, +			&max8997_rtc_ops, THIS_MODULE); + +	if (IS_ERR(info->rtc_dev)) { +		ret = PTR_ERR(info->rtc_dev); +		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); +		return ret; +	} + +	virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1); +	if (!virq) { +		dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n"); +		goto err_out; +	} +	info->virq = virq; + +	ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, +				max8997_rtc_alarm_irq, 0, +				"rtc-alarm0", info); +	if (ret < 0) { +		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", +			info->virq, ret); +		goto err_out; +	} + +	return ret; + +err_out: +	rtc_device_unregister(info->rtc_dev); +	return ret; +} + +static int max8997_rtc_remove(struct platform_device *pdev) +{ +	struct max8997_rtc_info *info = platform_get_drvdata(pdev); + +	if (info) +		rtc_device_unregister(info->rtc_dev); + +	return 0; +} + +static void max8997_rtc_shutdown(struct platform_device *pdev) +{ +	struct max8997_rtc_info *info = platform_get_drvdata(pdev); + +	max8997_rtc_enable_wtsr(info, false); +	max8997_rtc_enable_smpl(info, false); +} + +static const struct platform_device_id rtc_id[] = { +	{ "max8997-rtc", 0 }, +	{}, +}; + +static struct platform_driver max8997_rtc_driver = { +	.driver		= { +		.name	= "max8997-rtc", +		.owner	= THIS_MODULE, +	}, +	.probe		= max8997_rtc_probe, +	.remove		= max8997_rtc_remove, +	.shutdown	= max8997_rtc_shutdown, +	.id_table	= rtc_id, +}; + +module_platform_driver(max8997_rtc_driver); + +MODULE_DESCRIPTION("Maxim MAX8997 RTC driver"); +MODULE_AUTHOR("<[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index bec10be96f84..bdcc60830aec 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -13,6 +13,7 @@  #include <linux/init.h>  #include <linux/module.h>  #include <linux/rtc.h> +#include <linux/of.h>  #include <linux/of_device.h>  #include <linux/of_platform.h>  #include <linux/io.h> @@ -403,17 +404,19 @@ static int mpc5121_rtc_remove(struct platform_device *op)  	return 0;  } +#ifdef CONFIG_OF  static struct of_device_id mpc5121_rtc_match[] = {  	{ .compatible = "fsl,mpc5121-rtc", },  	{ .compatible = "fsl,mpc5200-rtc", },  	{},  }; +#endif  static struct platform_driver mpc5121_rtc_driver = {  	.driver = {  		.name = "mpc5121-rtc",  		.owner = THIS_MODULE, -		.of_match_table = mpc5121_rtc_match, +		.of_match_table = of_match_ptr(mpc5121_rtc_match),  	},  	.probe = mpc5121_rtc_probe,  	.remove = mpc5121_rtc_remove, diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index be05a645f99e..889e3160e701 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -23,6 +23,7 @@  #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */  #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */  #define REG_CONTROL3_PM_MASK 0xe0 +#define REG_CONTROL3_BLF (1 << 2) /* battery low bit, read-only */  #define REG_SECONDS  0x03  #define REG_SECONDS_OS (1 << 7) @@ -250,9 +251,39 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return pcf8523_start_rtc(client);  } +#ifdef CONFIG_RTC_INTF_DEV +static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, +			     unsigned long arg) +{ +	struct i2c_client *client = to_i2c_client(dev); +	u8 value; +	int ret = 0, err; + +	switch (cmd) { +	case RTC_VL_READ: +		err = pcf8523_read(client, REG_CONTROL3, &value); +		if (err < 0) +			return err; + +		if (value & REG_CONTROL3_BLF) +			ret = 1; + +		if (copy_to_user((void __user *)arg, &ret, sizeof(int))) +			return -EFAULT; + +		return 0; +	default: +		return -ENOIOCTLCMD; +	} +} +#else +#define pcf8523_rtc_ioctl NULL +#endif +  static const struct rtc_class_ops pcf8523_rtc_ops = {  	.read_time = pcf8523_rtc_read_time,  	.set_time = pcf8523_rtc_set_time, +	.ioctl = pcf8523_rtc_ioctl,  };  static int pcf8523_probe(struct i2c_client *client, diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 7098ee89bd29..f7daf18a112e 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -181,7 +181,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)  				__func__, err, data[0], data[1]);  			return -EIO;  		} -	}; +	}  	return 0;  } diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 3415b8f18555..5f97c61247d5 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -185,8 +185,8 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)  	if (ctrl & (CTRL_STOP | CTRL_HOLD)) {  		unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD); -		printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", -		       ctrl, new_ctrl); +		dev_warn(dev, "resetting control %02x -> %02x\n", +			ctrl, new_ctrl);  		if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0)  			return err; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08378e3cc21c..8900ea784817 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -44,6 +44,7 @@  #define RTC_YMR		0x34	/* Year match register */  #define RTC_YLR		0x38	/* Year data load register */ +#define RTC_CR_EN	(1 << 0)	/* counter enable bit */  #define RTC_CR_CWEN	(1 << 26)	/* Clockwatch enable bit */  #define RTC_TCR_EN	(1 << 1) /* Periodic timer enable bit */ @@ -320,7 +321,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)  	struct pl031_local *ldata;  	struct pl031_vendor_data *vendor = id->data;  	struct rtc_class_ops *ops = &vendor->ops; -	unsigned long time; +	unsigned long time, data;  	ret = amba_request_regions(adev, NULL);  	if (ret) @@ -345,10 +346,13 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)  	dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));  	dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev)); +	data = readl(ldata->base + RTC_CR);  	/* Enable the clockwatch on ST Variants */  	if (vendor->clockwatch) -		writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, -		       ldata->base + RTC_CR); +		data |= RTC_CR_CWEN; +	else +		data |= RTC_CR_EN; +	writel(data, ldata->base + RTC_CR);  	/*  	 * On ST PL031 variants, the RTC reset value does not provide correct @@ -380,6 +384,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)  		goto out_no_irq;  	} +	device_init_wakeup(&adev->dev, 1); +  	return 0;  out_no_irq: diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index f771b2ee4b18..03c85ee719a7 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -62,6 +62,10 @@  #define RYxR_MONTH_S	5  #define RYxR_MONTH_MASK	(0xf << RYxR_MONTH_S)  #define RYxR_DAY_MASK	0x1f +#define RDxR_WOM_S     20 +#define RDxR_WOM_MASK  (0x7 << RDxR_WOM_S) +#define RDxR_DOW_S     17 +#define RDxR_DOW_MASK  (0x7 << RDxR_DOW_S)  #define RDxR_HOUR_S	12  #define RDxR_HOUR_MASK	(0x1f << RDxR_HOUR_S)  #define RDxR_MIN_S	6 @@ -91,6 +95,7 @@ struct pxa_rtc {  	spinlock_t		lock;		/* Protects this structure */  }; +  static u32 ryxr_calc(struct rtc_time *tm)  {  	return ((tm->tm_year + 1900) << RYxR_YEAR_S) @@ -100,7 +105,10 @@ static u32 ryxr_calc(struct rtc_time *tm)  static u32 rdxr_calc(struct rtc_time *tm)  { -	return (tm->tm_hour << RDxR_HOUR_S) | (tm->tm_min << RDxR_MIN_S) +	return ((((tm->tm_mday + 6) / 7) << RDxR_WOM_S) & RDxR_WOM_MASK) +		| (((tm->tm_wday + 1) << RDxR_DOW_S) & RDxR_DOW_MASK) +		| (tm->tm_hour << RDxR_HOUR_S) +		| (tm->tm_min << RDxR_MIN_S)  		| tm->tm_sec;  } @@ -109,6 +117,7 @@ static void tm_calc(u32 rycr, u32 rdcr, struct rtc_time *tm)  	tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900;  	tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1;  	tm->tm_mday = (rycr & RYxR_DAY_MASK); +	tm->tm_wday = ((rycr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1;  	tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S;  	tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S;  	tm->tm_sec = rdcr & RDxR_SEC_MASK; @@ -300,8 +309,6 @@ static int pxa_rtc_proc(struct device *dev, struct seq_file *seq)  }  static const struct rtc_class_ops pxa_rtc_ops = { -	.open = pxa_rtc_open, -	.release = pxa_rtc_release,  	.read_time = pxa_rtc_read_time,  	.set_time = pxa_rtc_set_time,  	.read_alarm = pxa_rtc_read_alarm, @@ -341,7 +348,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)  		dev_err(dev, "No alarm IRQ resource defined\n");  		goto err_ress;  	} - +	pxa_rtc_open(dev);  	ret = -ENOMEM;  	pxa_rtc->base = ioremap(pxa_rtc->ress->start,  				resource_size(pxa_rtc->ress)); @@ -387,6 +394,9 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev)  {  	struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev); +	struct device *dev = &pdev->dev; +	pxa_rtc_release(dev); +  	rtc_device_unregister(pxa_rtc->rtc);  	spin_lock_irq(&pxa_rtc->lock); @@ -444,10 +454,7 @@ static struct platform_driver pxa_rtc_driver = {  static int __init pxa_rtc_init(void)  { -	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) -		return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe); - -	return -ENODEV; +	return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe);  }  static void __exit pxa_rtc_exit(void) diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index d1aee793ecc8..d98ea5b759c8 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c @@ -39,6 +39,8 @@   *	1.13	Nobuhiro Iwamatsu: Updata driver.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/err.h>  #include <linux/rtc.h> @@ -352,8 +354,7 @@ static void rs5c313_check_xstp_bit(void)  		tm.tm_year 	= 2000 - 1900;  		rs5c313_rtc_set_time(NULL, &tm); -		printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to " -				"1 Jan 2000\n"); +		pr_err("invalid value, resetting to 1 Jan 2000\n");  	}  	RS5C313_CEDISABLE;  	ndelay(700);		/* CE:L */ diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 76f565ae384d..581739f40097 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -311,8 +311,7 @@ static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)  		buf &= ~RS5C_CTRL1_AALE;  	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { -		printk(KERN_WARNING "%s: can't update alarm\n", -			rs5c->rtc->name); +		dev_warn(dev, "can't update alarm\n");  		status = -EIO;  	} else  		rs5c->regs[RS5C_REG_CTRL1] = buf; @@ -381,7 +380,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  		addr = RS5C_ADDR(RS5C_REG_CTRL1);  		buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;  		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { -			pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); +			dev_dbg(dev, "can't disable alarm\n");  			return -EIO;  		}  		rs5c->regs[RS5C_REG_CTRL1] = buf[0]; @@ -395,7 +394,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	for (i = 0; i < sizeof(buf); i++) {  		addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);  		if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { -			pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); +			dev_dbg(dev, "can't set alarm time\n");  			return -EIO;  		}  	} @@ -405,8 +404,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  		addr = RS5C_ADDR(RS5C_REG_CTRL1);  		buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;  		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) -			printk(KERN_WARNING "%s: can't enable alarm\n", -				rs5c->rtc->name); +			dev_warn(dev, "can't enable alarm\n");  		rs5c->regs[RS5C_REG_CTRL1] = buf[0];  	} diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c new file mode 100644 index 000000000000..599ec73ec886 --- /dev/null +++ b/drivers/rtc/rtc-rx4581.c @@ -0,0 +1,314 @@ +/* drivers/rtc/rtc-rx4581.c + * + * written by Torben Hohn <[email protected]> + * + * Based on: + * drivers/rtc/rtc-max6902.c + * + * Copyright (C) 2006 8D Technologies inc. + * Copyright (C) 2004 Compulab Ltd. + * + * 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 + * published by the Free Software Foundation. + * + * Driver for MAX6902 spi RTC + * + * and based on: + * drivers/rtc/rtc-rx8581.c + * + * An I2C driver for the Epson RX8581 RTC + * + * Author: Martyn Welch <[email protected]> + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * 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 + * published by the Free Software Foundation. + * + * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) + * Copyright 2005-06 Tower Technologies + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/rtc.h> +#include <linux/spi/spi.h> +#include <linux/bcd.h> + +#define RX4581_REG_SC		0x00 /* Second in BCD */ +#define RX4581_REG_MN		0x01 /* Minute in BCD */ +#define RX4581_REG_HR		0x02 /* Hour in BCD */ +#define RX4581_REG_DW		0x03 /* Day of Week */ +#define RX4581_REG_DM		0x04 /* Day of Month in BCD */ +#define RX4581_REG_MO		0x05 /* Month in BCD */ +#define RX4581_REG_YR		0x06 /* Year in BCD */ +#define RX4581_REG_RAM		0x07 /* RAM */ +#define RX4581_REG_AMN		0x08 /* Alarm Min in BCD*/ +#define RX4581_REG_AHR		0x09 /* Alarm Hour in BCD */ +#define RX4581_REG_ADM		0x0A +#define RX4581_REG_ADW		0x0A +#define RX4581_REG_TMR0		0x0B +#define RX4581_REG_TMR1		0x0C +#define RX4581_REG_EXT		0x0D /* Extension Register */ +#define RX4581_REG_FLAG		0x0E /* Flag Register */ +#define RX4581_REG_CTRL		0x0F /* Control Register */ + + +/* Flag Register bit definitions */ +#define RX4581_FLAG_UF		0x20 /* Update */ +#define RX4581_FLAG_TF		0x10 /* Timer */ +#define RX4581_FLAG_AF		0x08 /* Alarm */ +#define RX4581_FLAG_VLF		0x02 /* Voltage Low */ + +/* Control Register bit definitions */ +#define RX4581_CTRL_UIE		0x20 /* Update Interrupt Enable */ +#define RX4581_CTRL_TIE		0x10 /* Timer Interrupt Enable */ +#define RX4581_CTRL_AIE		0x08 /* Alarm Interrupt Enable */ +#define RX4581_CTRL_STOP	0x02 /* STOP bit */ +#define RX4581_CTRL_RESET	0x01 /* RESET bit */ + +static int rx4581_set_reg(struct device *dev, unsigned char address, +				unsigned char data) +{ +	struct spi_device *spi = to_spi_device(dev); +	unsigned char buf[2]; + +	/* high nibble must be '0' to write */ +	buf[0] = address & 0x0f; +	buf[1] = data; + +	return spi_write_then_read(spi, buf, 2, NULL, 0); +} + +static int rx4581_get_reg(struct device *dev, unsigned char address, +				unsigned char *data) +{ +	struct spi_device *spi = to_spi_device(dev); + +	/* Set MSB to indicate read */ +	*data = address | 0x80; + +	return spi_write_then_read(spi, data, 1, data, 1); +} + +/* + * In the routines that deal directly with the rx8581 hardware, we use + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. + */ +static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm) +{ +	struct spi_device *spi = to_spi_device(dev); +	unsigned char date[7]; +	unsigned char data; +	int err; + +	/* First we ensure that the "update flag" is not set, we read the +	 * time and date then re-read the "update flag". If the update flag +	 * has been set, we know that the time has changed during the read so +	 * we repeat the whole process again. +	 */ +	err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); +	if (err != 0) { +		dev_err(dev, "Unable to read device flags\n"); +		return -EIO; +	} + +	do { +		/* If update flag set, clear it */ +		if (data & RX4581_FLAG_UF) { +			err = rx4581_set_reg(dev, +				RX4581_REG_FLAG, (data & ~RX4581_FLAG_UF)); +			if (err != 0) { +				dev_err(dev, "Unable to write device " +					"flags\n"); +				return -EIO; +			} +		} + +		/* Now read time and date */ +		date[0] = 0x80; +		err = spi_write_then_read(spi, date, 1, date, 7); +		if (err < 0) { +			dev_err(dev, "Unable to read date\n"); +			return -EIO; +		} + +		/* Check flag register */ +		err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); +		if (err != 0) { +			dev_err(dev, "Unable to read device flags\n"); +			return -EIO; +		} +	} while (data & RX4581_FLAG_UF); + +	if (data & RX4581_FLAG_VLF) +		dev_info(dev, +			"low voltage detected, date/time is not reliable.\n"); + +	dev_dbg(dev, +		"%s: raw data is sec=%02x, min=%02x, hr=%02x, " +		"wday=%02x, mday=%02x, mon=%02x, year=%02x\n", +		__func__, +		date[0], date[1], date[2], date[3], date[4], date[5], date[6]); + +	tm->tm_sec = bcd2bin(date[RX4581_REG_SC] & 0x7F); +	tm->tm_min = bcd2bin(date[RX4581_REG_MN] & 0x7F); +	tm->tm_hour = bcd2bin(date[RX4581_REG_HR] & 0x3F); /* rtc hr 0-23 */ +	tm->tm_wday = ilog2(date[RX4581_REG_DW] & 0x7F); +	tm->tm_mday = bcd2bin(date[RX4581_REG_DM] & 0x3F); +	tm->tm_mon = bcd2bin(date[RX4581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ +	tm->tm_year = bcd2bin(date[RX4581_REG_YR]); +	if (tm->tm_year < 70) +		tm->tm_year += 100;	/* assume we are in 1970...2069 */ + + +	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " +		"mday=%d, mon=%d, year=%d, wday=%d\n", +		__func__, +		tm->tm_sec, tm->tm_min, tm->tm_hour, +		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + +	err = rtc_valid_tm(tm); +	if (err < 0) +		dev_err(dev, "retrieved date/time is not valid.\n"); + +	return err; +} + +static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm) +{ +	struct spi_device *spi = to_spi_device(dev); +	int err; +	unsigned char buf[8], data; + +	dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " +		"mday=%d, mon=%d, year=%d, wday=%d\n", +		__func__, +		tm->tm_sec, tm->tm_min, tm->tm_hour, +		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + +	buf[0] = 0x00; +	/* hours, minutes and seconds */ +	buf[RX4581_REG_SC+1] = bin2bcd(tm->tm_sec); +	buf[RX4581_REG_MN+1] = bin2bcd(tm->tm_min); +	buf[RX4581_REG_HR+1] = bin2bcd(tm->tm_hour); + +	buf[RX4581_REG_DM+1] = bin2bcd(tm->tm_mday); + +	/* month, 1 - 12 */ +	buf[RX4581_REG_MO+1] = bin2bcd(tm->tm_mon + 1); + +	/* year and century */ +	buf[RX4581_REG_YR+1] = bin2bcd(tm->tm_year % 100); +	buf[RX4581_REG_DW+1] = (0x1 << tm->tm_wday); + +	/* Stop the clock */ +	err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data); +	if (err != 0) { +		dev_err(dev, "Unable to read control register\n"); +		return -EIO; +	} + +	err = rx4581_set_reg(dev, RX4581_REG_CTRL, +		(data | RX4581_CTRL_STOP)); +	if (err != 0) { +		dev_err(dev, "Unable to write control register\n"); +		return -EIO; +	} + +	/* write register's data */ +	err = spi_write_then_read(spi, buf, 8, NULL, 0); +	if (err != 0) { +		dev_err(dev, "Unable to write to date registers\n"); +		return -EIO; +	} + +	/* get VLF and clear it */ +	err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); +	if (err != 0) { +		dev_err(dev, "Unable to read flag register\n"); +		return -EIO; +	} + +	err = rx4581_set_reg(dev, RX4581_REG_FLAG, +		(data & ~(RX4581_FLAG_VLF))); +	if (err != 0) { +		dev_err(dev, "Unable to write flag register\n"); +		return -EIO; +	} + +	/* Restart the clock */ +	err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data); +	if (err != 0) { +		dev_err(dev, "Unable to read control register\n"); +		return -EIO; +	} + +	err = rx4581_set_reg(dev, RX4581_REG_CTRL, +		(data & ~(RX4581_CTRL_STOP))); +	if (err != 0) { +		dev_err(dev, "Unable to write control register\n"); +		return -EIO; +	} + +	return 0; +} + +static const struct rtc_class_ops rx4581_rtc_ops = { +	.read_time	= rx4581_get_datetime, +	.set_time	= rx4581_set_datetime, +}; + +static int rx4581_probe(struct spi_device *spi) +{ +	struct rtc_device *rtc; +	unsigned char tmp; +	int res; + +	res = rx4581_get_reg(&spi->dev, RX4581_REG_SC, &tmp); +	if (res != 0) +		return res; + +	rtc = rtc_device_register("rx4581", +				&spi->dev, &rx4581_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc)) +		return PTR_ERR(rtc); + +	dev_set_drvdata(&spi->dev, rtc); +	return 0; +} + +static int rx4581_remove(struct spi_device *spi) +{ +	struct rtc_device *rtc = dev_get_drvdata(&spi->dev); + +	rtc_device_unregister(rtc); +	return 0; +} + +static const struct spi_device_id rx4581_id[] = { +	{ "rx4581", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(spi, rx4581_id); + +static struct spi_driver rx4581_driver = { +	.driver = { +		.name	= "rtc-rx4581", +		.owner	= THIS_MODULE, +	}, +	.probe	= rx4581_probe, +	.remove = rx4581_remove, +	.id_table = rx4581_id, +}; + +module_spi_driver(rx4581_driver); + +MODULE_DESCRIPTION("rx4581 spi RTC driver"); +MODULE_AUTHOR("Torben Hohn"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rtc-rx4581"); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 404651464d45..fb994e9ddc15 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -115,7 +115,7 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)  {  	unsigned int tmp; -	pr_debug("%s: aie=%d\n", __func__, enabled); +	dev_dbg(dev, "%s: aie=%d\n", __func__, enabled);  	clk_enable(rtc_clk);  	tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; @@ -203,7 +203,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  	rtc_tm->tm_year += 100; -	pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", +	dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",  		 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,  		 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); @@ -218,7 +218,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; -	pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", +	dev_dbg(dev, "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); @@ -259,7 +259,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)  	alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; -	pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", +	dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",  		 alm_en,  		 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,  		 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); @@ -310,7 +310,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  	unsigned int alrm_en;  	clk_enable(rtc_clk); -	pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", +	dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",  		 alrm->enabled,  		 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,  		 tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -333,7 +333,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  		writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);  	} -	pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); +	dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);  	writeb(alrm_en, base + S3C2410_RTCALM); @@ -459,7 +459,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)  	int ret;  	int tmp; -	pr_debug("%s: probe=%p\n", __func__, pdev); +	dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev);  	/* find the IRQs */ @@ -475,7 +475,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)  		return s3c_rtc_alarmno;  	} -	pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", +	dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",  		 s3c_rtc_tickno, s3c_rtc_alarmno);  	/* get the memory region */ @@ -486,11 +486,9 @@ static int s3c_rtc_probe(struct platform_device *pdev)  		return -ENOENT;  	} -	s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res); -	if (s3c_rtc_base == NULL) { -		dev_err(&pdev->dev, "failed to ioremap memory region\n"); -		return -EINVAL; -	} +	s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(s3c_rtc_base)) +		return PTR_ERR(s3c_rtc_base);  	rtc_clk = devm_clk_get(&pdev->dev, "rtc");  	if (IS_ERR(rtc_clk)) { @@ -506,7 +504,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)  	s3c_rtc_enable(pdev, 1); -	pr_debug("s3c2410_rtc: RTCCON=%02x\n", +	dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",  		 readw(s3c_rtc_base + S3C2410_RTCCON));  	device_init_wakeup(&pdev->dev, 1); diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 50a5c4adee48..5ec5036df0bc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -108,9 +108,6 @@ static int sa1100_rtc_open(struct device *dev)  	struct rtc_device *rtc = info->rtc;  	int ret; -	ret = clk_prepare_enable(info->clk); -	if (ret) -		goto fail_clk;  	ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", dev);  	if (ret) {  		dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz); @@ -130,7 +127,6 @@ static int sa1100_rtc_open(struct device *dev)  	free_irq(info->irq_1hz, dev);   fail_ui:  	clk_disable_unprepare(info->clk); - fail_clk:  	return ret;  } @@ -144,7 +140,6 @@ static void sa1100_rtc_release(struct device *dev)  	free_irq(info->irq_alarm, dev);  	free_irq(info->irq_1hz, dev); -	clk_disable_unprepare(info->clk);  }  static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) @@ -253,6 +248,9 @@ static int sa1100_rtc_probe(struct platform_device *pdev)  	spin_lock_init(&info->lock);  	platform_set_drvdata(pdev, info); +	ret = clk_prepare_enable(info->clk); +	if (ret) +		goto err_enable_clk;  	/*  	 * According to the manual we should be able to let RTTR be zero  	 * and then a default diviser for a 32.768KHz clock is used. @@ -305,6 +303,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)  	return 0;  err_dev: +	clk_disable_unprepare(info->clk); +err_enable_clk:  	platform_set_drvdata(pdev, NULL);  	clk_put(info->clk);  err_clk: @@ -318,6 +318,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)  	if (info) {  		rtc_device_unregister(info->rtc); +		clk_disable_unprepare(info->clk);  		clk_put(info->clk);  		platform_set_drvdata(pdev, NULL);  		kfree(info); @@ -349,12 +350,14 @@ static const struct dev_pm_ops sa1100_rtc_pm_ops = {  };  #endif +#ifdef CONFIG_OF  static struct of_device_id sa1100_rtc_dt_ids[] = {  	{ .compatible = "mrvl,sa1100-rtc", },  	{ .compatible = "mrvl,mmp-rtc", },  	{}  };  MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids); +#endif  static struct platform_driver sa1100_rtc_driver = {  	.probe		= sa1100_rtc_probe, @@ -364,7 +367,7 @@ static struct platform_driver sa1100_rtc_driver = {  #ifdef CONFIG_PM  		.pm	= &sa1100_rtc_pm_ops,  #endif -		.of_match_table = sa1100_rtc_dt_ids, +		.of_match_table = of_match_ptr(sa1100_rtc_dt_ids),  	},  }; diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index d5ec7854a651..f7d90703db5e 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -252,9 +252,9 @@ static int snvs_rtc_probe(struct platform_device *pdev)  		return -ENOMEM;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	data->ioaddr = devm_request_and_ioremap(&pdev->dev, res); -	if (!data->ioaddr) -		return -EADDRNOTAVAIL; +	data->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(data->ioaddr)) +		return PTR_ERR(data->ioaddr);  	data->irq = platform_get_irq(pdev, 0);  	if (data->irq < 0) @@ -338,7 +338,7 @@ static struct platform_driver snvs_rtc_driver = {  		.name	= "snvs_rtc",  		.owner	= THIS_MODULE,  		.pm	= &snvs_rtc_pm_ops, -		.of_match_table = snvs_dt_ids, +		.of_match_table = of_match_ptr(snvs_dt_ids),  	},  	.probe		= snvs_rtc_probe,  	.remove		= snvs_rtc_remove, diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index c2121b5a01f2..a18c3192ed40 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -385,11 +385,9 @@ static int spear_rtc_probe(struct platform_device *pdev)  		return status;  	} -	config->ioaddr = devm_request_and_ioremap(&pdev->dev, res); -	if (!config->ioaddr) { -		dev_err(&pdev->dev, "request-ioremap fail\n"); -		return -ENOMEM; -	} +	config->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(config->ioaddr)) +		return PTR_ERR(config->ioaddr);  	config->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(config->clk)) diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 739ef55694f4..b2a8ed99b2bf 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -26,6 +26,7 @@  #include <linux/rtc.h>  #include <linux/slab.h>  #include <linux/of_device.h> +#include <linux/of.h>  #include <mach/common.h> @@ -280,7 +281,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {  	.driver		= {  		.name	= "stmp3xxx-rtc",  		.owner	= THIS_MODULE, -		.of_match_table = rtc_dt_ids, +		.of_match_table = of_match_ptr(rtc_dt_ids),  	},  }; diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 5b2261052a65..59b5c2dcb58c 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c @@ -3,6 +3,8 @@   * Copyright (C) 2008 David S. Miller <[email protected]>   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/delay.h> @@ -26,10 +28,10 @@ retry:  			udelay(100);  			goto retry;  		} -		printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); +		pr_warn("tod_get() timed out.\n");  		return 0;  	} -	printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); +	pr_warn("tod_get() not supported.\n");  	return 0;  } @@ -53,10 +55,10 @@ retry:  			udelay(100);  			goto retry;  		} -		printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); +		pr_warn("tod_set() timed out.\n");  		return -EAGAIN;  	} -	printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); +	pr_warn("tod_set() not supported.\n");  	return -EOPNOTSUPP;  } diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index c84ea6659f49..7c033756d6b5 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -327,11 +327,9 @@ static int tegra_rtc_probe(struct platform_device *pdev)  		return -EBUSY;  	} -	info->rtc_base = devm_request_and_ioremap(&pdev->dev, res); -	if (!info->rtc_base) { -		dev_err(&pdev->dev, "Unable to request mem region and grab IOs for device.\n"); -		return -EBUSY; -	} +	info->rtc_base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(info->rtc_base)) +		return PTR_ERR(info->rtc_base);  	info->tegra_rtc_irq = platform_get_irq(pdev, 0);  	if (info->tegra_rtc_irq <= 0) diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index 70f61b8e9e6f..aab4e8c93622 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -282,7 +282,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)  		goto fail_rtc_register;  	} -	ret = request_threaded_irq(rtc->irq, NULL, tps6586x_rtc_irq, +	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, +				tps6586x_rtc_irq,  				IRQF_ONESHOT | IRQF_EARLY_RESUME,  				dev_name(&pdev->dev), rtc);  	if (ret < 0) { @@ -311,7 +312,6 @@ static int tps6586x_rtc_remove(struct platform_device *pdev)  	tps6586x_update(tps_dev, RTC_CTRL, 0,  		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);  	rtc_device_unregister(rtc->rtc); -	free_irq(rtc->irq, rtc);  	return 0;  } diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index e5fef141a0e2..8bd8115329b5 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -22,13 +22,13 @@  #include <linux/rtc.h>  #include <linux/bcd.h>  #include <linux/platform_device.h> +#include <linux/pm_runtime.h>  #include <linux/interrupt.h>  #include <linux/mfd/tps65910.h>  struct tps65910_rtc {  	struct rtc_device	*rtc; -	/* To store the list of enabled interrupts */ -	u32 irqstat; +	int irq;  };  /* Total number of RTC registers needed to set time*/ @@ -267,13 +267,14 @@ static int tps65910_rtc_probe(struct platform_device *pdev)  	}  	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, -		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, +		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME,  		dev_name(&pdev->dev), &pdev->dev);  	if (ret < 0) {  		dev_err(&pdev->dev, "IRQ is not free.\n");  		return ret;  	} -	device_init_wakeup(&pdev->dev, 1); +	tps_rtc->irq = irq; +	device_set_wakeup_capable(&pdev->dev, 1);  	tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,  		&tps65910_rtc_ops, THIS_MODULE); @@ -304,49 +305,36 @@ static int tps65910_rtc_remove(struct platform_device *pdev)  }  #ifdef CONFIG_PM_SLEEP -  static int tps65910_rtc_suspend(struct device *dev)  { -	struct tps65910 *tps = dev_get_drvdata(dev->parent); -	u8 alarm = TPS65910_RTC_INTERRUPTS_IT_ALARM; -	int ret; - -	/* Store current list of enabled interrupts*/ -	ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, -		&tps->rtc->irqstat); -	if (ret < 0) -		return ret; +	struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); -	/* Enable RTC ALARM interrupt only */ -	return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, alarm); +	if (device_may_wakeup(dev)) +		enable_irq_wake(tps_rtc->irq); +	return 0;  }  static int tps65910_rtc_resume(struct device *dev)  { -	struct tps65910 *tps = dev_get_drvdata(dev->parent); +	struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); -	/* Restore list of enabled interrupts before suspend */ -	return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, -		tps->rtc->irqstat); +	if (device_may_wakeup(dev)) +		disable_irq_wake(tps_rtc->irq); +	return 0;  } +#endif  static const struct dev_pm_ops tps65910_rtc_pm_ops = { -	.suspend	= tps65910_rtc_suspend, -	.resume		= tps65910_rtc_resume, +	SET_SYSTEM_SLEEP_PM_OPS(tps65910_rtc_suspend, tps65910_rtc_resume)  }; -#define DEV_PM_OPS     (&tps65910_rtc_pm_ops) -#else -#define DEV_PM_OPS     NULL -#endif -  static struct platform_driver tps65910_rtc_driver = {  	.probe		= tps65910_rtc_probe,  	.remove		= tps65910_rtc_remove,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= "tps65910-rtc", -		.pm	= DEV_PM_OPS, +		.pm	= &tps65910_rtc_pm_ops,  	},  }; diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c new file mode 100644 index 000000000000..9aaf8aaebae9 --- /dev/null +++ b/drivers/rtc/rtc-tps80031.c @@ -0,0 +1,349 @@ +/* + * rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver + * + * RTC driver for TI TPS80031/TPS80032 Fully Integrated + * Power Management with Power Path and Battery Charger + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, + * whether express or implied; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include <linux/bcd.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mfd/tps80031.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/rtc.h> +#include <linux/slab.h> + +#define ENABLE_ALARM_INT			0x08 +#define ALARM_INT_STATUS			0x40 + +/** + * Setting bit to 1 in STOP_RTC will run the RTC and + * setting this bit to 0 will freeze RTC. + */ +#define STOP_RTC				0x1 + +/* Power on reset Values of RTC registers */ +#define TPS80031_RTC_POR_YEAR			0 +#define TPS80031_RTC_POR_MONTH			1 +#define TPS80031_RTC_POR_DAY			1 + +/* Numbers of registers for time and alarms */ +#define TPS80031_RTC_TIME_NUM_REGS		7 +#define TPS80031_RTC_ALARM_NUM_REGS		6 + +/** + * PMU RTC have only 2 nibbles to store year information, so using an + * offset of 100 to set the base year as 2000 for our driver. + */ +#define RTC_YEAR_OFFSET 100 + +struct tps80031_rtc { +	struct rtc_device	*rtc; +	int			irq; +}; + +static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	u8 buff[TPS80031_RTC_TIME_NUM_REGS]; +	int ret; + +	ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, +			TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff); +	if (ret < 0) { +		dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret); +		return ret; +	} + +	tm->tm_sec = bcd2bin(buff[0]); +	tm->tm_min = bcd2bin(buff[1]); +	tm->tm_hour = bcd2bin(buff[2]); +	tm->tm_mday = bcd2bin(buff[3]); +	tm->tm_mon = bcd2bin(buff[4]) - 1; +	tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; +	tm->tm_wday = bcd2bin(buff[6]); +	return 0; +} + +static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	u8 buff[7]; +	int ret; + +	buff[0] = bin2bcd(tm->tm_sec); +	buff[1] = bin2bcd(tm->tm_min); +	buff[2] = bin2bcd(tm->tm_hour); +	buff[3] = bin2bcd(tm->tm_mday); +	buff[4] = bin2bcd(tm->tm_mon + 1); +	buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET); +	buff[6] = bin2bcd(tm->tm_wday); + +	/* Stop RTC while updating the RTC time registers */ +	ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, +				TPS80031_RTC_CTRL_REG, STOP_RTC); +	if (ret < 0) { +		dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret); +		return ret; +	} + +	ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, +			TPS80031_SECONDS_REG, +			TPS80031_RTC_TIME_NUM_REGS, buff); +	if (ret < 0) { +		dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret); +		return ret; +	} + +	ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, +				TPS80031_RTC_CTRL_REG, STOP_RTC); +	if (ret < 0) +		dev_err(dev->parent, "Start RTC failed, err = %d\n", ret); +	return ret; +} + +static int tps80031_rtc_alarm_irq_enable(struct device *dev, +					 unsigned int enable) +{ +	int ret; + +	if (enable) +		ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, +				TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); +	else +		ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, +				TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); +	if (ret < 0) { +		dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret); +		return ret; +	} +	return 0; +} + +static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	u8 buff[TPS80031_RTC_ALARM_NUM_REGS]; +	int ret; + +	buff[0] = bin2bcd(alrm->time.tm_sec); +	buff[1] = bin2bcd(alrm->time.tm_min); +	buff[2] = bin2bcd(alrm->time.tm_hour); +	buff[3] = bin2bcd(alrm->time.tm_mday); +	buff[4] = bin2bcd(alrm->time.tm_mon + 1); +	buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET); +	ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, +			TPS80031_ALARM_SECONDS_REG, +			TPS80031_RTC_ALARM_NUM_REGS, buff); +	if (ret < 0) { +		dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret); +		return ret; +	} +	return tps80031_rtc_alarm_irq_enable(dev, alrm->enabled); +} + +static int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	u8 buff[6]; +	int ret; + +	ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, +			TPS80031_ALARM_SECONDS_REG, +			TPS80031_RTC_ALARM_NUM_REGS, buff); +	if (ret < 0) { +		dev_err(dev->parent, +			"reading RTC_ALARM failed, err = %d\n", ret); +		return ret; +	} + +	alrm->time.tm_sec = bcd2bin(buff[0]); +	alrm->time.tm_min = bcd2bin(buff[1]); +	alrm->time.tm_hour = bcd2bin(buff[2]); +	alrm->time.tm_mday = bcd2bin(buff[3]); +	alrm->time.tm_mon = bcd2bin(buff[4]) - 1; +	alrm->time.tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; +	return 0; +} + +static int clear_alarm_int_status(struct device *dev, struct tps80031_rtc *rtc) +{ +	int ret; +	u8 buf; + +	/** +	 * As per datasheet, A dummy read of this  RTC_STATUS_REG register +	 * is necessary before each I2C read in order to update the status +	 * register value. +	 */ +	ret = tps80031_read(dev->parent, TPS80031_SLAVE_ID1, +				TPS80031_RTC_STATUS_REG, &buf); +	if (ret < 0) { +		dev_err(dev, "reading RTC_STATUS failed. err = %d\n", ret); +		return ret; +	} + +	/* clear Alarm status bits.*/ +	ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, +			TPS80031_RTC_STATUS_REG, ALARM_INT_STATUS); +	if (ret < 0) { +		dev_err(dev, "clear Alarm INT failed, err = %d\n", ret); +		return ret; +	} +	return 0; +} + +static irqreturn_t tps80031_rtc_irq(int irq, void *data) +{ +	struct device *dev = data; +	struct tps80031_rtc *rtc = dev_get_drvdata(dev); +	int ret; + +	ret = clear_alarm_int_status(dev, rtc); +	if (ret < 0) +		return ret; + +	rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); +	return IRQ_HANDLED; +} + +static const struct rtc_class_ops tps80031_rtc_ops = { +	.read_time = tps80031_rtc_read_time, +	.set_time = tps80031_rtc_set_time, +	.set_alarm = tps80031_rtc_set_alarm, +	.read_alarm = tps80031_rtc_read_alarm, +	.alarm_irq_enable = tps80031_rtc_alarm_irq_enable, +}; + +static int tps80031_rtc_probe(struct platform_device *pdev) +{ +	struct tps80031_rtc *rtc; +	struct rtc_time tm; +	int ret; + +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); +	if (!rtc) +		return -ENOMEM; + +	rtc->irq = platform_get_irq(pdev, 0); +	platform_set_drvdata(pdev, rtc); + +	/* Start RTC */ +	ret = tps80031_set_bits(pdev->dev.parent, TPS80031_SLAVE_ID1, +			TPS80031_RTC_CTRL_REG, STOP_RTC); +	if (ret < 0) { +		dev_err(&pdev->dev, "failed to start RTC. err = %d\n", ret); +		return ret; +	} + +	/* If RTC have POR values, set time 01:01:2000 */ +	tps80031_rtc_read_time(&pdev->dev, &tm); +	if ((tm.tm_year == RTC_YEAR_OFFSET + TPS80031_RTC_POR_YEAR) && +		(tm.tm_mon == (TPS80031_RTC_POR_MONTH - 1)) && +		(tm.tm_mday == TPS80031_RTC_POR_DAY)) { +		tm.tm_year = 2000; +		tm.tm_mday = 1; +		tm.tm_mon = 1; +		ret = tps80031_rtc_set_time(&pdev->dev, &tm); +		if (ret < 0) { +			dev_err(&pdev->dev, +				"RTC set time failed, err = %d\n", ret); +			return ret; +		} +	} + +	/* Clear alarm intretupt status if it is there */ +	ret = clear_alarm_int_status(&pdev->dev, rtc); +	if (ret < 0) { +		dev_err(&pdev->dev, "Clear alarm int failed, err = %d\n", ret); +		return ret; +	} + +	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, +			       &tps80031_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc->rtc)) { +		ret = PTR_ERR(rtc->rtc); +		dev_err(&pdev->dev, "RTC registration failed, err %d\n", ret); +		return ret; +	} + +	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, +			tps80031_rtc_irq, +			IRQF_ONESHOT | IRQF_EARLY_RESUME, +			dev_name(&pdev->dev), rtc); +	if (ret < 0) { +		dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n", +			 rtc->irq, ret); +		rtc_device_unregister(rtc->rtc); +		return ret; +	} +	device_set_wakeup_capable(&pdev->dev, 1); +	return 0; +} + +static int tps80031_rtc_remove(struct platform_device *pdev) +{ +	struct tps80031_rtc *rtc = platform_get_drvdata(pdev); + +	rtc_device_unregister(rtc->rtc); +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tps80031_rtc_suspend(struct device *dev) +{ +	struct tps80031_rtc *rtc = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		enable_irq_wake(rtc->irq); +	return 0; +} + +static int tps80031_rtc_resume(struct device *dev) +{ +	struct tps80031_rtc *rtc = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		disable_irq_wake(rtc->irq); +	return 0; +}; +#endif + +static const struct dev_pm_ops tps80031_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(tps80031_rtc_suspend, tps80031_rtc_resume) +}; + +static struct platform_driver tps80031_rtc_driver = { +	.driver	= { +		.name	= "tps80031-rtc", +		.owner	= THIS_MODULE, +		.pm	= &tps80031_pm_ops, +	}, +	.probe	= tps80031_rtc_probe, +	.remove	= tps80031_rtc_remove, +}; + +module_platform_driver(tps80031_rtc_driver); + +MODULE_ALIAS("platform:tps80031-rtc"); +MODULE_DESCRIPTION("TI TPS80031/TPS80032 RTC driver"); +MODULE_AUTHOR("Laxman Dewangan <[email protected]>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index ccd4ad370b32..8bc6c80b184c 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -27,6 +27,7 @@  #include <linux/bcd.h>  #include <linux/platform_device.h>  #include <linux/interrupt.h> +#include <linux/of.h>  #include <linux/i2c/twl.h> @@ -588,11 +589,14 @@ static int twl_rtc_resume(struct platform_device *pdev)  #define twl_rtc_resume  NULL  #endif +#ifdef CONFIG_OF  static const struct of_device_id twl_rtc_of_match[] = {  	{.compatible = "ti,twl4030-rtc", },  	{ },  };  MODULE_DEVICE_TABLE(of, twl_rtc_of_match); +#endif +  MODULE_ALIAS("platform:twl_rtc");  static struct platform_driver twl4030rtc_driver = { @@ -604,7 +608,7 @@ static struct platform_driver twl4030rtc_driver = {  	.driver		= {  		.owner		= THIS_MODULE,  		.name		= "twl_rtc", -		.of_match_table = twl_rtc_of_match, +		.of_match_table = of_match_ptr(twl_rtc_of_match),  	},  }; diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 6c3774cf5a24..f91be04b9050 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -352,7 +352,7 @@ static int rtc_probe(struct platform_device *pdev)  	disable_irq(aie_irq);  	disable_irq(pie_irq); -	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n"); +	dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n");  	return 0; diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 00c930f4b6f3..a000bc0a8bff 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -137,7 +137,7 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)  		return -EINVAL;  	} -	writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) +	writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S)  		| (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)  		| (bin2bcd(tm->tm_mday))  		| ((tm->tm_year >= 200) << DATE_CENTURY_S), @@ -231,20 +231,21 @@ static int vt8500_rtc_probe(struct platform_device *pdev)  		return -ENXIO;  	} -	vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, -					     resource_size(vt8500_rtc->res), -					     "vt8500-rtc"); +	vt8500_rtc->res = devm_request_mem_region(&pdev->dev, +					vt8500_rtc->res->start, +					resource_size(vt8500_rtc->res), +					"vt8500-rtc");  	if (vt8500_rtc->res == NULL) {  		dev_err(&pdev->dev, "failed to request I/O memory\n");  		return -EBUSY;  	} -	vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, +	vt8500_rtc->regbase = devm_ioremap(&pdev->dev, vt8500_rtc->res->start,  				      resource_size(vt8500_rtc->res));  	if (!vt8500_rtc->regbase) {  		dev_err(&pdev->dev, "Unable to map RTC I/O memory\n");  		ret = -EBUSY; -		goto err_release; +		goto err_return;  	}  	/* Enable RTC and set it to 24-hour mode */ @@ -257,11 +258,11 @@ static int vt8500_rtc_probe(struct platform_device *pdev)  		ret = PTR_ERR(vt8500_rtc->rtc);  		dev_err(&pdev->dev,  			"Failed to register RTC device -> %d\n", ret); -		goto err_unmap; +		goto err_return;  	} -	ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0, -			  "rtc alarm", vt8500_rtc); +	ret = devm_request_irq(&pdev->dev, 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); @@ -272,11 +273,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev)  err_unreg:  	rtc_device_unregister(vt8500_rtc->rtc); -err_unmap: -	iounmap(vt8500_rtc->regbase); -err_release: -	release_mem_region(vt8500_rtc->res->start, -			   resource_size(vt8500_rtc->res)); +err_return:  	return ret;  } @@ -284,15 +281,10 @@ static int vt8500_rtc_remove(struct platform_device *pdev)  {  	struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); -	free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); -  	rtc_device_unregister(vt8500_rtc->rtc);  	/* Disable alarm matching */  	writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); -	iounmap(vt8500_rtc->regbase); -	release_mem_region(vt8500_rtc->res->start, -			   resource_size(vt8500_rtc->res));  	platform_set_drvdata(pdev, NULL); diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 1b0affbe2659..2f0ac7b30a0c 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -443,9 +443,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev)  		goto err;  	} -	ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, -				   IRQF_TRIGGER_RISING, "RTC alarm", -				   wm831x_rtc); +	ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, +				wm831x_alm_irq, +				IRQF_TRIGGER_RISING, "RTC alarm", +				wm831x_rtc);  	if (ret != 0) {  		dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",  			alm_irq, ret); @@ -462,9 +463,7 @@ err:  static int wm831x_rtc_remove(struct platform_device *pdev)  {  	struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); -	int alm_irq = platform_get_irq_byname(pdev, "ALM"); -	free_irq(alm_irq, wm831x_rtc);  	rtc_device_unregister(wm831x_rtc->rtc);  	return 0; diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c new file mode 100644 index 000000000000..bf3e242ccc5c --- /dev/null +++ b/drivers/rtc/systohc.c @@ -0,0 +1,44 @@ +/* + * 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 published by + * the Free Software Foundation. + * + */ +#include <linux/rtc.h> +#include <linux/time.h> + +/** + * rtc_set_ntp_time - Save NTP synchronized time to the RTC + * @now: Current time of day + * + * Replacement for the NTP platform function update_persistent_clock + * that stores time for later retrieval by rtc_hctosys. + * + * Returns 0 on successful RTC update, -ENODEV if a RTC update is not + * possible at all, and various other -errno for specific temporary failure + * cases. + * + * If temporary failure is indicated the caller should try again 'soon' + */ +int rtc_set_ntp_time(struct timespec now) +{ +	struct rtc_device *rtc; +	struct rtc_time tm; +	int err = -ENODEV; + +	if (now.tv_nsec < (NSEC_PER_SEC >> 1)) +		rtc_time_to_tm(now.tv_sec, &tm); +	else +		rtc_time_to_tm(now.tv_sec + 1, &tm); + +	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); +	if (rtc) { +		/* rtc_hctosys exclusively uses UTC, so we call set_time here, +		 * not set_mmss. */ +		if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss)) +			err = rtc_set_time(rtc, &tm); +		rtc_class_close(rtc); +	} + +	return err; +} |