diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
| commit | bf61c8840efe60fd8f91446860b63338fb424158 (patch) | |
| tree | 7a71832407a4f0d6346db773343f4c3ae2257b19 /drivers/rtc | |
| parent | 5846115b30f3a881e542c8bfde59a699c1c13740 (diff) | |
| parent | 0c6a61657da78098472fd0eb71cc01f2387fa1bb (diff) | |
| download | olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.tar.xz olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.zip  | |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.10 merge window.
Diffstat (limited to 'drivers/rtc')
100 files changed, 4898 insertions, 657 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 19c03ab2bdc..79fbe3832df 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 @@ -269,6 +305,25 @@ config RTC_DRV_X1205  	  This driver can also be built as a module. If so, the module  	  will be called rtc-x1205. +config RTC_DRV_PALMAS +	tristate "TI Palmas RTC driver" +	depends on MFD_PALMAS +	help +	  If you say yes here you get support for the RTC of TI PALMA series PMIC +	  chips. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-palma. + +config RTC_DRV_PCF8523 +	tristate "NXP PCF8523" +	help +	  If you say yes here you get support for the NXP PCF8523 RTC +	  chips. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-pcf8523. +  config RTC_DRV_PCF8563  	tristate "Philips PCF8563/Epson RTC8564"  	help @@ -343,6 +398,14 @@ config RTC_DRV_TWL4030  	  This driver can also be built as a module. If so, the module  	  will be called rtc-twl. +config RTC_DRV_TPS6586X +	tristate "TI TPS6586X RTC driver" +	depends on MFD_TPS6586X +	help +	  TI Power Managment IC TPS6586X supports RTC functionality +	  along with alarm. This driver supports the RTC driver for +	  the TPS6586X RTC module. +  config RTC_DRV_TPS65910  	tristate "TI TPS65910 RTC driver"  	depends on RTC_CLASS && MFD_TPS65910 @@ -353,6 +416,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 @@ -510,6 +581,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" @@ -600,6 +679,16 @@ config RTC_DRV_DA9052  	  Say y here to support the RTC driver for Dialog Semiconductor  	  DA9052-BC and DA9053-AA/Bx PMICs. +config RTC_DRV_DA9055 +	tristate "Dialog Semiconductor DA9055 RTC" +	depends on MFD_DA9055 +	help +	  If you say yes here you will get support for the +	  RTC of the Dialog DA9055 PMIC. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-da9055 +  config RTC_DRV_EFI  	tristate "EFI RTC"  	depends on IA64 @@ -768,7 +857,7 @@ config RTC_DRV_DAVINCI  config RTC_DRV_IMXDI  	tristate "Freescale IMX DryIce Real Time Clock" -	depends on SOC_IMX25 +	depends on ARCH_MXC  	help  	   Support for Freescale IMX DryIce RTC @@ -777,11 +866,13 @@ config RTC_DRV_IMXDI  config RTC_DRV_OMAP  	tristate "TI OMAP1" -	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX +	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX  	help -	  Say "yes" here to support the real time clock on TI OMAP1 and -	  DA8xx/OMAP-L13x chips.  This driver can also be built as a -	  module called rtc-omap. +	  Say "yes" here to support the on chip real time clock +	  present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x. + +	  This driver can also be built as a module, if so, module +	  will be called rtc-omap.  config HAVE_S3C_RTC  	bool @@ -994,7 +1085,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 @@ -1144,4 +1235,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 56297f0fd38..c33f86f1a69 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 @@ -29,6 +30,7 @@ obj-$(CONFIG_RTC_DRV_BQ4802)	+= rtc-bq4802.o  obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o  obj-$(CONFIG_RTC_DRV_COH901331)	+= rtc-coh901331.o  obj-$(CONFIG_RTC_DRV_DA9052)	+= rtc-da9052.o +obj-$(CONFIG_RTC_DRV_DA9055)	+= rtc-da9055.o  obj-$(CONFIG_RTC_DRV_DAVINCI)	+= rtc-davinci.o  obj-$(CONFIG_RTC_DRV_DM355EVM)	+= rtc-dm355evm.o  obj-$(CONFIG_RTC_DRV_VRTC)	+= rtc-mrst.o @@ -51,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 @@ -68,14 +72,18 @@ 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  obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o  obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o +obj-$(CONFIG_RTC_DRV_PALMAS)	+= rtc-palmas.o  obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o +obj-$(CONFIG_RTC_DRV_PCF8523)	+= rtc-pcf8523.o  obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o  obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o  obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o @@ -93,6 +101,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 @@ -109,7 +118,9 @@ obj-$(CONFIG_RTC_DRV_TEGRA)	+= rtc-tegra.o  obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o  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 f8a0aab218c..9b742d3ffb9 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; @@ -244,7 +253,6 @@ void rtc_device_unregister(struct rtc_device *rtc)  		rtc_proc_del_device(rtc);  		device_unregister(&rtc->dev);  		rtc->ops = NULL; -		ida_simple_remove(&rtc_ida, rtc->id);  		mutex_unlock(&rtc->ops_lock);  		put_device(&rtc->dev);  	} @@ -255,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 9592b936b71..42bd57da239 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-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 6367984e056..63b17ebe90e 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -248,7 +248,7 @@ static int pm80x_rtc_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); -static int __devinit pm80x_rtc_probe(struct platform_device *pdev) +static int pm80x_rtc_probe(struct platform_device *pdev)  {  	struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);  	struct pm80x_platform_data *pm80x_pdata; @@ -342,7 +342,7 @@ out:  	return ret;  } -static int __devexit pm80x_rtc_remove(struct platform_device *pdev) +static int pm80x_rtc_remove(struct platform_device *pdev)  {  	struct pm80x_rtc_info *info = platform_get_drvdata(pdev);  	platform_set_drvdata(pdev, NULL); @@ -358,7 +358,7 @@ static struct platform_driver pm80x_rtc_driver = {  		   .pm = &pm80x_rtc_pm_ops,  		   },  	.probe = pm80x_rtc_probe, -	.remove = __devexit_p(pm80x_rtc_remove), +	.remove = pm80x_rtc_remove,  };  module_platform_driver(pm80x_rtc_driver); diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index de9e854b326..f663746f460 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -286,8 +286,8 @@ out:  #endif  #ifdef CONFIG_OF -static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev, -					struct pm860x_rtc_info *info) +static int pm860x_rtc_dt_init(struct platform_device *pdev, +			      struct pm860x_rtc_info *info)  {  	struct device_node *np = pdev->dev.parent->of_node;  	int ret; @@ -307,7 +307,7 @@ static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev,  #define pm860x_rtc_dt_init(x, y)	(-1)  #endif -static int __devinit pm860x_rtc_probe(struct platform_device *pdev) +static int pm860x_rtc_probe(struct platform_device *pdev)  {  	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);  	struct pm860x_rtc_pdata *pdata = NULL; @@ -412,7 +412,7 @@ out:  	return ret;  } -static int __devexit pm860x_rtc_remove(struct platform_device *pdev) +static int pm860x_rtc_remove(struct platform_device *pdev)  {  	struct pm860x_rtc_info *info = platform_get_drvdata(pdev); @@ -459,7 +459,7 @@ static struct platform_driver pm860x_rtc_driver = {  		.pm	= &pm860x_rtc_pm_ops,  	},  	.probe		= pm860x_rtc_probe, -	.remove		= __devexit_p(pm860x_rtc_remove), +	.remove		= pm860x_rtc_remove,  };  module_platform_driver(pm860x_rtc_driver); diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 2e5970fe9ee..57cde2b061e 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -389,7 +389,7 @@ static const struct rtc_class_ops ab8500_rtc_ops = {  	.alarm_irq_enable	= ab8500_rtc_irq_enable,  }; -static int __devinit ab8500_rtc_probe(struct platform_device *pdev) +static int ab8500_rtc_probe(struct platform_device *pdev)  {  	int err;  	struct rtc_device *rtc; @@ -448,7 +448,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit ab8500_rtc_remove(struct platform_device *pdev) +static int ab8500_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtc = platform_get_drvdata(pdev);  	int irq = platform_get_irq_byname(pdev, "ALARM"); @@ -468,7 +468,7 @@ static struct platform_driver ab8500_rtc_driver = {  		.owner = THIS_MODULE,  	},  	.probe	= ab8500_rtc_probe, -	.remove = __devexit_p(ab8500_rtc_remove), +	.remove = ab8500_rtc_remove,  };  module_platform_driver(ab8500_rtc_driver); diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index fca9790c7de..434ebc3a99d 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -31,7 +31,7 @@  #include <asm/uaccess.h> -#include <mach/at91_rtc.h> +#include "rtc-at91rm9200.h"  #define at91_rtc_read(field) \  	__raw_readl(at91_rtc_regs + field) @@ -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-at91rm9200.h b/drivers/rtc/rtc-at91rm9200.h new file mode 100644 index 00000000000..da1945e5f71 --- /dev/null +++ b/drivers/rtc/rtc-at91rm9200.h @@ -0,0 +1,75 @@ +/* + * arch/arm/mach-at91/include/mach/at91_rtc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Real Time Clock (RTC) - System peripheral registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_RTC_H +#define AT91_RTC_H + +#define	AT91_RTC_CR		0x00			/* Control Register */ +#define		AT91_RTC_UPDTIM		(1 <<  0)		/* Update Request Time Register */ +#define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */ +#define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */ +#define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8) +#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8) +#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8) +#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8) +#define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */ +#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16) +#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16) +#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16) + +#define	AT91_RTC_MR		0x04			/* Mode Register */ +#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */ + +#define	AT91_RTC_TIMR		0x08			/* Time Register */ +#define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */ +#define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */ +#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */ +#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */ + +#define	AT91_RTC_CALR		0x0c			/* Calendar Register */ +#define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */ +#define		AT91_RTC_YEAR		(0xff <<  8)		/* Current Year */ +#define		AT91_RTC_MONTH		(0x1f << 16)		/* Current Month */ +#define		AT91_RTC_DAY		(7    << 21)		/* Current Day */ +#define		AT91_RTC_DATE		(0x3f << 24)		/* Current Date */ + +#define	AT91_RTC_TIMALR		0x10			/* Time Alarm Register */ +#define		AT91_RTC_SECEN		(1 <<  7)		/* Second Alarm Enable */ +#define		AT91_RTC_MINEN		(1 << 15)		/* Minute Alarm Enable */ +#define		AT91_RTC_HOUREN		(1 << 23)		/* Hour Alarm Enable */ + +#define	AT91_RTC_CALALR		0x14			/* Calendar Alarm Register */ +#define		AT91_RTC_MTHEN		(1 << 23)		/* Month Alarm Enable */ +#define		AT91_RTC_DATEEN		(1 << 31)		/* Date Alarm Enable */ + +#define	AT91_RTC_SR		0x18			/* Status Register */ +#define		AT91_RTC_ACKUPD		(1 <<  0)		/* Acknowledge for Update */ +#define		AT91_RTC_ALARM		(1 <<  1)		/* Alarm Flag */ +#define		AT91_RTC_SECEV		(1 <<  2)		/* Second Event */ +#define		AT91_RTC_TIMEV		(1 <<  3)		/* Time Event */ +#define		AT91_RTC_CALEV		(1 <<  4)		/* Calendar Event */ + +#define	AT91_RTC_SCCR		0x1c			/* Status Clear Command Register */ +#define	AT91_RTC_IER		0x20			/* Interrupt Enable Register */ +#define	AT91_RTC_IDR		0x24			/* Interrupt Disable Register */ +#define	AT91_RTC_IMR		0x28			/* Interrupt Mask Register */ + +#define	AT91_RTC_VER		0x2c			/* Valid Entry Register */ +#define		AT91_RTC_NVTIM		(1 <<  0)		/* Non valid Time */ +#define		AT91_RTC_NVCAL		(1 <<  1)		/* Non valid Calendar */ +#define		AT91_RTC_NVTIMALR	(1 <<  2)		/* Non valid Time Alarm */ +#define		AT91_RTC_NVCALALR	(1 <<  3)		/* Non valid Calendar Alarm */ + +#endif diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 2dfe7a2fb99..39cfd2ee004 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -19,8 +19,8 @@  #include <linux/interrupt.h>  #include <linux/ioctl.h>  #include <linux/slab.h> +#include <linux/platform_data/atmel.h> -#include <mach/board.h>  #include <mach/at91_rtt.h>  #include <mach/cpu.h> @@ -289,7 +289,7 @@ static const struct rtc_class_ops at91_rtc_ops = {  /*   * Initialize and install RTC driver   */ -static int __devinit at91_rtc_probe(struct platform_device *pdev) +static int at91_rtc_probe(struct platform_device *pdev)  {  	struct resource	*r, *r_gpbr;  	struct sam9_rtc	*rtc; @@ -387,7 +387,7 @@ fail:  /*   * Disable and remove the RTC driver   */ -static int __devexit at91_rtc_remove(struct platform_device *pdev) +static int at91_rtc_remove(struct platform_device *pdev)  {  	struct sam9_rtc	*rtc = platform_get_drvdata(pdev);  	u32		mr = rtt_readl(rtc, MR); @@ -463,7 +463,7 @@ static int at91_rtc_resume(struct platform_device *pdev)  static struct platform_driver at91_rtc_driver = {  	.probe		= at91_rtc_probe, -	.remove		= __devexit_p(at91_rtc_remove), +	.remove		= at91_rtc_remove,  	.shutdown	= at91_rtc_shutdown,  	.suspend	= at91_rtc_suspend,  	.resume		= at91_rtc_resume, diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index 979ed0406ce..b309da4ec74 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c @@ -62,7 +62,7 @@ static struct rtc_class_ops au1xtoy_rtc_ops = {  	.set_time	= au1xtoy_rtc_set_time,  }; -static int __devinit au1xtoy_rtc_probe(struct platform_device *pdev) +static int au1xtoy_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtcdev;  	unsigned long t; @@ -116,7 +116,7 @@ out_err:  	return ret;  } -static int __devexit au1xtoy_rtc_remove(struct platform_device *pdev) +static int au1xtoy_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtcdev = platform_get_drvdata(pdev); @@ -131,7 +131,7 @@ static struct platform_driver au1xrtc_driver = {  		.name	= "rtc-au1xxx",  		.owner	= THIS_MODULE,  	}, -	.remove		= __devexit_p(au1xtoy_rtc_remove), +	.remove		= au1xtoy_rtc_remove,  };  static int __init au1xtoy_rtc_init(void) diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index abfc1a0c07d..4ec614b0954 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -342,7 +342,7 @@ static struct rtc_class_ops bfin_rtc_ops = {  	.alarm_irq_enable = bfin_rtc_alarm_irq_enable,  }; -static int __devinit bfin_rtc_probe(struct platform_device *pdev) +static int bfin_rtc_probe(struct platform_device *pdev)  {  	struct bfin_rtc *rtc;  	struct device *dev = &pdev->dev; @@ -388,7 +388,7 @@ err:  	return ret;  } -static int __devexit bfin_rtc_remove(struct platform_device *pdev) +static int bfin_rtc_remove(struct platform_device *pdev)  {  	struct bfin_rtc *rtc = platform_get_drvdata(pdev);  	struct device *dev = &pdev->dev; @@ -451,7 +451,7 @@ static struct platform_driver bfin_rtc_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= bfin_rtc_probe, -	.remove		= __devexit_p(bfin_rtc_remove), +	.remove		= bfin_rtc_remove,  	.suspend	= bfin_rtc_suspend,  	.resume		= bfin_rtc_resume,  }; diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index f090159dce4..036cb89f818 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -163,7 +163,7 @@ static int bq32k_probe(struct i2c_client *client,  	return 0;  } -static int __devexit bq32k_remove(struct i2c_client *client) +static int bq32k_remove(struct i2c_client *client)  {  	struct rtc_device *rtc = i2c_get_clientdata(client); @@ -183,7 +183,7 @@ static struct i2c_driver bq32k_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= bq32k_probe, -	.remove		= __devexit_p(bq32k_remove), +	.remove		= bq32k_remove,  	.id_table	= bq32k_id,  }; diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index bf612ef2294..693be71b5b1 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c @@ -140,7 +140,7 @@ static const struct rtc_class_ops bq4802_ops = {  	.set_time	= bq4802_set_time,  }; -static int __devinit bq4802_probe(struct platform_device *pdev) +static int bq4802_probe(struct platform_device *pdev)  {  	struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL);  	int err = -ENOMEM; @@ -191,7 +191,7 @@ out_free:  	goto out;  } -static int __devexit bq4802_remove(struct platform_device *pdev) +static int bq4802_remove(struct platform_device *pdev)  {  	struct bq4802 *p = platform_get_drvdata(pdev); @@ -215,7 +215,7 @@ static struct platform_driver bq4802_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= bq4802_probe, -	.remove		= __devexit_p(bq4802_remove), +	.remove		= bq4802_remove,  };  module_platform_driver(bq4802_driver); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 4267789ca99..af97c94e8a3 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;  } @@ -947,8 +943,7 @@ static void rtc_wake_off(struct device *dev)   */  static struct cmos_rtc_board_info acpi_rtc_info; -static void __devinit -cmos_wake_setup(struct device *dev) +static void cmos_wake_setup(struct device *dev)  {  	if (acpi_disabled)  		return; @@ -980,8 +975,7 @@ cmos_wake_setup(struct device *dev)  #else -static void __devinit -cmos_wake_setup(struct device *dev) +static void cmos_wake_setup(struct device *dev)  {  } @@ -991,8 +985,7 @@ cmos_wake_setup(struct device *dev)  #include <linux/pnp.h> -static int __devinit -cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) +static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)  {  	cmos_wake_setup(&pnp->dev); @@ -1101,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  /*----------------------------------------------------------------*/ @@ -1143,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 c8115b83e5a..2d28ec1aa1c 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 78070255bd3..0dde688ca09 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -228,7 +228,7 @@ static const struct rtc_class_ops da9052_rtc_ops = {  	.alarm_irq_enable = da9052_rtc_alarm_irq_enable,  }; -static int __devinit da9052_rtc_probe(struct platform_device *pdev) +static int da9052_rtc_probe(struct platform_device *pdev)  {  	struct da9052_rtc *rtc;  	int ret; @@ -240,9 +240,10 @@ static int __devinit 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,24 +251,17 @@ static int __devinit 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 __devexit da9052_rtc_remove(struct platform_device *pdev) +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; @@ -275,7 +269,7 @@ static int __devexit da9052_rtc_remove(struct platform_device *pdev)  static struct platform_driver da9052_rtc_driver = {  	.probe	= da9052_rtc_probe, -	.remove	= __devexit_p(da9052_rtc_remove), +	.remove	= da9052_rtc_remove,  	.driver = {  		.name	= "da9052-rtc",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c new file mode 100644 index 00000000000..8f0dcfedb83 --- /dev/null +++ b/drivers/rtc/rtc-da9055.c @@ -0,0 +1,413 @@ +/* + * Real time clock driver for DA9055 + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: Dajun Dajun Chen <dajun.chen@diasemi.com> + * + * 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/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + +#include <linux/mfd/da9055/core.h> +#include <linux/mfd/da9055/reg.h> +#include <linux/mfd/da9055/pdata.h> + +struct da9055_rtc { +	struct rtc_device *rtc; +	struct da9055 *da9055; +	int alarm_enable; +}; + +static int da9055_rtc_enable_alarm(struct da9055_rtc *rtc, bool enable) +{ +	int ret; +	if (enable) { +		ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, +					DA9055_RTC_ALM_EN, +					DA9055_RTC_ALM_EN); +		if (ret != 0) +			dev_err(rtc->da9055->dev, "Failed to enable ALM: %d\n", +				ret); +		rtc->alarm_enable = 1; +	} else { +		ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, +					DA9055_RTC_ALM_EN, 0); +		if (ret != 0) +			dev_err(rtc->da9055->dev, +				"Failed to disable ALM: %d\n", ret); +		rtc->alarm_enable = 0; +	} +	return ret; +} + +static irqreturn_t da9055_rtc_alm_irq(int irq, void *data) +{ +	struct da9055_rtc *rtc = data; + +	da9055_rtc_enable_alarm(rtc, 0); +	rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); + +	return IRQ_HANDLED; +} + +static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) +{ +	int ret; +	uint8_t v[5]; + +	ret = da9055_group_read(da9055, DA9055_REG_ALARM_MI, 5, v); +	if (ret != 0) { +		dev_err(da9055->dev, "Failed to group read ALM: %d\n", ret); +		return ret; +	} + +	rtc_tm->tm_year = (v[4] & DA9055_RTC_ALM_YEAR) + 100; +	rtc_tm->tm_mon  = (v[3] & DA9055_RTC_ALM_MONTH) - 1; +	rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY; +	rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR; +	rtc_tm->tm_min  = v[0] & DA9055_RTC_ALM_MIN; + +	return rtc_valid_tm(rtc_tm); +} + +static int da9055_set_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) +{ +	int ret; +	uint8_t v[2]; + +	rtc_tm->tm_year -= 100; +	rtc_tm->tm_mon += 1; + +	ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MI, +				DA9055_RTC_ALM_MIN, rtc_tm->tm_min); +	if (ret != 0) { +		dev_err(da9055->dev, "Failed to write ALRM MIN: %d\n", ret); +		return ret; +	} + +	v[0] = rtc_tm->tm_hour; +	v[1] = rtc_tm->tm_mday; + +	ret = da9055_group_write(da9055, DA9055_REG_ALARM_H, 2, v); +	if (ret < 0) +		return ret; + +	ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, +				DA9055_RTC_ALM_MONTH, rtc_tm->tm_mon); +	if (ret < 0) +		dev_err(da9055->dev, "Failed to write ALM Month:%d\n", ret); + +	ret = da9055_reg_update(da9055, DA9055_REG_ALARM_Y, +				DA9055_RTC_ALM_YEAR, rtc_tm->tm_year); +	if (ret < 0) +		dev_err(da9055->dev, "Failed to write ALM Year:%d\n", ret); + +	return ret; +} + +static int da9055_rtc_get_alarm_status(struct da9055 *da9055) +{ +	int ret; + +	ret = da9055_reg_read(da9055, DA9055_REG_ALARM_Y); +	if (ret < 0) { +		dev_err(da9055->dev, "Failed to read ALM: %d\n", ret); +		return ret; +	} +	ret &= DA9055_RTC_ALM_EN; +	return (ret > 0) ? 1 : 0; +} + +static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) +{ +	struct da9055_rtc *rtc = dev_get_drvdata(dev); +	uint8_t v[6]; +	int ret; + +	ret = da9055_reg_read(rtc->da9055, DA9055_REG_COUNT_S); +	if (ret < 0) +		return ret; + +	/* +	 * Registers are only valid when RTC_READ +	 * status bit is asserted +	 */ +	if (!(ret & DA9055_RTC_READ)) +		return -EBUSY; + +	ret = da9055_group_read(rtc->da9055, DA9055_REG_COUNT_S, 6, v); +	if (ret < 0) { +		dev_err(rtc->da9055->dev, "Failed to read RTC time : %d\n", +			ret); +		return ret; +	} + +	rtc_tm->tm_year = (v[5] & DA9055_RTC_YEAR) + 100; +	rtc_tm->tm_mon  = (v[4] & DA9055_RTC_MONTH) - 1; +	rtc_tm->tm_mday = v[3] & DA9055_RTC_DAY; +	rtc_tm->tm_hour = v[2] & DA9055_RTC_HOUR; +	rtc_tm->tm_min  = v[1] & DA9055_RTC_MIN; +	rtc_tm->tm_sec  = v[0] & DA9055_RTC_SEC; + +	return rtc_valid_tm(rtc_tm); +} + +static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct da9055_rtc *rtc; +	uint8_t v[6]; + +	rtc = dev_get_drvdata(dev); + +	v[0] = tm->tm_sec; +	v[1] = tm->tm_min; +	v[2] = tm->tm_hour; +	v[3] = tm->tm_mday; +	v[4] = tm->tm_mon + 1; +	v[5] = tm->tm_year - 100; + +	return da9055_group_write(rtc->da9055, DA9055_REG_COUNT_S, 6, v); +} + +static int da9055_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	int ret; +	struct rtc_time *tm = &alrm->time; +	struct da9055_rtc *rtc = dev_get_drvdata(dev); + +	ret = da9055_read_alarm(rtc->da9055, tm); + +	if (ret) +		return ret; + +	alrm->enabled = da9055_rtc_get_alarm_status(rtc->da9055); + +	return 0; +} + +static int da9055_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	int ret; +	struct rtc_time *tm = &alrm->time; +	struct da9055_rtc *rtc = dev_get_drvdata(dev); + +	ret = da9055_rtc_enable_alarm(rtc, 0); +	if (ret < 0) +		return ret; + +	ret = da9055_set_alarm(rtc->da9055, tm); +	if (ret) +		return ret; + +	ret = da9055_rtc_enable_alarm(rtc, 1); + +	return ret; +} + +static int da9055_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ +	struct da9055_rtc *rtc = dev_get_drvdata(dev); + +	return da9055_rtc_enable_alarm(rtc, enabled); +} + +static const struct rtc_class_ops da9055_rtc_ops = { +	.read_time	= da9055_rtc_read_time, +	.set_time	= da9055_rtc_set_time, +	.read_alarm	= da9055_rtc_read_alarm, +	.set_alarm	= da9055_rtc_set_alarm, +	.alarm_irq_enable = da9055_rtc_alarm_irq_enable, +}; + +static int da9055_rtc_device_init(struct da9055 *da9055, +					struct da9055_pdata *pdata) +{ +	int ret; + +	/* Enable RTC and the internal Crystal */ +	ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, +				DA9055_RTC_EN, DA9055_RTC_EN); +	if (ret < 0) +		return ret; +	ret = da9055_reg_update(da9055, DA9055_REG_EN_32K, +				DA9055_CRYSTAL_EN, DA9055_CRYSTAL_EN); +	if (ret < 0) +		return ret; + +	/* Enable RTC in Power Down mode */ +	ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, +				DA9055_RTC_MODE_PD, DA9055_RTC_MODE_PD); +	if (ret < 0) +		return ret; + +	/* Enable RTC in Reset mode */ +	if (pdata && pdata->reset_enable) { +		ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, +					DA9055_RTC_MODE_SD, +					DA9055_RTC_MODE_SD << +					DA9055_RTC_MODE_SD_SHIFT); +		if (ret < 0) +			return ret; +	} + +	/* Disable the RTC TICK ALM */ +	ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, +				DA9055_RTC_TICK_WAKE_MASK, 0); +	if (ret < 0) +		return ret; + +	return 0; +} + +static int da9055_rtc_probe(struct platform_device *pdev) +{ +	struct da9055_rtc *rtc; +	struct da9055_pdata *pdata = NULL; +	int ret, alm_irq; + +	rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL); +	if (!rtc) +		return -ENOMEM; + +	rtc->da9055 = dev_get_drvdata(pdev->dev.parent); +	pdata = rtc->da9055->dev->platform_data; +	platform_set_drvdata(pdev, rtc); + +	ret = da9055_rtc_device_init(rtc->da9055, pdata); +	if (ret < 0) +		goto err_rtc; + +	ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y); +	if (ret < 0) +		goto err_rtc; + +	if (ret & DA9055_RTC_ALM_EN) +		rtc->alarm_enable = 1; + +	device_init_wakeup(&pdev->dev, 1); + +	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, +					&da9055_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc->rtc)) { +		ret = PTR_ERR(rtc->rtc); +		goto err_rtc; +	} + +	alm_irq = platform_get_irq_byname(pdev, "ALM"); +	alm_irq = regmap_irq_get_virq(rtc->da9055->irq_data, alm_irq); +	ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, +					da9055_rtc_alm_irq, +					IRQF_TRIGGER_HIGH | IRQF_ONESHOT, +					"ALM", rtc); +	if (ret != 0) +		dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret); + +err_rtc: +	return ret; + +} + +static int da9055_rtc_remove(struct platform_device *pdev) +{ +	struct da9055_rtc *rtc = pdev->dev.platform_data; + +	rtc_device_unregister(rtc->rtc); +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +#ifdef CONFIG_PM +/* Turn off the alarm if it should not be a wake source. */ +static int da9055_rtc_suspend(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); +	int ret; + +	if (!device_may_wakeup(&pdev->dev)) { +		/* Disable the ALM IRQ */ +		ret = da9055_rtc_enable_alarm(rtc, 0); +		if (ret < 0) +			dev_err(&pdev->dev, "Failed to disable RTC ALM\n"); +	} + +	return 0; +} + +/* Enable the alarm if it should be enabled (in case it was disabled to + * prevent use as a wake source). + */ +static int da9055_rtc_resume(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); +	int ret; + +	if (!device_may_wakeup(&pdev->dev)) { +		if (rtc->alarm_enable) { +			ret = da9055_rtc_enable_alarm(rtc, 1); +			if (ret < 0) +				dev_err(&pdev->dev, +					"Failed to restart RTC ALM\n"); +		} +	} + +	return 0; +} + +/* Unconditionally disable the alarm */ +static int da9055_rtc_freeze(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); +	int ret; + +	ret = da9055_rtc_enable_alarm(rtc, 0); +	if (ret < 0) +		dev_err(&pdev->dev, "Failed to freeze RTC ALMs\n"); + +	return 0; + +} +#else +#define da9055_rtc_suspend NULL +#define da9055_rtc_resume NULL +#define da9055_rtc_freeze NULL +#endif + +static const struct dev_pm_ops da9055_rtc_pm_ops = { +	.suspend = da9055_rtc_suspend, +	.resume = da9055_rtc_resume, + +	.freeze = da9055_rtc_freeze, +	.thaw = da9055_rtc_resume, +	.restore = da9055_rtc_resume, + +	.poweroff = da9055_rtc_suspend, +}; + +static struct platform_driver da9055_rtc_driver = { +	.probe  = da9055_rtc_probe, +	.remove = da9055_rtc_remove, +	.driver = { +		.name   = "da9055-rtc", +		.owner  = THIS_MODULE, +		.pm = &da9055_rtc_pm_ops, +	}, +}; + +module_platform_driver(da9055_rtc_driver); + +MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); +MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9055-rtc"); diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 14c2109dbaa..56b73089bb2 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -485,7 +485,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	struct resource *res, *mem;  	int ret = 0; -	davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); +	davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL);  	if (!davinci_rtc) {  		dev_dbg(dev, "could not allocate memory for private data\n");  		return -ENOMEM; @@ -494,34 +494,31 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	davinci_rtc->irq = platform_get_irq(pdev, 0);  	if (davinci_rtc->irq < 0) {  		dev_err(dev, "no RTC irq\n"); -		ret = davinci_rtc->irq; -		goto fail1; +		return davinci_rtc->irq;  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(dev, "no mem resource\n"); -		ret = -EINVAL; -		goto fail1; +		return -EINVAL;  	}  	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); -		ret = -EBUSY; -		goto fail1; +		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,9 +526,10 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,  				    &davinci_rtc_ops, THIS_MODULE);  	if (IS_ERR(davinci_rtc->rtc)) { -		dev_err(dev, "unable to register RTC device, err %ld\n", -				PTR_ERR(davinci_rtc->rtc)); -		goto fail3; +		ret = PTR_ERR(davinci_rtc->rtc); +		dev_err(dev, "unable to register RTC device, err %d\n", +				ret); +		goto fail1;  	}  	rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); @@ -541,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 */ @@ -559,20 +557,14 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  	return 0; -fail4: -	rtc_device_unregister(davinci_rtc->rtc); -fail3: -	platform_set_drvdata(pdev, NULL); -	iounmap(davinci_rtc->base);  fail2: -	release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); +	rtc_device_unregister(davinci_rtc->rtc);  fail1: -	kfree(davinci_rtc); - +	platform_set_drvdata(pdev, NULL);  	return ret;  } -static int __devexit davinci_rtc_remove(struct platform_device *pdev) +static int davinci_rtc_remove(struct platform_device *pdev)  {  	struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); @@ -580,23 +572,16 @@ static int __devexit 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); -	kfree(davinci_rtc); -  	return 0;  }  static struct platform_driver davinci_rtc_driver = {  	.probe		= davinci_rtc_probe, -	.remove		= __devexit_p(davinci_rtc_remove), +	.remove		= davinci_rtc_remove,  	.driver		= {  		.name = "rtc_davinci",  		.owner = THIS_MODULE, diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index cace6d3aed9..d0493936925 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> @@ -379,25 +381,6 @@ static long rtc_dev_ioctl(struct file *file,  		err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);  		break; -#if 0 -	case RTC_EPOCH_SET: -#ifndef rtc_epoch -		/* -		 * There were no RTC clocks before 1900. -		 */ -		if (arg < 1900) { -			err = -EINVAL; -			break; -		} -		rtc_epoch = arg; -		err = 0; -#endif -		break; - -	case RTC_EPOCH_READ: -		err = put_user(rtc_epoch, (unsigned long __user *)uarg); -		break; -#endif  	case RTC_WKALM_SET:  		mutex_unlock(&rtc->ops_lock);  		if (copy_from_user(&alarm, uarg, sizeof(alarm))) @@ -481,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;  	} @@ -499,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);  } @@ -518,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-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index d4457afcba8..b2ed2c94b08 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c @@ -123,7 +123,7 @@ static struct rtc_class_ops dm355evm_rtc_ops = {  /*----------------------------------------------------------------------*/ -static int __devinit dm355evm_rtc_probe(struct platform_device *pdev) +static int dm355evm_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc; @@ -139,7 +139,7 @@ static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit dm355evm_rtc_remove(struct platform_device *pdev) +static int dm355evm_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -154,7 +154,7 @@ static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)   */  static struct platform_driver rtc_dm355evm_driver = {  	.probe		= dm355evm_rtc_probe, -	.remove		= __devexit_p(dm355evm_rtc_remove), +	.remove		= dm355evm_rtc_remove,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= "rtc-dm355evm", diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 990c3ff489b..d989412a348 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -329,7 +329,7 @@ static const struct rtc_class_ops ds1286_ops = {  	.alarm_irq_enable = ds1286_alarm_irq_enable,  }; -static int __devinit ds1286_probe(struct platform_device *pdev) +static int ds1286_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct resource *res; @@ -376,7 +376,7 @@ out:  	return ret;  } -static int __devexit ds1286_remove(struct platform_device *pdev) +static int ds1286_remove(struct platform_device *pdev)  {  	struct ds1286_priv *priv = platform_get_drvdata(pdev); @@ -393,7 +393,7 @@ static struct platform_driver ds1286_platform_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= ds1286_probe, -	.remove		= __devexit_p(ds1286_remove), +	.remove		= ds1286_remove,  };  module_platform_driver(ds1286_platform_driver); diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index f0d63892264..fdbcdb289d6 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -234,7 +234,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit ds1302_rtc_remove(struct platform_device *pdev) +static int ds1302_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -249,7 +249,7 @@ static struct platform_driver ds1302_platform_driver = {  		.name	= DRV_NAME,  		.owner	= THIS_MODULE,  	}, -	.remove		= __devexit_p(ds1302_rtc_remove), +	.remove		= ds1302_rtc_remove,  };  static int __init ds1302_rtc_init(void) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 686a865913e..b05a6dc9640 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -601,7 +601,7 @@ static struct bin_attribute nvram = {   * Interface to SPI stack   */ -static int __devinit ds1305_probe(struct spi_device *spi) +static int ds1305_probe(struct spi_device *spi)  {  	struct ds1305			*ds1305;  	int				status; @@ -635,9 +635,7 @@ static int __devinit 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 __devinit 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 */ @@ -787,7 +783,7 @@ fail0:  	return status;  } -static int __devexit ds1305_remove(struct spi_device *spi) +static int ds1305_remove(struct spi_device *spi)  {  	struct ds1305 *ds1305 = spi_get_drvdata(spi); @@ -810,7 +806,7 @@ static struct spi_driver ds1305_driver = {  	.driver.name	= "rtc-ds1305",  	.driver.owner	= THIS_MODULE,  	.probe		= ds1305_probe, -	.remove		= __devexit_p(ds1305_remove), +	.remove		= ds1305_remove,  	/* REVISIT add suspend/resume */  }; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 836710ce750..970a236b147 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); @@ -617,8 +610,8 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,  /*----------------------------------------------------------------------*/ -static int __devinit ds1307_probe(struct i2c_client *client, -				  const struct i2c_device_id *id) +static int ds1307_probe(struct i2c_client *client, +			const struct i2c_device_id *id)  {  	struct ds1307		*ds1307;  	int			err = -ENODEV; @@ -938,7 +931,7 @@ exit_free:  	return err;  } -static int __devexit ds1307_remove(struct i2c_client *client) +static int ds1307_remove(struct i2c_client *client)  {  	struct ds1307 *ds1307 = i2c_get_clientdata(client); @@ -963,7 +956,7 @@ static struct i2c_driver ds1307_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= ds1307_probe, -	.remove		= __devexit_p(ds1307_remove), +	.remove		= ds1307_remove,  	.id_table	= ds1307_id,  }; diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 966316088b7..fef76868aae 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -391,7 +391,7 @@ out_free:  	return ret;  } -static int __devexit ds1374_remove(struct i2c_client *client) +static int ds1374_remove(struct i2c_client *client)  {  	struct ds1374 *ds1374 = i2c_get_clientdata(client); @@ -442,7 +442,7 @@ static struct i2c_driver ds1374_driver = {  		.pm = DS1374_PM,  	},  	.probe = ds1374_probe, -	.remove = __devexit_p(ds1374_remove), +	.remove = ds1374_remove,  	.id_table = ds1374_id,  }; diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index b0a99e1b25b..f994257981a 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -121,7 +121,7 @@ static const struct rtc_class_ops ds1390_rtc_ops = {  	.set_time	= ds1390_set_time,  }; -static int __devinit ds1390_probe(struct spi_device *spi) +static int ds1390_probe(struct spi_device *spi)  {  	unsigned char tmp;  	struct ds1390 *chip; @@ -156,7 +156,7 @@ static int __devinit ds1390_probe(struct spi_device *spi)  	return res;  } -static int __devexit ds1390_remove(struct spi_device *spi) +static int ds1390_remove(struct spi_device *spi)  {  	struct ds1390 *chip = spi_get_drvdata(spi); @@ -172,7 +172,7 @@ static struct spi_driver ds1390_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= ds1390_probe, -	.remove = __devexit_p(ds1390_remove), +	.remove = ds1390_remove,  };  module_spi_driver(ds1390_driver); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 1f675f5294f..6a3fcfe3b0e 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -476,8 +476,7 @@ static struct bin_attribute ds1511_nvram_attr = {  	.write = ds1511_nvram_write,  }; - static int __devinit -ds1511_rtc_probe(struct platform_device *pdev) +static int ds1511_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct resource *res; @@ -551,8 +550,7 @@ ds1511_rtc_probe(struct platform_device *pdev)  	return ret;  } - static int __devexit -ds1511_rtc_remove(struct platform_device *pdev) +static int ds1511_rtc_remove(struct platform_device *pdev)  {  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); @@ -573,7 +571,7 @@ MODULE_ALIAS("platform:ds1511");  static struct platform_driver ds1511_rtc_driver = {  	.probe		= ds1511_rtc_probe, -	.remove		= __devexit_p(ds1511_rtc_remove), +	.remove		= ds1511_rtc_remove,  	.driver		= {  		.name	= "ds1511",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 6ccedbbf923..25ce0621ade 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -276,7 +276,7 @@ static struct bin_attribute ds1553_nvram_attr = {  	.write = ds1553_nvram_write,  }; -static int __devinit ds1553_rtc_probe(struct platform_device *pdev) +static int ds1553_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct resource *res; @@ -338,7 +338,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit ds1553_rtc_remove(struct platform_device *pdev) +static int ds1553_rtc_remove(struct platform_device *pdev)  {  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); @@ -354,7 +354,7 @@ MODULE_ALIAS("platform:rtc-ds1553");  static struct platform_driver ds1553_rtc_driver = {  	.probe		= ds1553_rtc_probe, -	.remove		= __devexit_p(ds1553_rtc_remove), +	.remove		= ds1553_rtc_remove,  	.driver		= {  		.name	= "rtc-ds1553",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 76112667c50..609c870e2cc 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -159,7 +159,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,  	return count;  } -static int __devinit ds1742_rtc_probe(struct platform_device *pdev) +static int ds1742_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct resource *res; @@ -222,7 +222,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit ds1742_rtc_remove(struct platform_device *pdev) +static int ds1742_rtc_remove(struct platform_device *pdev)  {  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); @@ -233,7 +233,7 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev)  static struct platform_driver ds1742_rtc_driver = {  	.probe		= ds1742_rtc_probe, -	.remove		= __devexit_p(ds1742_rtc_remove), +	.remove		= ds1742_rtc_remove,  	.driver		= {  		.name	= "rtc-ds1742",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 5ea9df7c8c3..b04fc4272fb 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-ds3232.c b/drivers/rtc/rtc-ds3232.c index e1945095814..db0ca08db31 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -391,8 +391,8 @@ static const struct rtc_class_ops ds3232_rtc_ops = {  	.alarm_irq_enable = ds3232_alarm_irq_enable,  }; -static int __devinit ds3232_probe(struct i2c_client *client, -		const struct i2c_device_id *id) +static int ds3232_probe(struct i2c_client *client, +			const struct i2c_device_id *id)  {  	struct ds3232 *ds3232;  	int ret; @@ -439,7 +439,7 @@ out_free:  	return ret;  } -static int __devexit ds3232_remove(struct i2c_client *client) +static int ds3232_remove(struct i2c_client *client)  {  	struct ds3232 *ds3232 = i2c_get_clientdata(client); @@ -469,7 +469,7 @@ static struct i2c_driver ds3232_driver = {  		.owner = THIS_MODULE,  	},  	.probe = ds3232_probe, -	.remove = __devexit_p(ds3232_remove), +	.remove = ds3232_remove,  	.id_table = ds3232_id,  }; diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index fda707926f0..7a4495ef1c3 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c @@ -105,7 +105,7 @@ static const struct rtc_class_ops ds3234_rtc_ops = {  	.set_time	= ds3234_set_time,  }; -static int __devinit ds3234_probe(struct spi_device *spi) +static int ds3234_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	unsigned char tmp; @@ -156,7 +156,7 @@ static int __devinit ds3234_probe(struct spi_device *spi)  	return 0;  } -static int __devexit ds3234_remove(struct spi_device *spi) +static int ds3234_remove(struct spi_device *spi)  {  	struct rtc_device *rtc = spi_get_drvdata(spi); @@ -170,7 +170,7 @@ static struct spi_driver ds3234_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	 = ds3234_probe, -	.remove = __devexit_p(ds3234_remove), +	.remove = ds3234_remove,  };  module_spi_driver(ds3234_driver); diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index c9f890b088d..1a0c37c9152 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-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 9602278ff98..1a4e5e4a70c 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -127,7 +127,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {  	.attrs	= ep93xx_rtc_attrs,  }; -static int __devinit ep93xx_rtc_probe(struct platform_device *pdev) +static int ep93xx_rtc_probe(struct platform_device *pdev)  {  	struct ep93xx_rtc *ep93xx_rtc;  	struct resource *res; @@ -174,7 +174,7 @@ exit:  	return err;  } -static int __devexit ep93xx_rtc_remove(struct platform_device *pdev) +static int ep93xx_rtc_remove(struct platform_device *pdev)  {  	struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev); @@ -192,7 +192,7 @@ static struct platform_driver ep93xx_rtc_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= ep93xx_rtc_probe, -	.remove		= __devexit_p(ep93xx_rtc_remove), +	.remove		= ep93xx_rtc_remove,  };  module_platform_driver(ep93xx_rtc_driver); diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 86b6ecce99f..bff3cdc5140 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); @@ -361,8 +346,8 @@ static const struct rtc_class_ops fm3130_rtc_ops = {  static struct i2c_driver fm3130_driver; -static int __devinit fm3130_probe(struct i2c_client *client, -				  const struct i2c_device_id *id) +static int fm3130_probe(struct i2c_client *client, +			const struct i2c_device_id *id)  {  	struct fm3130		*fm3130;  	int			err = -ENODEV; @@ -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 */ @@ -546,7 +521,7 @@ exit_free:  	return err;  } -static int __devexit fm3130_remove(struct i2c_client *client) +static int fm3130_remove(struct i2c_client *client)  {  	struct fm3130 *fm3130 = i2c_get_clientdata(client); @@ -561,7 +536,7 @@ static struct i2c_driver fm3130_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= fm3130_probe, -	.remove		= __devexit_p(fm3130_remove), +	.remove		= fm3130_remove,  	.id_table	= fm3130_id,  }; diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c new file mode 100644 index 00000000000..31c5728ef62 --- /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 <holler@ahsoftware.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 4eed51044c5..82aad695979 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -36,7 +36,9 @@  #include <linux/platform_device.h>  #include <linux/rtc.h>  #include <linux/sched.h> +#include <linux/spinlock.h>  #include <linux/workqueue.h> +#include <linux/of.h>  /* DryIce Register Definitions */ @@ -404,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); @@ -473,12 +475,11 @@ static int dryice_rtc_probe(struct platform_device *pdev)  err:  	clk_disable_unprepare(imxdi->clk); -	clk_put(imxdi->clk);  	return rc;  } -static int __devexit dryice_rtc_remove(struct platform_device *pdev) +static int dryice_rtc_remove(struct platform_device *pdev)  {  	struct imxdi_dev *imxdi = platform_get_drvdata(pdev); @@ -490,17 +491,26 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev)  	rtc_device_unregister(imxdi->rtc);  	clk_disable_unprepare(imxdi->clk); -	clk_put(imxdi->clk);  	return 0;  } +#ifdef CONFIG_OF +static const struct of_device_id dryice_dt_ids[] = { +	{ .compatible = "fsl,imx25-rtc" }, +	{ /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, dryice_dt_ids); +#endif +  static struct platform_driver dryice_rtc_driver = {  	.driver = {  		   .name = "imxdi_rtc",  		   .owner = THIS_MODULE, +		   .of_match_table = of_match_ptr(dryice_dt_ids),  		   }, -	.remove = __devexit_p(dryice_rtc_remove), +	.remove = dryice_rtc_remove,  };  static int __init dryice_rtc_init(void) diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 1850104705c..6b4298ea683 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 26c81f23360..c016ad81767 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -118,7 +118,7 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],  	return ret;  } -/* simple check to see wether we have a isl1208 */ +/* simple check to see whether we have a isl1208 */  static int  isl1208_i2c_validate_client(struct i2c_client *client)  { @@ -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-jz4740.c b/drivers/rtc/rtc-jz4740.c index 1224182d3ea..1e48686ca6d 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -210,7 +210,7 @@ void jz4740_rtc_poweroff(struct device *dev)  }  EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); -static int __devinit jz4740_rtc_probe(struct platform_device *pdev) +static int jz4740_rtc_probe(struct platform_device *pdev)  {  	int ret;  	struct jz4740_rtc *rtc; @@ -297,7 +297,7 @@ err_free:  	return ret;  } -static int __devexit jz4740_rtc_remove(struct platform_device *pdev) +static int jz4740_rtc_remove(struct platform_device *pdev)  {  	struct jz4740_rtc *rtc = platform_get_drvdata(pdev); @@ -347,7 +347,7 @@ static const struct dev_pm_ops jz4740_pm_ops = {  static struct platform_driver jz4740_rtc_driver = {  	.probe	 = jz4740_rtc_probe, -	.remove	 = __devexit_p(jz4740_rtc_remove), +	.remove	 = jz4740_rtc_remove,  	.driver	 = {  		.name  = "jz4740-rtc",  		.owner = THIS_MODULE, diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c new file mode 100644 index 00000000000..9a4631218f4 --- /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 <milo.kim@ti.com> + * + * 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-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index d5218553741..40a598332ba 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -197,7 +197,7 @@ static const struct rtc_class_ops lpc32xx_rtc_ops = {  	.alarm_irq_enable	= lpc32xx_rtc_alarm_irq_enable,  }; -static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) +static int lpc32xx_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct lpc32xx_rtc *rtc; @@ -299,7 +299,7 @@ static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev) +static int lpc32xx_rtc_remove(struct platform_device *pdev)  {  	struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); @@ -397,7 +397,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match);  static struct platform_driver lpc32xx_rtc_driver = {  	.probe		= lpc32xx_rtc_probe, -	.remove		= __devexit_p(lpc32xx_rtc_remove), +	.remove		= lpc32xx_rtc_remove,  	.driver = {  		.name	= RTC_NAME,  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 07e81c5f824..f59b6349551 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -143,7 +143,7 @@ static struct rtc_class_ops  ls1x_rtc_ops = {  	.set_time	= ls1x_rtc_set_time,  }; -static int __devinit ls1x_rtc_probe(struct platform_device *pdev) +static int ls1x_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtcdev;  	unsigned long v; @@ -185,7 +185,7 @@ err:  	return ret;  } -static int __devexit ls1x_rtc_remove(struct platform_device *pdev) +static int ls1x_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtcdev = platform_get_drvdata(pdev); @@ -200,7 +200,7 @@ static struct platform_driver  ls1x_rtc_driver = {  		.name	= "ls1x-rtc",  		.owner	= THIS_MODULE,  	}, -	.remove		= __devexit_p(ls1x_rtc_remove), +	.remove		= ls1x_rtc_remove,  	.probe		= ls1x_rtc_probe,  }; diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index efab3d48cb1..49169680786 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -170,7 +170,7 @@ static const struct rtc_class_ops m41t93_rtc_ops = {  static struct spi_driver m41t93_driver; -static int __devinit m41t93_probe(struct spi_device *spi) +static int m41t93_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	int res; @@ -195,7 +195,7 @@ static int __devinit m41t93_probe(struct spi_device *spi)  } -static int __devexit m41t93_remove(struct spi_device *spi) +static int m41t93_remove(struct spi_device *spi)  {  	struct rtc_device *rtc = spi_get_drvdata(spi); @@ -211,7 +211,7 @@ static struct spi_driver m41t93_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= m41t93_probe, -	.remove = __devexit_p(m41t93_remove), +	.remove = m41t93_remove,  };  module_spi_driver(m41t93_driver); diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index 6e78193e026..89266c6764b 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -110,7 +110,7 @@ static const struct rtc_class_ops m41t94_rtc_ops = {  static struct spi_driver m41t94_driver; -static int __devinit m41t94_probe(struct spi_device *spi) +static int m41t94_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	int res; @@ -134,7 +134,7 @@ static int __devinit m41t94_probe(struct spi_device *spi)  	return 0;  } -static int __devexit m41t94_remove(struct spi_device *spi) +static int m41t94_remove(struct spi_device *spi)  {  	struct rtc_device *rtc = spi_get_drvdata(spi); @@ -150,7 +150,7 @@ static struct spi_driver m41t94_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= m41t94_probe, -	.remove = __devexit_p(m41t94_remove), +	.remove = m41t94_remove,  };  module_spi_driver(m41t94_driver); diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index f9e3b358373..31c9190a1fc 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -141,7 +141,7 @@ static const struct rtc_class_ops m48t35_ops = {  	.set_time	= m48t35_set_time,  }; -static int __devinit m48t35_probe(struct platform_device *pdev) +static int m48t35_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct m48t35_priv *priv; @@ -194,7 +194,7 @@ out:  	return ret;  } -static int __devexit m48t35_remove(struct platform_device *pdev) +static int m48t35_remove(struct platform_device *pdev)  {  	struct m48t35_priv *priv = platform_get_drvdata(pdev); @@ -213,7 +213,7 @@ static struct platform_driver m48t35_platform_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= m48t35_probe, -	.remove		= __devexit_p(m48t35_remove), +	.remove		= m48t35_remove,  };  module_platform_driver(m48t35_platform_driver); diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 30ebfec9fd2..130f29af386 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -383,7 +383,7 @@ static struct bin_attribute m48t59_nvram_attr = {  	.write = m48t59_nvram_write,  }; -static int __devinit m48t59_rtc_probe(struct platform_device *pdev) +static int m48t59_rtc_probe(struct platform_device *pdev)  {  	struct m48t59_plat_data *pdata = pdev->dev.platform_data;  	struct m48t59_private *m48t59 = NULL; @@ -501,7 +501,7 @@ out:  	return ret;  } -static int __devexit m48t59_rtc_remove(struct platform_device *pdev) +static int m48t59_rtc_remove(struct platform_device *pdev)  {  	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);  	struct m48t59_plat_data *pdata = pdev->dev.platform_data; @@ -527,7 +527,7 @@ static struct platform_driver m48t59_rtc_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= m48t59_rtc_probe, -	.remove		= __devexit_p(m48t59_rtc_remove), +	.remove		= m48t59_rtc_remove,  };  module_platform_driver(m48t59_rtc_driver); diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 863fb3363aa..2ffbcacd243 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -144,7 +144,7 @@ static const struct rtc_class_ops m48t86_rtc_ops = {  	.proc		= m48t86_rtc_proc,  }; -static int __devinit m48t86_rtc_probe(struct platform_device *dev) +static int m48t86_rtc_probe(struct platform_device *dev)  {  	unsigned char reg;  	struct m48t86_ops *ops = dev->dev.platform_data; @@ -164,7 +164,7 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev)  	return 0;  } -static int __devexit m48t86_rtc_remove(struct platform_device *dev) +static int m48t86_rtc_remove(struct platform_device *dev)  {  	struct rtc_device *rtc = platform_get_drvdata(dev); @@ -182,7 +182,7 @@ static struct platform_driver m48t86_rtc_platform_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= m48t86_rtc_probe, -	.remove		= __devexit_p(m48t86_rtc_remove), +	.remove		= m48t86_rtc_remove,  };  module_platform_driver(m48t86_rtc_platform_driver); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 36c74d22e8b..7d0bf698b79 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -120,7 +120,7 @@ static const struct rtc_class_ops max6902_rtc_ops = {  	.set_time	= max6902_set_time,  }; -static int __devinit max6902_probe(struct spi_device *spi) +static int max6902_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	unsigned char tmp; @@ -143,7 +143,7 @@ static int __devinit max6902_probe(struct spi_device *spi)  	return 0;  } -static int __devexit max6902_remove(struct spi_device *spi) +static int max6902_remove(struct spi_device *spi)  {  	struct rtc_device *rtc = dev_get_drvdata(&spi->dev); @@ -157,7 +157,7 @@ static struct spi_driver max6902_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= max6902_probe, -	.remove = __devexit_p(max6902_remove), +	.remove = max6902_remove,  };  module_spi_driver(max6902_driver); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c new file mode 100644 index 00000000000..6b1337f9baf --- /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("<woong.byun@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index e094ffa434f..31ca8faf9f0 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c @@ -176,7 +176,7 @@ static const struct rtc_class_ops max8907_rtc_ops = {  	.set_alarm	= max8907_rtc_set_alarm,  }; -static int __devinit max8907_rtc_probe(struct platform_device *pdev) +static int max8907_rtc_probe(struct platform_device *pdev)  {  	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);  	struct max8907_rtc *rtc; @@ -205,8 +205,9 @@ static int __devinit 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); @@ -220,11 +221,10 @@ err_unregister:  	return ret;  } -static int __devexit max8907_rtc_remove(struct platform_device *pdev) +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; @@ -236,7 +236,7 @@ static struct platform_driver max8907_rtc_driver = {  		.owner = THIS_MODULE,  	},  	.probe = max8907_rtc_probe, -	.remove = __devexit_p(max8907_rtc_remove), +	.remove = max8907_rtc_remove,  };  module_platform_driver(max8907_rtc_driver); diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 34e4349611d..a0c8265646d 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -247,7 +247,7 @@ static const struct rtc_class_ops max8925_rtc_ops = {  	.set_alarm	= max8925_rtc_set_alarm,  }; -static int __devinit max8925_rtc_probe(struct platform_device *pdev) +static int max8925_rtc_probe(struct platform_device *pdev)  {  	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);  	struct max8925_rtc_info *info; @@ -292,7 +292,7 @@ out_irq:  	return ret;  } -static int __devexit max8925_rtc_remove(struct platform_device *pdev) +static int max8925_rtc_remove(struct platform_device *pdev)  {  	struct max8925_rtc_info *info = platform_get_drvdata(pdev); @@ -334,7 +334,7 @@ static struct platform_driver max8925_rtc_driver = {  		.pm     = &max8925_rtc_pm_ops,  	},  	.probe		= max8925_rtc_probe, -	.remove		= __devexit_p(max8925_rtc_remove), +	.remove		= max8925_rtc_remove,  };  module_platform_driver(max8925_rtc_driver); diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c new file mode 100644 index 00000000000..00e505b6bee --- /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("<ms925.kim@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 7196f438c08..8f234a075e8 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -249,7 +249,7 @@ static const struct rtc_class_ops max8998_rtc_ops = {  	.alarm_irq_enable = max8998_rtc_alarm_irq_enable,  }; -static int __devinit max8998_rtc_probe(struct platform_device *pdev) +static int max8998_rtc_probe(struct platform_device *pdev)  {  	struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent);  	struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev); @@ -298,7 +298,7 @@ out_rtc:  	return ret;  } -static int __devexit max8998_rtc_remove(struct platform_device *pdev) +static int max8998_rtc_remove(struct platform_device *pdev)  {  	struct max8998_rtc_info *info = platform_get_drvdata(pdev); @@ -323,7 +323,7 @@ static struct platform_driver max8998_rtc_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= max8998_rtc_probe, -	.remove		= __devexit_p(max8998_rtc_remove), +	.remove		= max8998_rtc_remove,  	.id_table	= max8998_rtc_id,  }; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 029e421baae..bdcc60830ae 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> @@ -306,7 +307,7 @@ static const struct rtc_class_ops mpc5200_rtc_ops = {  	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,  }; -static int __devinit mpc5121_rtc_probe(struct platform_device *op) +static int mpc5121_rtc_probe(struct platform_device *op)  {  	struct mpc5121_rtc_data *rtc;  	int err = 0; @@ -382,7 +383,7 @@ out_free:  	return err;  } -static int __devexit mpc5121_rtc_remove(struct platform_device *op) +static int mpc5121_rtc_remove(struct platform_device *op)  {  	struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev);  	struct mpc5121_rtc_regs __iomem *regs = rtc->regs; @@ -403,20 +404,22 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)  	return 0;  } -static struct of_device_id mpc5121_rtc_match[] __devinitdata = { +#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 = __devexit_p(mpc5121_rtc_remove), +	.remove = mpc5121_rtc_remove,  };  module_platform_driver(mpc5121_rtc_driver); diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index f51719bf4a7..578baf9d972 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -322,8 +322,8 @@ static irqreturn_t mrst_rtc_irq(int irq, void *p)  	return IRQ_NONE;  } -static int __devinit -vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) +static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, +			      int rtc_irq)  {  	int retval = 0;  	unsigned char rtc_control; @@ -394,7 +394,7 @@ static void rtc_mrst_do_shutdown(void)  	spin_unlock_irq(&rtc_lock);  } -static void __devexit rtc_mrst_do_remove(struct device *dev) +static void rtc_mrst_do_remove(struct device *dev)  {  	struct mrst_rtc	*mrst = dev_get_drvdata(dev);  	struct resource *iomem; @@ -503,14 +503,14 @@ static inline int mrst_poweroff(struct device *dev)  #endif -static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev) +static int vrtc_mrst_platform_probe(struct platform_device *pdev)  {  	return vrtc_mrst_do_probe(&pdev->dev,  			platform_get_resource(pdev, IORESOURCE_MEM, 0),  			platform_get_irq(pdev, 0));  } -static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev) +static int vrtc_mrst_platform_remove(struct platform_device *pdev)  {  	rtc_mrst_do_remove(&pdev->dev);  	return 0; @@ -528,7 +528,7 @@ MODULE_ALIAS("platform:vrtc_mrst");  static struct platform_driver vrtc_mrst_platform_driver = {  	.probe		= vrtc_mrst_platform_probe, -	.remove		= __devexit_p(vrtc_mrst_platform_remove), +	.remove		= vrtc_mrst_platform_remove,  	.shutdown	= vrtc_mrst_platform_shutdown,  	.driver = {  		.name		= (char *) driver_name, diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index ebc1649d45d..8f87fec27ce 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -14,6 +14,7 @@  #include <linux/platform_device.h>  #include <linux/of.h>  #include <linux/delay.h> +#include <linux/clk.h>  #include <linux/gfp.h>  #include <linux/module.h> @@ -41,6 +42,7 @@ struct rtc_plat_data {  	struct rtc_device *rtc;  	void __iomem *ioaddr;  	int		irq; +	struct clk	*clk;  };  static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -215,12 +217,13 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = {  	.alarm_irq_enable = mv_rtc_alarm_irq_enable,  }; -static int __devinit mv_rtc_probe(struct platform_device *pdev) +static int mv_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct rtc_plat_data *pdata;  	resource_size_t size;  	u32 rtc_time; +	int ret = 0;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) @@ -239,11 +242,17 @@ static int __devinit mv_rtc_probe(struct platform_device *pdev)  	if (!pdata->ioaddr)  		return -ENOMEM; +	pdata->clk = devm_clk_get(&pdev->dev, NULL); +	/* Not all SoCs require a clock.*/ +	if (!IS_ERR(pdata->clk)) +		clk_prepare_enable(pdata->clk); +  	/* make sure the 24 hours mode is enabled */  	rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);  	if (rtc_time & RTC_HOURS_12H_MODE) {  		dev_err(&pdev->dev, "24 Hours mode not supported.\n"); -		return -EINVAL; +		ret = -EINVAL; +		goto out;  	}  	/* make sure it is actually functional */ @@ -252,7 +261,8 @@ static int __devinit mv_rtc_probe(struct platform_device *pdev)  		rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);  		if (rtc_time == 0x01000000) {  			dev_err(&pdev->dev, "internal RTC not ticking\n"); -			return -ENODEV; +			ret = -ENODEV; +			goto out;  		}  	} @@ -268,8 +278,10 @@ static int __devinit mv_rtc_probe(struct platform_device *pdev)  	} else  		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,  						 &mv_rtc_ops, THIS_MODULE); -	if (IS_ERR(pdata->rtc)) -		return PTR_ERR(pdata->rtc); +	if (IS_ERR(pdata->rtc)) { +		ret = PTR_ERR(pdata->rtc); +		goto out; +	}  	if (pdata->irq >= 0) {  		writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); @@ -282,6 +294,11 @@ static int __devinit mv_rtc_probe(struct platform_device *pdev)  	}  	return 0; +out: +	if (!IS_ERR(pdata->clk)) +		clk_disable_unprepare(pdata->clk); + +	return ret;  }  static int __exit mv_rtc_remove(struct platform_device *pdev) @@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)  		device_init_wakeup(&pdev->dev, 0);  	rtc_device_unregister(pdata->rtc); +	if (!IS_ERR(pdata->clk)) +		clk_disable_unprepare(pdata->clk); +  	return 0;  } diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index cd0106293a4..1c3ef728956 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -17,8 +17,6 @@  #include <linux/platform_device.h>  #include <linux/clk.h> -#include <mach/hardware.h> -  #define RTC_INPUT_CLK_32768HZ	(0x00 << 5)  #define RTC_INPUT_CLK_32000HZ	(0x01 << 5)  #define RTC_INPUT_CLK_38400HZ	(0x02 << 5) @@ -72,14 +70,38 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = {  #define RTC_TEST2	0x2C	/*  32bit rtc test reg 2 */  #define RTC_TEST3	0x30	/*  32bit rtc test reg 3 */ +enum imx_rtc_type { +	IMX1_RTC, +	IMX21_RTC, +}; +  struct rtc_plat_data {  	struct rtc_device *rtc;  	void __iomem *ioaddr;  	int irq;  	struct clk *clk;  	struct rtc_time g_rtc_alarm; +	enum imx_rtc_type devtype;  }; +static struct platform_device_id imx_rtc_devtype[] = { +	{ +		.name = "imx1-rtc", +		.driver_data = IMX1_RTC, +	}, { +		.name = "imx21-rtc", +		.driver_data = IMX21_RTC, +	}, { +		/* sentinel */ +	} +}; +MODULE_DEVICE_TABLE(platform, imx_rtc_devtype); + +static inline int is_imx1_rtc(struct rtc_plat_data *data) +{ +	return data->devtype == IMX1_RTC; +} +  /*   * This function is used to obtain the RTC time or the alarm value in   * second. @@ -278,10 +300,13 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)   */  static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)  { +	struct platform_device *pdev = to_platform_device(dev); +	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); +  	/*  	 * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only  	 */ -	if (cpu_is_mx1()) { +	if (is_imx1_rtc(pdata)) {  		struct rtc_time tm;  		rtc_time_to_tm(time, &tm); @@ -343,7 +368,7 @@ static struct rtc_class_ops mxc_rtc_ops = {  	.alarm_irq_enable	= mxc_rtc_alarm_irq_enable,  }; -static int __devinit mxc_rtc_probe(struct platform_device *pdev) +static int mxc_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct rtc_device *rtc; @@ -360,6 +385,8 @@ static int __devinit mxc_rtc_probe(struct platform_device *pdev)  	if (!pdata)  		return -ENOMEM; +	pdata->devtype = pdev->id_entry->driver_data; +  	if (!devm_request_mem_region(&pdev->dev, res->start,  				     resource_size(res), pdev->name))  		return -EBUSY; @@ -433,7 +460,7 @@ exit_free_pdata:  	return ret;  } -static int __devexit mxc_rtc_remove(struct platform_device *pdev) +static int mxc_rtc_remove(struct platform_device *pdev)  {  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); @@ -480,8 +507,9 @@ static struct platform_driver mxc_rtc_driver = {  #endif  		   .owner	= THIS_MODULE,  	}, +	.id_table = imx_rtc_devtype,  	.probe = mxc_rtc_probe, -	.remove = __devexit_p(mxc_rtc_remove), +	.remove = mxc_rtc_remove,  };  module_platform_driver(mxc_rtc_driver) diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index b79010987d1..a63680850fe 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c @@ -222,7 +222,7 @@ static struct rtc_class_ops nuc900_rtc_ops = {  	.alarm_irq_enable = nuc900_alarm_irq_enable,  }; -static int __devinit nuc900_rtc_probe(struct platform_device *pdev) +static int nuc900_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct nuc900_rtc *nuc900_rtc; @@ -284,7 +284,7 @@ fail1:	kfree(nuc900_rtc);  	return err;  } -static int __devexit nuc900_rtc_remove(struct platform_device *pdev) +static int nuc900_rtc_remove(struct platform_device *pdev)  {  	struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev);  	struct resource *res; @@ -304,7 +304,7 @@ static int __devexit nuc900_rtc_remove(struct platform_device *pdev)  }  static struct platform_driver nuc900_rtc_driver = { -	.remove		= __devexit_p(nuc900_rtc_remove), +	.remove		= nuc900_rtc_remove,  	.driver		= {  		.name	= "nuc900-rtc",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0b614e32653..600971407aa 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -20,6 +20,9 @@  #include <linux/rtc.h>  #include <linux/bcd.h>  #include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/pm_runtime.h>  #include <asm/io.h> @@ -38,6 +41,8 @@   * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment.   */ +#define	DRIVER_NAME			"omap_rtc" +  #define OMAP_RTC_BASE			0xfffb4800  /* RTC registers */ @@ -64,6 +69,9 @@  #define OMAP_RTC_COMP_MSB_REG		0x50  #define OMAP_RTC_OSC_REG		0x54 +#define OMAP_RTC_KICK0_REG		0x6c +#define OMAP_RTC_KICK1_REG		0x70 +  /* OMAP_RTC_CTRL_REG bit fields: */  #define OMAP_RTC_CTRL_SPLIT		(1<<7)  #define OMAP_RTC_CTRL_DISABLE		(1<<6) @@ -88,10 +96,18 @@  #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)  #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2) +/* OMAP_RTC_KICKER values */ +#define	KICK0_VALUE			0x83e70b13 +#define	KICK1_VALUE			0x95a4f1e0 + +#define	OMAP_RTC_HAS_KICKER		0x1 +  static void __iomem	*rtc_base; -#define rtc_read(addr)		__raw_readb(rtc_base + (addr)) -#define rtc_write(val, addr)	__raw_writeb(val, rtc_base + (addr)) +#define rtc_read(addr)		readb(rtc_base + (addr)) +#define rtc_write(val, addr)	writeb(val, rtc_base + (addr)) + +#define rtc_writel(val, addr)	writel(val, rtc_base + (addr))  /* we rely on the rtc framework to handle locking (rtc->ops_lock), @@ -285,11 +301,38 @@ static struct rtc_class_ops omap_rtc_ops = {  static int omap_rtc_alarm;  static int omap_rtc_timer; +#define	OMAP_RTC_DATA_DA830_IDX	1 + +static struct platform_device_id omap_rtc_devtype[] = { +	{ +		.name	= DRIVER_NAME, +	}, { +		.name	= "da830-rtc", +		.driver_data = OMAP_RTC_HAS_KICKER, +	}, +	{}, +}; +MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); + +static const struct of_device_id omap_rtc_of_match[] = { +	{	.compatible	= "ti,da830-rtc", +		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, omap_rtc_of_match); +  static int __init omap_rtc_probe(struct platform_device *pdev)  {  	struct resource		*res, *mem;  	struct rtc_device	*rtc;  	u8			reg, new_ctrl; +	const struct platform_device_id *id_entry; +	const struct of_device_id *of_id; + +	of_id = of_match_device(omap_rtc_of_match, &pdev->dev); +	if (of_id) +		pdev->id_entry = of_id->data;  	omap_rtc_timer = platform_get_irq(pdev, 0);  	if (omap_rtc_timer <= 0) { @@ -322,6 +365,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)  		goto fail;  	} +	/* Enable the clock/module so that we can access the registers */ +	pm_runtime_enable(&pdev->dev); +	pm_runtime_get_sync(&pdev->dev); + +	id_entry = platform_get_device_id(pdev); +	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { +		rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); +		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); +	} +  	rtc = rtc_device_register(pdev->name, &pdev->dev,  			&omap_rtc_ops, THIS_MODULE);  	if (IS_ERR(rtc)) { @@ -398,6 +451,10 @@ fail2:  fail1:  	rtc_device_unregister(rtc);  fail0: +	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) +		rtc_writel(0, OMAP_RTC_KICK0_REG); +	pm_runtime_put_sync(&pdev->dev); +	pm_runtime_disable(&pdev->dev);  	iounmap(rtc_base);  fail:  	release_mem_region(mem->start, resource_size(mem)); @@ -408,6 +465,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device	*rtc = platform_get_drvdata(pdev);  	struct resource		*mem = dev_get_drvdata(&rtc->dev); +	const struct platform_device_id *id_entry = +				platform_get_device_id(pdev);  	device_init_wakeup(&pdev->dev, 0); @@ -420,6 +479,13 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)  		free_irq(omap_rtc_alarm, rtc);  	rtc_device_unregister(rtc); +	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) +		rtc_writel(0, OMAP_RTC_KICK0_REG); + +	/* Disable the clock/module */ +	pm_runtime_put_sync(&pdev->dev); +	pm_runtime_disable(&pdev->dev); +  	iounmap(rtc_base);  	release_mem_region(mem->start, resource_size(mem));  	return 0; @@ -442,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)  	else  		rtc_write(0, OMAP_RTC_INTERRUPTS_REG); +	/* Disable the clock/module */ +	pm_runtime_put_sync(&pdev->dev); +  	return 0;  }  static int omap_rtc_resume(struct platform_device *pdev)  { +	/* Enable the clock/module so that we can access the registers */ +	pm_runtime_get_sync(&pdev->dev); +  	if (device_may_wakeup(&pdev->dev))  		disable_irq_wake(omap_rtc_alarm);  	else @@ -471,9 +543,11 @@ static struct platform_driver omap_rtc_driver = {  	.resume		= omap_rtc_resume,  	.shutdown	= omap_rtc_shutdown,  	.driver		= { -		.name	= "omap_rtc", +		.name	= DRIVER_NAME,  		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(omap_rtc_of_match),  	}, +	.id_table	= omap_rtc_devtype,  };  static int __init rtc_init(void) diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c new file mode 100644 index 00000000000..59c42986254 --- /dev/null +++ b/drivers/rtc/rtc-palmas.c @@ -0,0 +1,339 @@ +/* + * rtc-palmas.c -- Palmas Real Time Clock driver. + + * RTC driver for TI Palma series devices like TPS65913, + * TPS65914 power management IC. + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan <ldewangan@nvidia.com> + * + * 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/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/palmas.h> +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/pm.h> + +struct palmas_rtc { +	struct rtc_device	*rtc; +	struct device		*dev; +	unsigned int		irq; +}; + +/* Total number of RTC registers needed to set time*/ +#define PALMAS_NUM_TIME_REGS	(PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1) + +static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	int ret; + +	/* Copy RTC counting registers to static registers or latches */ +	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, +		PALMAS_RTC_CTRL_REG_GET_TIME, PALMAS_RTC_CTRL_REG_GET_TIME); +	if (ret < 0) { +		dev_err(dev, "RTC CTRL reg update failed, err: %d\n", ret); +		return ret; +	} + +	ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, +			rtc_data, PALMAS_NUM_TIME_REGS); +	if (ret < 0) { +		dev_err(dev, "RTC_SECONDS reg read failed, err = %d\n", ret); +		return ret; +	} + +	tm->tm_sec = bcd2bin(rtc_data[0]); +	tm->tm_min = bcd2bin(rtc_data[1]); +	tm->tm_hour = bcd2bin(rtc_data[2]); +	tm->tm_mday = bcd2bin(rtc_data[3]); +	tm->tm_mon = bcd2bin(rtc_data[4]) - 1; +	tm->tm_year = bcd2bin(rtc_data[5]) + 100; + +	return ret; +} + +static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	int ret; + +	rtc_data[0] = bin2bcd(tm->tm_sec); +	rtc_data[1] = bin2bcd(tm->tm_min); +	rtc_data[2] = bin2bcd(tm->tm_hour); +	rtc_data[3] = bin2bcd(tm->tm_mday); +	rtc_data[4] = bin2bcd(tm->tm_mon + 1); +	rtc_data[5] = bin2bcd(tm->tm_year - 100); + +	/* Stop RTC while updating the RTC time registers */ +	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, +		PALMAS_RTC_CTRL_REG_STOP_RTC, 0); +	if (ret < 0) { +		dev_err(dev, "RTC stop failed, err = %d\n", ret); +		return ret; +	} + +	ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, +		rtc_data, PALMAS_NUM_TIME_REGS); +	if (ret < 0) { +		dev_err(dev, "RTC_SECONDS reg write failed, err = %d\n", ret); +		return ret; +	} + +	/* Start back RTC */ +	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, +		PALMAS_RTC_CTRL_REG_STOP_RTC, PALMAS_RTC_CTRL_REG_STOP_RTC); +	if (ret < 0) +		dev_err(dev, "RTC start failed, err = %d\n", ret); +	return ret; +} + +static int palmas_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) +{ +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	u8 val; + +	val = enabled ? PALMAS_RTC_INTERRUPTS_REG_IT_ALARM : 0; +	return palmas_write(palmas, PALMAS_RTC_BASE, +		PALMAS_RTC_INTERRUPTS_REG, val); +} + +static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ +	unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; +	u32 int_val; +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	int ret; + +	ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, +			PALMAS_ALARM_SECONDS_REG, +			alarm_data, PALMAS_NUM_TIME_REGS); +	if (ret < 0) { +		dev_err(dev, "RTC_ALARM_SECONDS read failed, err = %d\n", ret); +		return ret; +	} + +	alm->time.tm_sec = bcd2bin(alarm_data[0]); +	alm->time.tm_min = bcd2bin(alarm_data[1]); +	alm->time.tm_hour = bcd2bin(alarm_data[2]); +	alm->time.tm_mday = bcd2bin(alarm_data[3]); +	alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; +	alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; + +	ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG, +			&int_val); +	if (ret < 0) { +		dev_err(dev, "RTC_INTERRUPTS reg read failed, err = %d\n", ret); +		return ret; +	} + +	if (int_val & PALMAS_RTC_INTERRUPTS_REG_IT_ALARM) +		alm->enabled = 1; +	return ret; +} + +static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ +	unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	int ret; + +	ret = palmas_rtc_alarm_irq_enable(dev, 0); +	if (ret < 0) { +		dev_err(dev, "Disable RTC alarm failed\n"); +		return ret; +	} + +	alarm_data[0] = bin2bcd(alm->time.tm_sec); +	alarm_data[1] = bin2bcd(alm->time.tm_min); +	alarm_data[2] = bin2bcd(alm->time.tm_hour); +	alarm_data[3] = bin2bcd(alm->time.tm_mday); +	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); +	alarm_data[5] = bin2bcd(alm->time.tm_year - 100); + +	ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, +		PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS); +	if (ret < 0) { +		dev_err(dev, "ALARM_SECONDS_REG write failed, err = %d\n", ret); +		return ret; +	} + +	if (alm->enabled) +		ret = palmas_rtc_alarm_irq_enable(dev, 1); +	return ret; +} + +static int palmas_clear_interrupts(struct device *dev) +{ +	struct palmas *palmas = dev_get_drvdata(dev->parent); +	unsigned int rtc_reg; +	int ret; + +	ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, +				&rtc_reg); +	if (ret < 0) { +		dev_err(dev, "RTC_STATUS read failed, err = %d\n", ret); +		return ret; +	} + +	ret = palmas_write(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, +			rtc_reg); +	if (ret < 0) { +		dev_err(dev, "RTC_STATUS write failed, err = %d\n", ret); +		return ret; +	} +	return 0; +} + +static irqreturn_t palmas_rtc_interrupt(int irq, void *context) +{ +	struct palmas_rtc *palmas_rtc = context; +	struct device *dev = palmas_rtc->dev; +	int ret; + +	ret = palmas_clear_interrupts(dev); +	if (ret < 0) { +		dev_err(dev, "RTC interrupt clear failed, err = %d\n", ret); +		return IRQ_NONE; +	} + +	rtc_update_irq(palmas_rtc->rtc, 1, RTC_IRQF | RTC_AF); +	return IRQ_HANDLED; +} + +static struct rtc_class_ops palmas_rtc_ops = { +	.read_time	= palmas_rtc_read_time, +	.set_time	= palmas_rtc_set_time, +	.read_alarm	= palmas_rtc_read_alarm, +	.set_alarm	= palmas_rtc_set_alarm, +	.alarm_irq_enable = palmas_rtc_alarm_irq_enable, +}; + +static int palmas_rtc_probe(struct platform_device *pdev) +{ +	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); +	struct palmas_rtc *palmas_rtc = NULL; +	int ret; + +	palmas_rtc = devm_kzalloc(&pdev->dev, sizeof(struct palmas_rtc), +			GFP_KERNEL); +	if (!palmas_rtc) +		return -ENOMEM; + +	/* Clear pending interrupts */ +	ret = palmas_clear_interrupts(&pdev->dev); +	if (ret < 0) { +		dev_err(&pdev->dev, "clear RTC int failed, err = %d\n", ret); +		return ret; +	} + +	palmas_rtc->dev = &pdev->dev; +	platform_set_drvdata(pdev, palmas_rtc); + +	/* Start RTC */ +	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, +			PALMAS_RTC_CTRL_REG_STOP_RTC, +			PALMAS_RTC_CTRL_REG_STOP_RTC); +	if (ret < 0) { +		dev_err(&pdev->dev, "RTC_CTRL write failed, err = %d\n", ret); +		return ret; +	} + +	palmas_rtc->irq = platform_get_irq(pdev, 0); + +	palmas_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, +				&palmas_rtc_ops, THIS_MODULE); +	if (IS_ERR(palmas_rtc->rtc)) { +		ret = PTR_ERR(palmas_rtc->rtc); +		dev_err(&pdev->dev, "RTC register failed, err = %d\n", ret); +		return ret; +	} + +	ret = request_threaded_irq(palmas_rtc->irq, NULL, +			palmas_rtc_interrupt, +			IRQF_TRIGGER_LOW | IRQF_ONESHOT | +			IRQF_EARLY_RESUME, +			dev_name(&pdev->dev), palmas_rtc); +	if (ret < 0) { +		dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret); +		rtc_device_unregister(palmas_rtc->rtc); +		return ret; +	} + +	device_set_wakeup_capable(&pdev->dev, 1); +	return 0; +} + +static int palmas_rtc_remove(struct platform_device *pdev) +{ +	struct palmas_rtc *palmas_rtc = platform_get_drvdata(pdev); + +	palmas_rtc_alarm_irq_enable(&pdev->dev, 0); +	free_irq(palmas_rtc->irq, palmas_rtc); +	rtc_device_unregister(palmas_rtc->rtc); +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int palmas_rtc_suspend(struct device *dev) +{ +	struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		enable_irq_wake(palmas_rtc->irq); +	return 0; +} + +static int palmas_rtc_resume(struct device *dev) +{ +	struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		disable_irq_wake(palmas_rtc->irq); +	return 0; +} +#endif + +static const struct dev_pm_ops palmas_rtc_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(palmas_rtc_suspend, palmas_rtc_resume) +}; + +static struct platform_driver palmas_rtc_driver = { +	.probe		= palmas_rtc_probe, +	.remove		= palmas_rtc_remove, +	.driver		= { +		.owner	= THIS_MODULE, +		.name	= "palmas-rtc", +		.pm	= &palmas_rtc_pm_ops, +	}, +}; + +module_platform_driver(palmas_rtc_driver); + +MODULE_ALIAS("platform:palmas_rtc"); +MODULE_DESCRIPTION("TI PALMAS series RTC driver"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index cd4f198cc2e..e0019cd0bf7 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c @@ -139,7 +139,7 @@ static const struct rtc_class_ops pcap_rtc_ops = {  	.alarm_irq_enable = pcap_rtc_alarm_irq_enable,  }; -static int __devinit pcap_rtc_probe(struct platform_device *pdev) +static int pcap_rtc_probe(struct platform_device *pdev)  {  	struct pcap_rtc *pcap_rtc;  	int timer_irq, alarm_irq; @@ -183,7 +183,7 @@ fail_rtc:  	return err;  } -static int __devexit pcap_rtc_remove(struct platform_device *pdev) +static int pcap_rtc_remove(struct platform_device *pdev)  {  	struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); @@ -196,7 +196,7 @@ static int __devexit pcap_rtc_remove(struct platform_device *pdev)  }  static struct platform_driver pcap_rtc_driver = { -	.remove = __devexit_p(pcap_rtc_remove), +	.remove = pcap_rtc_remove,  	.driver = {  		.name  = "pcap-rtc",  		.owner = THIS_MODULE, diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 13e4df63974..02b742afa76 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -219,7 +219,7 @@ static const struct rtc_class_ops pcf2123_rtc_ops = {  	.set_time	= pcf2123_rtc_set_time,  }; -static int __devinit pcf2123_probe(struct spi_device *spi) +static int pcf2123_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	struct pcf2123_plat_data *pdata; @@ -319,7 +319,7 @@ kfree_exit:  	return ret;  } -static int __devexit pcf2123_remove(struct spi_device *spi) +static int pcf2123_remove(struct spi_device *spi)  {  	struct pcf2123_plat_data *pdata = spi->dev.platform_data;  	int i; @@ -345,7 +345,7 @@ static struct spi_driver pcf2123_driver = {  			.owner	= THIS_MODULE,  	},  	.probe	= pcf2123_probe, -	.remove	= __devexit_p(pcf2123_remove), +	.remove	= pcf2123_remove,  };  module_spi_driver(pcf2123_driver); diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index a20202f9ee5..e9f3135d305 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -248,7 +248,7 @@ static void pcf50633_rtc_irq(int irq, void *data)  	rtc->alarm_pending = 1;  } -static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) +static int pcf50633_rtc_probe(struct platform_device *pdev)  {  	struct pcf50633_rtc *rtc; @@ -272,7 +272,7 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit pcf50633_rtc_remove(struct platform_device *pdev) +static int pcf50633_rtc_remove(struct platform_device *pdev)  {  	struct pcf50633_rtc *rtc; @@ -291,7 +291,7 @@ static struct platform_driver pcf50633_rtc_driver = {  		.name = "pcf50633-rtc",  	},  	.probe = pcf50633_rtc_probe, -	.remove = __devexit_p(pcf50633_rtc_remove), +	.remove = pcf50633_rtc_remove,  };  module_platform_driver(pcf50633_rtc_driver); diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c new file mode 100644 index 00000000000..889e3160e70 --- /dev/null +++ b/drivers/rtc/rtc-pcf8523.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * 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/bcd.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/of.h> + +#define DRIVER_NAME "rtc-pcf8523" + +#define REG_CONTROL1 0x00 +#define REG_CONTROL1_CAP_SEL (1 << 7) +#define REG_CONTROL1_STOP    (1 << 5) + +#define REG_CONTROL3 0x02 +#define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */ +#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) + +#define REG_MINUTES  0x04 +#define REG_HOURS    0x05 +#define REG_DAYS     0x06 +#define REG_WEEKDAYS 0x07 +#define REG_MONTHS   0x08 +#define REG_YEARS    0x09 + +struct pcf8523 { +	struct rtc_device *rtc; +}; + +static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep) +{ +	struct i2c_msg msgs[2]; +	u8 value = 0; +	int err; + +	msgs[0].addr = client->addr; +	msgs[0].flags = 0; +	msgs[0].len = sizeof(reg); +	msgs[0].buf = ® + +	msgs[1].addr = client->addr; +	msgs[1].flags = I2C_M_RD; +	msgs[1].len = sizeof(value); +	msgs[1].buf = &value; + +	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); +	if (err < 0) +		return err; + +	*valuep = value; + +	return 0; +} + +static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value) +{ +	u8 buffer[2] = { reg, value }; +	struct i2c_msg msg; +	int err; + +	msg.addr = client->addr; +	msg.flags = 0; +	msg.len = sizeof(buffer); +	msg.buf = buffer; + +	err = i2c_transfer(client->adapter, &msg, 1); +	if (err < 0) +		return err; + +	return 0; +} + +static int pcf8523_select_capacitance(struct i2c_client *client, bool high) +{ +	u8 value; +	int err; + +	err = pcf8523_read(client, REG_CONTROL1, &value); +	if (err < 0) +		return err; + +	if (!high) +		value &= ~REG_CONTROL1_CAP_SEL; +	else +		value |= REG_CONTROL1_CAP_SEL; + +	err = pcf8523_write(client, REG_CONTROL1, value); +	if (err < 0) +		return err; + +	return err; +} + +static int pcf8523_set_pm(struct i2c_client *client, u8 pm) +{ +	u8 value; +	int err; + +	err = pcf8523_read(client, REG_CONTROL3, &value); +	if (err < 0) +		return err; + +	value = (value & ~REG_CONTROL3_PM_MASK) | pm; + +	err = pcf8523_write(client, REG_CONTROL3, value); +	if (err < 0) +		return err; + +	return 0; +} + +static int pcf8523_stop_rtc(struct i2c_client *client) +{ +	u8 value; +	int err; + +	err = pcf8523_read(client, REG_CONTROL1, &value); +	if (err < 0) +		return err; + +	value |= REG_CONTROL1_STOP; + +	err = pcf8523_write(client, REG_CONTROL1, value); +	if (err < 0) +		return err; + +	return 0; +} + +static int pcf8523_start_rtc(struct i2c_client *client) +{ +	u8 value; +	int err; + +	err = pcf8523_read(client, REG_CONTROL1, &value); +	if (err < 0) +		return err; + +	value &= ~REG_CONTROL1_STOP; + +	err = pcf8523_write(client, REG_CONTROL1, value); +	if (err < 0) +		return err; + +	return 0; +} + +static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct i2c_client *client = to_i2c_client(dev); +	u8 start = REG_SECONDS, regs[7]; +	struct i2c_msg msgs[2]; +	int err; + +	msgs[0].addr = client->addr; +	msgs[0].flags = 0; +	msgs[0].len = 1; +	msgs[0].buf = &start; + +	msgs[1].addr = client->addr; +	msgs[1].flags = I2C_M_RD; +	msgs[1].len = sizeof(regs); +	msgs[1].buf = regs; + +	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); +	if (err < 0) +		return err; + +	if (regs[0] & REG_SECONDS_OS) { +		/* +		 * If the oscillator was stopped, try to clear the flag. Upon +		 * power-up the flag is always set, but if we cannot clear it +		 * the oscillator isn't running properly for some reason. The +		 * sensible thing therefore is to return an error, signalling +		 * that the clock cannot be assumed to be correct. +		 */ + +		regs[0] &= ~REG_SECONDS_OS; + +		err = pcf8523_write(client, REG_SECONDS, regs[0]); +		if (err < 0) +			return err; + +		err = pcf8523_read(client, REG_SECONDS, ®s[0]); +		if (err < 0) +			return err; + +		if (regs[0] & REG_SECONDS_OS) +			return -EAGAIN; +	} + +	tm->tm_sec = bcd2bin(regs[0] & 0x7f); +	tm->tm_min = bcd2bin(regs[1] & 0x7f); +	tm->tm_hour = bcd2bin(regs[2] & 0x3f); +	tm->tm_mday = bcd2bin(regs[3] & 0x3f); +	tm->tm_wday = regs[4] & 0x7; +	tm->tm_mon = bcd2bin(regs[5] & 0x1f); +	tm->tm_year = bcd2bin(regs[6]) + 100; + +	return rtc_valid_tm(tm); +} + +static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct i2c_msg msg; +	u8 regs[8]; +	int err; + +	err = pcf8523_stop_rtc(client); +	if (err < 0) +		return err; + +	regs[0] = REG_SECONDS; +	regs[1] = bin2bcd(tm->tm_sec); +	regs[2] = bin2bcd(tm->tm_min); +	regs[3] = bin2bcd(tm->tm_hour); +	regs[4] = bin2bcd(tm->tm_mday); +	regs[5] = tm->tm_wday; +	regs[6] = bin2bcd(tm->tm_mon); +	regs[7] = bin2bcd(tm->tm_year - 100); + +	msg.addr = client->addr; +	msg.flags = 0; +	msg.len = sizeof(regs); +	msg.buf = regs; + +	err = i2c_transfer(client->adapter, &msg, 1); +	if (err < 0) { +		/* +		 * If the time cannot be set, restart the RTC anyway. Note +		 * that errors are ignored if the RTC cannot be started so +		 * that we have a chance to propagate the original error. +		 */ +		pcf8523_start_rtc(client); +		return err; +	} + +	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, +			 const struct i2c_device_id *id) +{ +	struct pcf8523 *pcf; +	int err; + +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) +		return -ENODEV; + +	pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL); +	if (!pcf) +		return -ENOMEM; + +	err = pcf8523_select_capacitance(client, true); +	if (err < 0) +		return err; + +	err = pcf8523_set_pm(client, 0); +	if (err < 0) +		return err; + +	pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev, +				       &pcf8523_rtc_ops, THIS_MODULE); +	if (IS_ERR(pcf->rtc)) +		return PTR_ERR(pcf->rtc); + +	i2c_set_clientdata(client, pcf); + +	return 0; +} + +static int pcf8523_remove(struct i2c_client *client) +{ +	struct pcf8523 *pcf = i2c_get_clientdata(client); + +	rtc_device_unregister(pcf->rtc); + +	return 0; +} + +static const struct i2c_device_id pcf8523_id[] = { +	{ "pcf8523", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, pcf8523_id); + +#ifdef CONFIG_OF +static const struct of_device_id pcf8523_of_match[] = { +	{ .compatible = "nxp,pcf8523" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, pcf8523_of_match); +#endif + +static struct i2c_driver pcf8523_driver = { +	.driver = { +		.name = DRIVER_NAME, +		.owner = THIS_MODULE, +		.of_match_table = of_match_ptr(pcf8523_of_match), +	}, +	.probe = pcf8523_probe, +	.remove = pcf8523_remove, +	.id_table = pcf8523_id, +}; +module_i2c_driver(pcf8523_driver); + +MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); +MODULE_DESCRIPTION("NXP PCF8523 RTC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 98e3a2b681e..f7daf18a112 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;  } @@ -296,7 +296,7 @@ static const struct i2c_device_id pcf8563_id[] = {  MODULE_DEVICE_TABLE(i2c, pcf8563_id);  #ifdef CONFIG_OF -static const struct of_device_id pcf8563_of_match[] __devinitconst = { +static const struct of_device_id pcf8563_of_match[] = {  	{ .compatible = "nxp,pcf8563" },  	{}  }; diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 019ff357116..5f97c61247d 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; @@ -294,7 +294,7 @@ exit_kfree:  	return err;  } -static int __devexit pcf8583_remove(struct i2c_client *client) +static int pcf8583_remove(struct i2c_client *client)  {  	struct pcf8583 *pcf8583 = i2c_get_clientdata(client); @@ -316,7 +316,7 @@ static struct i2c_driver pcf8583_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= pcf8583_probe, -	.remove		= __devexit_p(pcf8583_remove), +	.remove		= pcf8583_remove,  	.id_table	= pcf8583_id,  }; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08378e3cc21..8900ea78481 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-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index d00bd24342a..f1a6557261f 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -382,7 +382,7 @@ rtc_alarm_handled:  	return IRQ_HANDLED;  } -static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) +static int pm8xxx_rtc_probe(struct platform_device *pdev)  {  	int rc;  	u8 ctrl_reg; @@ -485,7 +485,7 @@ fail_rtc_enable:  	return rc;  } -static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) +static int pm8xxx_rtc_remove(struct platform_device *pdev)  {  	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); @@ -524,7 +524,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resum  static struct platform_driver pm8xxx_rtc_driver = {  	.probe		= pm8xxx_rtc_probe, -	.remove		= __devexit_p(pm8xxx_rtc_remove), +	.remove		= pm8xxx_rtc_remove,  	.driver	= {  		.name	= PM8XXX_RTC_DEV_NAME,  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index ab0acaeb237..0407e13d4de 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -220,7 +220,7 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en)  	}  } -static int __devexit puv3_rtc_remove(struct platform_device *dev) +static int puv3_rtc_remove(struct platform_device *dev)  {  	struct rtc_device *rtc = platform_get_drvdata(dev); @@ -236,7 +236,7 @@ static int __devexit puv3_rtc_remove(struct platform_device *dev)  	return 0;  } -static int __devinit puv3_rtc_probe(struct platform_device *pdev) +static int puv3_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct resource *res; @@ -328,7 +328,7 @@ static int puv3_rtc_resume(struct platform_device *pdev)  static struct platform_driver puv3_rtc_driver = {  	.probe		= puv3_rtc_probe, -	.remove		= __devexit_p(puv3_rtc_remove), +	.remove		= puv3_rtc_remove,  	.suspend	= puv3_rtc_suspend,  	.resume		= puv3_rtc_resume,  	.driver		= { diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index f771b2ee4b1..03c85ee719a 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-r9701.c b/drivers/rtc/rtc-r9701.c index 2c183ebff71..7726f4a4f2d 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -119,7 +119,7 @@ static const struct rtc_class_ops r9701_rtc_ops = {  	.set_time	= r9701_set_datetime,  }; -static int __devinit r9701_probe(struct spi_device *spi) +static int r9701_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	struct rtc_time dt; @@ -164,7 +164,7 @@ static int __devinit r9701_probe(struct spi_device *spi)  	return 0;  } -static int __devexit r9701_remove(struct spi_device *spi) +static int r9701_remove(struct spi_device *spi)  {  	struct rtc_device *rtc = dev_get_drvdata(&spi->dev); @@ -178,7 +178,7 @@ static struct spi_driver r9701_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= r9701_probe, -	.remove = __devexit_p(r9701_remove), +	.remove = r9701_remove,  };  module_spi_driver(r9701_driver); diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index cdb140c29c5..eb3194d664a 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -211,7 +211,7 @@ static const struct rtc_class_ops rc5t583_rtc_ops = {  	.alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,  }; -static int __devinit rc5t583_rtc_probe(struct platform_device *pdev) +static int rc5t583_rtc_probe(struct platform_device *pdev)  {  	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);  	struct rc5t583_rtc *ricoh_rtc; @@ -271,7 +271,7 @@ static int __devinit rc5t583_rtc_probe(struct platform_device *pdev)   * Disable rc5t583 RTC interrupts.   * Sets status flag to free.   */ -static int __devexit rc5t583_rtc_remove(struct platform_device *pdev) +static int rc5t583_rtc_remove(struct platform_device *pdev)  {  	struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev); @@ -317,7 +317,7 @@ static const struct dev_pm_ops rc5t583_rtc_pm_ops = {  static struct platform_driver rc5t583_rtc_driver = {  	.probe		= rc5t583_rtc_probe, -	.remove		= __devexit_p(rc5t583_rtc_remove), +	.remove		= rc5t583_rtc_remove,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= "rtc-rc5t583", diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index e3ff179b99c..d98ea5b759c 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 */ @@ -377,7 +378,7 @@ static int rs5c313_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit rs5c313_rtc_remove(struct platform_device *pdev) +static int rs5c313_rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtc = platform_get_drvdata( pdev ); @@ -392,7 +393,7 @@ static struct platform_driver rs5c313_rtc_platform_driver = {  		.owner  = THIS_MODULE,  	},  	.probe 	= rs5c313_rtc_probe, -	.remove = __devexit_p( rs5c313_rtc_remove ), +	.remove = rs5c313_rtc_remove,  };  static int __init rs5c313_rtc_init(void) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index fd5c7af04ae..72ef10be866 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -152,7 +152,7 @@ static const struct rtc_class_ops rs5c348_rtc_ops = {  static struct spi_driver rs5c348_driver; -static int __devinit rs5c348_probe(struct spi_device *spi) +static int rs5c348_probe(struct spi_device *spi)  {  	int ret;  	struct rtc_device *rtc; @@ -218,7 +218,7 @@ static int __devinit rs5c348_probe(struct spi_device *spi)  	return ret;  } -static int __devexit rs5c348_remove(struct spi_device *spi) +static int rs5c348_remove(struct spi_device *spi)  {  	struct rs5c348_plat_data *pdata = spi->dev.platform_data;  	struct rtc_device *rtc = pdata->rtc; @@ -235,7 +235,7 @@ static struct spi_driver rs5c348_driver = {  		.owner	= THIS_MODULE,  	},  	.probe	= rs5c348_probe, -	.remove	= __devexit_p(rs5c348_remove), +	.remove	= rs5c348_remove,  };  module_spi_driver(rs5c348_driver); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 76f565ae384..581739f4009 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-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 0fbe57b2f6d..f8ee8ad7825 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -385,8 +385,8 @@ static struct i2c_device_id rv3029c2_id[] = {  };  MODULE_DEVICE_TABLE(i2c, rv3029c2_id); -static int __devinit -rv3029c2_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int rv3029c2_probe(struct i2c_client *client, +			  const struct i2c_device_id *id)  {  	struct rtc_device *rtc;  	int rc = 0; @@ -418,7 +418,7 @@ exit_unregister:  	return rc;  } -static int __devexit rv3029c2_remove(struct i2c_client *client) +static int rv3029c2_remove(struct i2c_client *client)  {  	struct rtc_device *rtc = i2c_get_clientdata(client); @@ -432,7 +432,7 @@ static struct i2c_driver rv3029c2_driver = {  		.name = "rtc-rv3029c2",  	},  	.probe = rv3029c2_probe, -	.remove = __devexit_p(rv3029c2_remove), +	.remove = rv3029c2_remove,  	.id_table = rv3029c2_id,  }; diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c new file mode 100644 index 00000000000..599ec73ec88 --- /dev/null +++ b/drivers/rtc/rtc-rx4581.c @@ -0,0 +1,314 @@ +/* drivers/rtc/rtc-rx4581.c + * + * written by Torben Hohn <torbenh@linutronix.de> + * + * 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 <martyn.welch@ge.com> + * 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-rx8025.c b/drivers/rtc/rtc-rx8025.c index 0de902dc1cd..0722d36b9c9 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -534,8 +534,8 @@ static void rx8025_sysfs_unregister(struct device *dev)  	device_remove_file(dev, &dev_attr_clock_adjust_ppb);  } -static int __devinit rx8025_probe(struct i2c_client *client, -				  const struct i2c_device_id *id) +static int rx8025_probe(struct i2c_client *client, +			const struct i2c_device_id *id)  {  	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);  	struct rx8025_data *rx8025; @@ -614,7 +614,7 @@ errout:  	return err;  } -static int __devexit rx8025_remove(struct i2c_client *client) +static int rx8025_remove(struct i2c_client *client)  {  	struct rx8025_data *rx8025 = i2c_get_clientdata(client);  	struct mutex *lock = &rx8025->rtc->ops_lock; @@ -640,7 +640,7 @@ static struct i2c_driver rx8025_driver = {  		.owner = THIS_MODULE,  	},  	.probe		= rx8025_probe, -	.remove		= __devexit_p(rx8025_remove), +	.remove		= rx8025_remove,  	.id_table	= rx8025_id,  }; diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index d84825124a7..b0c272658fa 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -228,8 +228,8 @@ static const struct rtc_class_ops rx8581_rtc_ops = {  	.set_time	= rx8581_rtc_set_time,  }; -static int __devinit rx8581_probe(struct i2c_client *client, -				const struct i2c_device_id *id) +static int rx8581_probe(struct i2c_client *client, +			const struct i2c_device_id *id)  {  	struct rtc_device *rtc; @@ -251,7 +251,7 @@ static int __devinit rx8581_probe(struct i2c_client *client,  	return 0;  } -static int __devexit rx8581_remove(struct i2c_client *client) +static int rx8581_remove(struct i2c_client *client)  {  	struct rtc_device *rtc = i2c_get_clientdata(client); @@ -272,7 +272,7 @@ static struct i2c_driver rx8581_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= rx8581_probe, -	.remove		= __devexit_p(rx8581_remove), +	.remove		= rx8581_remove,  	.id_table	= rx8581_id,  }; diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 77823d21d31..fb994e9ddc1 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -47,8 +47,6 @@ struct s3c_rtc_drv_data {  /* I have yet to find an S3C implementation with more than one   * of these rtc blocks in */ -static struct resource *s3c_rtc_mem; -  static struct clk *rtc_clk;  static void __iomem *s3c_rtc_base;  static int s3c_rtc_alarmno = NO_IRQ; @@ -117,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; @@ -186,7 +184,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  	rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);  	rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC); -	/* the only way to work out wether the system was mid-update +	/* the only way to work out whether the system was mid-update  	 * when we read it is to check the second counter, and if it  	 * is zero, then we re-try the entire read  	 */ @@ -205,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); @@ -220,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); @@ -261,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); @@ -312,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); @@ -335,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); @@ -423,25 +421,17 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)  	clk_disable(rtc_clk);  } -static int __devexit s3c_rtc_remove(struct platform_device *dev) +static int s3c_rtc_remove(struct platform_device *dev)  {  	struct rtc_device *rtc = platform_get_drvdata(dev); -	free_irq(s3c_rtc_alarmno, rtc); -	free_irq(s3c_rtc_tickno, rtc); -  	platform_set_drvdata(dev, NULL);  	rtc_device_unregister(rtc);  	s3c_rtc_setaie(&dev->dev, 0); -	clk_put(rtc_clk);  	rtc_clk = NULL; -	iounmap(s3c_rtc_base); -	release_resource(s3c_rtc_mem); -	kfree(s3c_rtc_mem); -  	return 0;  } @@ -461,7 +451,7 @@ static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)  	return platform_get_device_id(pdev)->driver_data;  } -static int __devinit s3c_rtc_probe(struct platform_device *pdev) +static int s3c_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	struct rtc_time rtc_tm; @@ -469,7 +459,7 @@ static int __devinit 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 */ @@ -485,7 +475,7 @@ static int __devinit 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 */ @@ -496,28 +486,16 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)  		return -ENOENT;  	} -	s3c_rtc_mem = request_mem_region(res->start, resource_size(res), -					 pdev->name); - -	if (s3c_rtc_mem == NULL) { -		dev_err(&pdev->dev, "failed to reserve memory region\n"); -		ret = -ENOENT; -		goto err_nores; -	} - -	s3c_rtc_base = ioremap(res->start, resource_size(res)); -	if (s3c_rtc_base == NULL) { -		dev_err(&pdev->dev, "failed ioremap()\n"); -		ret = -EINVAL; -		goto err_nomap; -	} +	s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(s3c_rtc_base)) +		return PTR_ERR(s3c_rtc_base); -	rtc_clk = clk_get(&pdev->dev, "rtc"); +	rtc_clk = devm_clk_get(&pdev->dev, "rtc");  	if (IS_ERR(rtc_clk)) {  		dev_err(&pdev->dev, "failed to find rtc clock source\n");  		ret = PTR_ERR(rtc_clk);  		rtc_clk = NULL; -		goto err_clk; +		return ret;  	}  	clk_enable(rtc_clk); @@ -526,7 +504,7 @@ static int __devinit 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); @@ -576,28 +554,24 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)  	s3c_rtc_setfreq(&pdev->dev, 1); -	ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, +	ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq,  			  0,  "s3c2410-rtc alarm", rtc);  	if (ret) {  		dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);  		goto err_alarm_irq;  	} -	ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, +	ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq,  			  0,  "s3c2410-rtc tick", rtc);  	if (ret) {  		dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); -		free_irq(s3c_rtc_alarmno, rtc); -		goto err_tick_irq; +		goto err_alarm_irq;  	}  	clk_disable(rtc_clk);  	return 0; - err_tick_irq: -	free_irq(s3c_rtc_alarmno, rtc); -   err_alarm_irq:  	platform_set_drvdata(pdev, NULL);  	rtc_device_unregister(rtc); @@ -605,15 +579,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)   err_nortc:  	s3c_rtc_enable(pdev, 0);  	clk_disable(rtc_clk); -	clk_put(rtc_clk); - err_clk: -	iounmap(s3c_rtc_base); - - err_nomap: -	release_resource(s3c_rtc_mem); - - err_nores:  	return ret;  } @@ -695,8 +661,6 @@ static const struct of_device_id s3c_rtc_dt_match[] = {  	{},  };  MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); -#else -#define s3c_rtc_dt_match NULL  #endif  static struct platform_device_id s3c_rtc_driver_ids[] = { @@ -720,14 +684,14 @@ MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);  static struct platform_driver s3c_rtc_driver = {  	.probe		= s3c_rtc_probe, -	.remove		= __devexit_p(s3c_rtc_remove), +	.remove		= s3c_rtc_remove,  	.suspend	= s3c_rtc_suspend,  	.resume		= s3c_rtc_resume,  	.id_table	= s3c_rtc_driver_ids,  	.driver		= {  		.name	= "s3c-rtc",  		.owner	= THIS_MODULE, -		.of_match_table	= s3c_rtc_dt_match, +		.of_match_table	= of_match_ptr(s3c_rtc_dt_match),  	},  }; diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 50a5c4adee4..5ec5036df0b 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 3c0da333f46..f7d90703db5 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -241,7 +241,7 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)  	return events ? IRQ_HANDLED : IRQ_NONE;  } -static int __devinit snvs_rtc_probe(struct platform_device *pdev) +static int snvs_rtc_probe(struct platform_device *pdev)  {  	struct snvs_rtc_data *data;  	struct resource *res; @@ -252,9 +252,9 @@ static int __devinit 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) @@ -294,7 +294,7 @@ static int __devinit snvs_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit snvs_rtc_remove(struct platform_device *pdev) +static int snvs_rtc_remove(struct platform_device *pdev)  {  	struct snvs_rtc_data *data = platform_get_drvdata(pdev); @@ -327,7 +327,7 @@ static int snvs_rtc_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume); -static const struct of_device_id __devinitconst snvs_dt_ids[] = { +static const struct of_device_id snvs_dt_ids[] = {  	{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },  	{ /* sentinel */ }  }; @@ -338,10 +338,10 @@ 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		= __devexit_p(snvs_rtc_remove), +	.remove		= snvs_rtc_remove,  };  module_platform_driver(snvs_rtc_driver); diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index bb507d23f6c..a18c3192ed4 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -351,7 +351,7 @@ static struct rtc_class_ops spear_rtc_ops = {  	.alarm_irq_enable = spear_alarm_irq_enable,  }; -static int __devinit spear_rtc_probe(struct platform_device *pdev) +static int spear_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct spear_rtc_config *config; @@ -363,35 +363,40 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)  		dev_err(&pdev->dev, "no resource defined\n");  		return -EBUSY;  	} -	if (!request_mem_region(res->start, resource_size(res), pdev->name)) { -		dev_err(&pdev->dev, "rtc region already claimed\n"); -		return -EBUSY; -	} -	config = kzalloc(sizeof(*config), GFP_KERNEL); +	config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);  	if (!config) {  		dev_err(&pdev->dev, "out of memory\n"); -		status = -ENOMEM; -		goto err_release_region; +		return -ENOMEM;  	} -	config->clk = clk_get(&pdev->dev, NULL); -	if (IS_ERR(config->clk)) { -		status = PTR_ERR(config->clk); -		goto err_kfree; +	/* alarm irqs */ +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) { +		dev_err(&pdev->dev, "no update irq?\n"); +		return irq;  	} -	status = clk_enable(config->clk); -	if (status < 0) -		goto err_clk_put; - -	config->ioaddr = ioremap(res->start, resource_size(res)); -	if (!config->ioaddr) { -		dev_err(&pdev->dev, "ioremap fail\n"); -		status = -ENOMEM; -		goto err_disable_clock; +	status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name, +			config); +	if (status) { +		dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n", +				irq); +		return status;  	} +	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)) +		return PTR_ERR(config->clk); + +	status = clk_prepare_enable(config->clk); +	if (status < 0) +		return status; +  	spin_lock_init(&config->lock);  	platform_set_drvdata(pdev, config); @@ -401,67 +406,31 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)  		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",  				PTR_ERR(config->rtc));  		status = PTR_ERR(config->rtc); -		goto err_iounmap; -	} - -	/* alarm irqs */ -	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "no update irq?\n"); -		status = irq; -		goto err_clear_platdata; +		goto err_disable_clock;  	} -	status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config); -	if (status) { -		dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ -				claimed\n", irq); -		goto err_clear_platdata; -	} +	config->rtc->uie_unsupported = 1;  	if (!device_can_wakeup(&pdev->dev))  		device_init_wakeup(&pdev->dev, 1);  	return 0; -err_clear_platdata: -	platform_set_drvdata(pdev, NULL); -	rtc_device_unregister(config->rtc); -err_iounmap: -	iounmap(config->ioaddr);  err_disable_clock: -	clk_disable(config->clk); -err_clk_put: -	clk_put(config->clk); -err_kfree: -	kfree(config); -err_release_region: -	release_mem_region(res->start, resource_size(res)); +	platform_set_drvdata(pdev, NULL); +	clk_disable_unprepare(config->clk);  	return status;  } -static int __devexit spear_rtc_remove(struct platform_device *pdev) +static int spear_rtc_remove(struct platform_device *pdev)  {  	struct spear_rtc_config *config = platform_get_drvdata(pdev); -	int irq; -	struct resource *res; -	/* leave rtc running, but disable irqs */ +	rtc_device_unregister(config->rtc);  	spear_rtc_disable_interrupt(config); +	clk_disable_unprepare(config->clk);  	device_init_wakeup(&pdev->dev, 0); -	irq = platform_get_irq(pdev, 0); -	if (irq) -		free_irq(irq, pdev); -	clk_disable(config->clk); -	clk_put(config->clk); -	iounmap(config->ioaddr); -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (res) -		release_mem_region(res->start, resource_size(res)); -	platform_set_drvdata(pdev, NULL); -	rtc_device_unregister(config->rtc); -	kfree(config);  	return 0;  } @@ -528,7 +497,7 @@ MODULE_DEVICE_TABLE(of, spear_rtc_id_table);  static struct platform_driver spear_rtc_driver = {  	.probe = spear_rtc_probe, -	.remove = __devexit_p(spear_rtc_remove), +	.remove = spear_rtc_remove,  	.suspend = spear_rtc_suspend,  	.resume = spear_rtc_resume,  	.shutdown = spear_rtc_shutdown, diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 279f5cfa691..7e4a6f65cb9 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -285,7 +285,7 @@ static struct bin_attribute stk17ta8_nvram_attr = {  	.write = stk17ta8_nvram_write,  }; -static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) +static int stk17ta8_rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	unsigned int cal; @@ -347,7 +347,7 @@ static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev) +static int stk17ta8_rtc_remove(struct platform_device *pdev)  {  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev); @@ -363,7 +363,7 @@ MODULE_ALIAS("platform:stk17ta8");  static struct platform_driver stk17ta8_rtc_driver = {  	.probe		= stk17ta8_rtc_probe, -	.remove		= __devexit_p(stk17ta8_rtc_remove), +	.remove		= stk17ta8_rtc_remove,  	.driver		= {  		.name	= "stk17ta8",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 739ef55694f..98f0d3c3073 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -26,6 +26,9 @@  #include <linux/rtc.h>  #include <linux/slab.h>  #include <linux/of_device.h> +#include <linux/of.h> +#include <linux/stmp_device.h> +#include <linux/stmp3xxx_rtc_wdt.h>  #include <mach/common.h> @@ -35,6 +38,7 @@  #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN		0x00000001  #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002  #define STMP3XXX_RTC_CTRL_ALARM_IRQ		0x00000004 +#define STMP3XXX_RTC_CTRL_WATCHDOGEN		0x00000010  #define STMP3XXX_RTC_STAT			0x10  #define STMP3XXX_RTC_STAT_STALE_SHIFT		16 @@ -44,6 +48,8 @@  #define STMP3XXX_RTC_ALARM			0x40 +#define STMP3XXX_RTC_WATCHDOG			0x50 +  #define STMP3XXX_RTC_PERSISTENT0		0x60  #define STMP3XXX_RTC_PERSISTENT0_SET		0x64  #define STMP3XXX_RTC_PERSISTENT0_CLR		0x68 @@ -51,12 +57,70 @@  #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN	0x00000004  #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE	0x00000080 +#define STMP3XXX_RTC_PERSISTENT1		0x70 +/* missing bitmask in headers */ +#define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000 +  struct stmp3xxx_rtc_data {  	struct rtc_device *rtc;  	void __iomem *io;  	int irq_alarm;  }; +#if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG) +/** + * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC + * @dev: the parent device of the watchdog (= the RTC) + * @timeout: the desired value for the timeout register of the watchdog. + *           0 disables the watchdog + * + * The watchdog needs one register and two bits which are in the RTC domain. + * To handle the resource conflict, the RTC driver will create another + * platform_device for the watchdog driver as a child of the RTC device. + * The watchdog driver is passed the below accessor function via platform_data + * to configure the watchdog. Locking is not needed because accessing SET/CLR + * registers is atomic. + */ + +static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) +{ +	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); + +	if (timeout) { +		writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG); +		writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, +		       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); +		writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, +		       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET); +	} else { +		writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, +		       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); +		writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, +		       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR); +	} +} + +static struct stmp3xxx_wdt_pdata wdt_pdata = { +	.wdt_set_timeout = stmp3xxx_wdt_set_timeout, +}; + +static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) +{ +	struct platform_device *wdt_pdev = +		platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); + +	if (wdt_pdev) { +		wdt_pdev->dev.parent = &rtc_pdev->dev; +		wdt_pdev->dev.platform_data = &wdt_pdata; +		platform_device_add(wdt_pdev); +	} +} +#else +static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) +{ +} +#endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */ +  static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)  {  	/* @@ -232,6 +296,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)  		goto out_irq_alarm;  	} +	stmp3xxx_wdt_register(pdev);  	return 0;  out_irq_alarm: @@ -280,7 +345,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 5b2261052a6..59b5c2dcb58 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c @@ -3,6 +3,8 @@   * Copyright (C) 2008 David S. Miller <davem@davemloft.net>   */ +#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 c006025cecc..7c033756d6b 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -303,7 +303,13 @@ static struct rtc_class_ops tegra_rtc_ops = {  	.alarm_irq_enable = tegra_rtc_alarm_irq_enable,  }; -static int __devinit tegra_rtc_probe(struct platform_device *pdev) +static const struct of_device_id tegra_rtc_dt_match[] = { +	{ .compatible = "nvidia,tegra20-rtc", }, +	{} +}; +MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match); + +static int tegra_rtc_probe(struct platform_device *pdev)  {  	struct tegra_rtc_info *info;  	struct resource *res; @@ -321,11 +327,9 @@ static int __devinit 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) @@ -375,7 +379,7 @@ err_dev_unreg:  	return ret;  } -static int __devexit tegra_rtc_remove(struct platform_device *pdev) +static int tegra_rtc_remove(struct platform_device *pdev)  {  	struct tegra_rtc_info *info = platform_get_drvdata(pdev); @@ -435,11 +439,12 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)  MODULE_ALIAS("platform:tegra_rtc");  static struct platform_driver tegra_rtc_driver = { -	.remove		= __devexit_p(tegra_rtc_remove), +	.remove		= tegra_rtc_remove,  	.shutdown	= tegra_rtc_shutdown,  	.driver		= {  		.name	= "tegra_rtc",  		.owner	= THIS_MODULE, +		.of_match_table = tegra_rtc_dt_match,  	},  #ifdef CONFIG_PM  	.suspend	= tegra_rtc_suspend, diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 7e96254bd36..b92e0f6383e 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -119,7 +119,7 @@ err:  	return err;  } -static int __devexit test_remove(struct platform_device *plat_dev) +static int test_remove(struct platform_device *plat_dev)  {  	struct rtc_device *rtc = platform_get_drvdata(plat_dev); @@ -131,7 +131,7 @@ static int __devexit test_remove(struct platform_device *plat_dev)  static struct platform_driver test_driver = {  	.probe	= test_probe, -	.remove = __devexit_p(test_remove), +	.remove = test_remove,  	.driver = {  		.name = "rtc-test",  		.owner = THIS_MODULE, @@ -152,24 +152,24 @@ static int __init test_init(void)  	if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {  		err = -ENOMEM; -		goto exit_free_test0; +		goto exit_put_test0;  	}  	if ((err = platform_device_add(test0))) -		goto exit_free_test1; +		goto exit_put_test1;  	if ((err = platform_device_add(test1))) -		goto exit_device_unregister; +		goto exit_del_test0;  	return 0; -exit_device_unregister: -	platform_device_unregister(test0); +exit_del_test0: +	platform_device_del(test0); -exit_free_test1: +exit_put_test1:  	platform_device_put(test1); -exit_free_test0: +exit_put_test0:  	platform_device_put(test0);  exit_driver_unregister: diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c index eb65dafee66..62db4841078 100644 --- a/drivers/rtc/rtc-tile.c +++ b/drivers/rtc/rtc-tile.c @@ -76,7 +76,7 @@ static const struct rtc_class_ops tile_rtc_ops = {  /*   * Device probe routine.   */ -static int __devinit tile_rtc_probe(struct platform_device *dev) +static int tile_rtc_probe(struct platform_device *dev)  {  	struct rtc_device *rtc; @@ -94,7 +94,7 @@ static int __devinit tile_rtc_probe(struct platform_device *dev)  /*   * Device cleanup routine.   */ -static int __devexit tile_rtc_remove(struct platform_device *dev) +static int tile_rtc_remove(struct platform_device *dev)  {  	struct rtc_device *rtc = platform_get_drvdata(dev); @@ -112,7 +112,7 @@ static struct platform_driver tile_rtc_platform_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= tile_rtc_probe, -	.remove		= __devexit_p(tile_rtc_remove), +	.remove		= tile_rtc_remove,  };  /* diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c new file mode 100644 index 00000000000..aab4e8c9362 --- /dev/null +++ b/drivers/rtc/rtc-tps6586x.c @@ -0,0 +1,356 @@ +/* + * rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan <ldewangan@nvidia.com> + * + * 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/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mfd/tps6586x.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/rtc.h> +#include <linux/slab.h> + +#define RTC_CTRL			0xc0 +#define POR_RESET_N			BIT(7) +#define OSC_SRC_SEL			BIT(6) +#define RTC_ENABLE			BIT(5)	/* enables alarm */ +#define RTC_BUF_ENABLE			BIT(4)	/* 32 KHz buffer enable */ +#define PRE_BYPASS			BIT(3)	/* 0=1KHz or 1=32KHz updates */ +#define CL_SEL_MASK			(BIT(2)|BIT(1)) +#define CL_SEL_POS			1 +#define RTC_ALARM1_HI			0xc1 +#define RTC_COUNT4			0xc6 + +/* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */ +#define RTC_COUNT4_DUMMYREAD		0xc5 + +/*only 14-bits width in second*/ +#define ALM1_VALID_RANGE_IN_SEC		0x3FFF + +#define TPS6586X_RTC_CL_SEL_1_5PF	0x0 +#define TPS6586X_RTC_CL_SEL_6_5PF	0x1 +#define TPS6586X_RTC_CL_SEL_7_5PF	0x2 +#define TPS6586X_RTC_CL_SEL_12_5PF	0x3 + +struct tps6586x_rtc { +	struct device		*dev; +	struct rtc_device	*rtc; +	int			irq; +	bool			irq_en; +	unsigned long long	epoch_start; +}; + +static inline struct device *to_tps6586x_dev(struct device *dev) +{ +	return dev->parent; +} + +static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); +	struct device *tps_dev = to_tps6586x_dev(dev); +	unsigned long long ticks = 0; +	unsigned long seconds; +	u8 buff[6]; +	int ret; +	int i; + +	ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(buff), buff); +	if (ret < 0) { +		dev_err(dev, "read counter failed with err %d\n", ret); +		return ret; +	} + +	for (i = 1; i < sizeof(buff); i++) { +		ticks <<= 8; +		ticks |= buff[i]; +	} + +	seconds = ticks >> 10; +	seconds += rtc->epoch_start; +	rtc_time_to_tm(seconds, tm); +	return rtc_valid_tm(tm); +} + +static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); +	struct device *tps_dev = to_tps6586x_dev(dev); +	unsigned long long ticks; +	unsigned long seconds; +	u8 buff[5]; +	int ret; + +	rtc_tm_to_time(tm, &seconds); +	if (seconds < rtc->epoch_start) { +		dev_err(dev, "requested time unsupported\n"); +		return -EINVAL; +	} +	seconds -= rtc->epoch_start; + +	ticks = (unsigned long long)seconds << 10; +	buff[0] = (ticks >> 32) & 0xff; +	buff[1] = (ticks >> 24) & 0xff; +	buff[2] = (ticks >> 16) & 0xff; +	buff[3] = (ticks >> 8) & 0xff; +	buff[4] = ticks & 0xff; + +	/* Disable RTC before changing time */ +	ret = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE); +	if (ret < 0) { +		dev_err(dev, "failed to clear RTC_ENABLE\n"); +		return ret; +	} + +	ret = tps6586x_writes(tps_dev, RTC_COUNT4, sizeof(buff), buff); +	if (ret < 0) { +		dev_err(dev, "failed to program new time\n"); +		return ret; +	} + +	/* Enable RTC */ +	ret = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE); +	if (ret < 0) { +		dev_err(dev, "failed to set RTC_ENABLE\n"); +		return ret; +	} +	return 0; +} + +static int tps6586x_rtc_alarm_irq_enable(struct device *dev, +			 unsigned int enabled) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); + +	if (enabled && !rtc->irq_en) { +		enable_irq(rtc->irq); +		rtc->irq_en = true; +	} else if (!enabled && rtc->irq_en)  { +		disable_irq(rtc->irq); +		rtc->irq_en = false; +	} +	return 0; +} + +static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); +	struct device *tps_dev = to_tps6586x_dev(dev); +	unsigned long seconds; +	unsigned long ticks; +	unsigned long rtc_current_time; +	unsigned long long rticks = 0; +	u8 buff[3]; +	u8 rbuff[6]; +	int ret; +	int i; + +	rtc_tm_to_time(&alrm->time, &seconds); + +	if (alrm->enabled && (seconds < rtc->epoch_start)) { +		dev_err(dev, "can't set alarm to requested time\n"); +		return -EINVAL; +	} + +	ret = tps6586x_rtc_alarm_irq_enable(dev, alrm->enabled); +	if (ret < 0) { +		dev_err(dev, "can't set alarm irq, err %d\n", ret); +		return ret; +	} + +	seconds -= rtc->epoch_start; +	ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, +			sizeof(rbuff), rbuff); +	if (ret < 0) { +		dev_err(dev, "read counter failed with err %d\n", ret); +		return ret; +	} + +	for (i = 1; i < sizeof(rbuff); i++) { +		rticks <<= 8; +		rticks |= rbuff[i]; +	} + +	rtc_current_time = rticks >> 10; +	if ((seconds - rtc_current_time) > ALM1_VALID_RANGE_IN_SEC) +		seconds = rtc_current_time - 1; + +	ticks = (unsigned long long)seconds << 10; +	buff[0] = (ticks >> 16) & 0xff; +	buff[1] = (ticks >> 8) & 0xff; +	buff[2] = ticks & 0xff; + +	ret = tps6586x_writes(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff); +	if (ret) +		dev_err(dev, "programming alarm failed with err %d\n", ret); + +	return ret; +} + +static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); +	struct device *tps_dev = to_tps6586x_dev(dev); +	unsigned long ticks; +	unsigned long seconds; +	u8 buff[3]; +	int ret; + +	ret = tps6586x_reads(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff); +	if (ret) { +		dev_err(dev, "read RTC_ALARM1_HI failed with err %d\n", ret); +		return ret; +	} + +	ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2]; +	seconds = ticks >> 10; +	seconds += rtc->epoch_start; + +	rtc_time_to_tm(seconds, &alrm->time); +	return 0; +} + +static const struct rtc_class_ops tps6586x_rtc_ops = { +	.read_time	= tps6586x_rtc_read_time, +	.set_time	= tps6586x_rtc_set_time, +	.set_alarm	= tps6586x_rtc_set_alarm, +	.read_alarm	= tps6586x_rtc_read_alarm, +	.alarm_irq_enable = tps6586x_rtc_alarm_irq_enable, +}; + +static irqreturn_t tps6586x_rtc_irq(int irq, void *data) +{ +	struct tps6586x_rtc *rtc = data; + +	rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); +	return IRQ_HANDLED; +} + +static int tps6586x_rtc_probe(struct platform_device *pdev) +{ +	struct device *tps_dev = to_tps6586x_dev(&pdev->dev); +	struct tps6586x_rtc *rtc; +	int ret; + +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); +	if (!rtc) +		return -ENOMEM; + +	rtc->dev = &pdev->dev; +	rtc->irq = platform_get_irq(pdev, 0); + +	/* Set epoch start as 00:00:00:01:01:2009 */ +	rtc->epoch_start = mktime(2009, 1, 1, 0, 0, 0); + +	/* 1 kHz tick mode, enable tick counting */ +	ret = tps6586x_update(tps_dev, RTC_CTRL, +		RTC_ENABLE | OSC_SRC_SEL | +		((TPS6586X_RTC_CL_SEL_1_5PF << CL_SEL_POS) & CL_SEL_MASK), +		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); +	if (ret < 0) { +		dev_err(&pdev->dev, "unable to start counter\n"); +		return ret; +	} + +	platform_set_drvdata(pdev, rtc); +	rtc->rtc = rtc_device_register(dev_name(&pdev->dev), &pdev->dev, +				       &tps6586x_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc->rtc)) { +		ret = PTR_ERR(rtc->rtc); +		dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); +		goto fail_rtc_register; +	} + +	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) { +		dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n", +				rtc->irq, ret); +		goto fail_req_irq; +	} +	disable_irq(rtc->irq); +	device_set_wakeup_capable(&pdev->dev, 1); +	return 0; + +fail_req_irq: +	rtc_device_unregister(rtc->rtc); + +fail_rtc_register: +	tps6586x_update(tps_dev, RTC_CTRL, 0, +		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); +	return ret; +}; + +static int tps6586x_rtc_remove(struct platform_device *pdev) +{ +	struct tps6586x_rtc *rtc = platform_get_drvdata(pdev); +	struct device *tps_dev = to_tps6586x_dev(&pdev->dev); + +	tps6586x_update(tps_dev, RTC_CTRL, 0, +		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); +	rtc_device_unregister(rtc->rtc); +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tps6586x_rtc_suspend(struct device *dev) +{ +	struct tps6586x_rtc *rtc = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		enable_irq_wake(rtc->irq); +	return 0; +} + +static int tps6586x_rtc_resume(struct device *dev) +{ +	struct tps6586x_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 tps6586x_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(tps6586x_rtc_suspend, tps6586x_rtc_resume) +}; + +static struct platform_driver tps6586x_rtc_driver = { +	.driver	= { +		.name	= "tps6586x-rtc", +		.owner	= THIS_MODULE, +		.pm	= &tps6586x_pm_ops, +	}, +	.probe	= tps6586x_rtc_probe, +	.remove	= tps6586x_rtc_remove, +}; +module_platform_driver(tps6586x_rtc_driver); + +MODULE_ALIAS("platform:rtc-tps6586x"); +MODULE_DESCRIPTION("TI TPS6586x RTC driver"); +MODULE_AUTHOR("Laxman dewangan <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 7a82337e4de..8bd8115329b 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*/ @@ -222,7 +222,7 @@ static const struct rtc_class_ops tps65910_rtc_ops = {  	.alarm_irq_enable = tps65910_rtc_alarm_irq_enable,  }; -static int __devinit tps65910_rtc_probe(struct platform_device *pdev) +static int tps65910_rtc_probe(struct platform_device *pdev)  {  	struct tps65910 *tps65910 = NULL;  	struct tps65910_rtc *tps_rtc = NULL; @@ -247,6 +247,13 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)  		return ret;  	dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); + +	/* Enable RTC digital power domain */ +	ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, +		DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); +	if (ret < 0) +		return ret; +  	rtc_reg = TPS65910_RTC_CTRL_STOP_RTC;  	ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg);  	if (ret < 0) @@ -260,13 +267,14 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)  	}  	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, -		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, -		"rtc-tps65910", &pdev->dev); +		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); @@ -285,61 +293,48 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)   * Disable tps65910 RTC interrupts.   * Sets status flag to free.   */ -static int __devexit tps65910_rtc_remove(struct platform_device *pdev) +static int tps65910_rtc_remove(struct platform_device *pdev)  {  	/* leave rtc running, but disable irqs */ -	struct rtc_device *rtc = platform_get_drvdata(pdev); +	struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev); -	tps65910_rtc_alarm_irq_enable(&rtc->dev, 0); +	tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); -	rtc_device_unregister(rtc); +	rtc_device_unregister(tps_rtc->rtc);  	return 0;  }  #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		= __devexit_p(tps65910_rtc_remove), +	.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 00000000000..9aaf8aaebae --- /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 <ldewangan@nvidia.com> + * + * 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 <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 9277d945bf4..8bc6c80b184 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> @@ -233,7 +234,7 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)   */  static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)  { -	unsigned char rtc_data[ALL_TIME_REGS + 1]; +	unsigned char rtc_data[ALL_TIME_REGS];  	int ret;  	u8 save_control;  	u8 rtc_control; @@ -300,15 +301,15 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)  static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)  {  	unsigned char save_control; -	unsigned char rtc_data[ALL_TIME_REGS + 1]; +	unsigned char rtc_data[ALL_TIME_REGS];  	int ret; -	rtc_data[1] = bin2bcd(tm->tm_sec); -	rtc_data[2] = bin2bcd(tm->tm_min); -	rtc_data[3] = bin2bcd(tm->tm_hour); -	rtc_data[4] = bin2bcd(tm->tm_mday); -	rtc_data[5] = bin2bcd(tm->tm_mon + 1); -	rtc_data[6] = bin2bcd(tm->tm_year - 100); +	rtc_data[0] = bin2bcd(tm->tm_sec); +	rtc_data[1] = bin2bcd(tm->tm_min); +	rtc_data[2] = bin2bcd(tm->tm_hour); +	rtc_data[3] = bin2bcd(tm->tm_mday); +	rtc_data[4] = bin2bcd(tm->tm_mon + 1); +	rtc_data[5] = bin2bcd(tm->tm_year - 100);  	/* Stop RTC while updating the TC registers */  	ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); @@ -341,7 +342,7 @@ out:   */  static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  { -	unsigned char rtc_data[ALL_TIME_REGS + 1]; +	unsigned char rtc_data[ALL_TIME_REGS];  	int ret;  	ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, @@ -368,19 +369,19 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)  { -	unsigned char alarm_data[ALL_TIME_REGS + 1]; +	unsigned char alarm_data[ALL_TIME_REGS];  	int ret;  	ret = twl_rtc_alarm_irq_enable(dev, 0);  	if (ret)  		goto out; -	alarm_data[1] = bin2bcd(alm->time.tm_sec); -	alarm_data[2] = bin2bcd(alm->time.tm_min); -	alarm_data[3] = bin2bcd(alm->time.tm_hour); -	alarm_data[4] = bin2bcd(alm->time.tm_mday); -	alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); -	alarm_data[6] = bin2bcd(alm->time.tm_year - 100); +	alarm_data[0] = bin2bcd(alm->time.tm_sec); +	alarm_data[1] = bin2bcd(alm->time.tm_min); +	alarm_data[2] = bin2bcd(alm->time.tm_hour); +	alarm_data[3] = bin2bcd(alm->time.tm_mday); +	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); +	alarm_data[5] = bin2bcd(alm->time.tm_year - 100);  	/* update all the alarm registers in one shot */  	ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, @@ -458,7 +459,7 @@ static struct rtc_class_ops twl_rtc_ops = {  /*----------------------------------------------------------------------*/ -static int __devinit twl_rtc_probe(struct platform_device *pdev) +static int twl_rtc_probe(struct platform_device *pdev)  {  	struct rtc_device *rtc;  	int ret = -EINVAL; @@ -535,7 +536,7 @@ out1:   * Disable all TWL RTC module interrupts.   * Sets status flag to free.   */ -static int __devexit twl_rtc_remove(struct platform_device *pdev) +static int twl_rtc_remove(struct platform_device *pdev)  {  	/* leave rtc running, but disable irqs */  	struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -588,23 +589,26 @@ 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 = {  	.probe		= twl_rtc_probe, -	.remove		= __devexit_p(twl_rtc_remove), +	.remove		= twl_rtc_remove,  	.shutdown	= twl_rtc_shutdown,  	.suspend	= twl_rtc_suspend,  	.resume		= twl_rtc_resume,  	.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 5f60a7c6a15..f91be04b905 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -280,7 +280,7 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {  	.set_alarm	= vr41xx_rtc_set_alarm,  }; -static int __devinit rtc_probe(struct platform_device *pdev) +static int rtc_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct rtc_device *rtc; @@ -352,7 +352,7 @@ static int __devinit 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; @@ -373,7 +373,7 @@ err_rtc1_iounmap:  	return retval;  } -static int __devexit rtc_remove(struct platform_device *pdev) +static int rtc_remove(struct platform_device *pdev)  {  	struct rtc_device *rtc; @@ -398,7 +398,7 @@ MODULE_ALIAS("platform:RTC");  static struct platform_driver rtc_platform_driver = {  	.probe		= rtc_probe, -	.remove		= __devexit_p(rtc_remove), +	.remove		= rtc_remove,  	.driver		= {  		.name	= rtc_name,  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 07bf19364a7..a000bc0a8bf 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -70,7 +70,7 @@  				| ALARM_SEC_BIT)  #define VT8500_RTC_CR_ENABLE	(1 << 0)	/* Enable RTC */ -#define VT8500_RTC_CR_24H	(1 << 1)	/* 24h time format */ +#define VT8500_RTC_CR_12H	(1 << 1)	/* 12h time format */  #define VT8500_RTC_CR_SM_ENABLE	(1 << 2)	/* Enable periodic irqs */  #define VT8500_RTC_CR_SM_SEC	(1 << 3)	/* 0: 1Hz/60, 1: 1Hz */  #define VT8500_RTC_CR_CALIB	(1 << 4)	/* Enable calibration */ @@ -119,7 +119,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm)  	tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);  	tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);  	tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); -	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); +	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1;  	tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S)  			+ ((date >> DATE_CENTURY_S) & 1 ? 200 : 100);  	tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; @@ -137,9 +137,10 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)  		return -EINVAL;  	} -	writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) -		| (bin2bcd(tm->tm_mon) << DATE_MONTH_S) -		| (bin2bcd(tm->tm_mday)), +	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),  		vt8500_rtc->regbase + VT8500_RTC_DS);  	writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)  		| (bin2bcd(tm->tm_hour) << TIME_HOUR_S) @@ -205,12 +206,13 @@ static const struct rtc_class_ops vt8500_rtc_ops = {  	.alarm_irq_enable = vt8500_alarm_irq_enable,  }; -static int __devinit vt8500_rtc_probe(struct platform_device *pdev) +static int vt8500_rtc_probe(struct platform_device *pdev)  {  	struct vt8500_rtc *vt8500_rtc;  	int ret; -	vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL); +	vt8500_rtc = devm_kzalloc(&pdev->dev, +			   sizeof(struct vt8500_rtc), GFP_KERNEL);  	if (!vt8500_rtc)  		return -ENOMEM; @@ -220,36 +222,34 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)  	vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!vt8500_rtc->res) {  		dev_err(&pdev->dev, "No I/O memory resource defined\n"); -		ret = -ENXIO; -		goto err_free; +		return -ENXIO;  	}  	vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);  	if (vt8500_rtc->irq_alarm < 0) {  		dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); -		ret = -ENXIO; -		goto err_free; +		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"); -		ret = -EBUSY; -		goto err_free; +		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 */ -	writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H, +	writel(VT8500_RTC_CR_ENABLE,  	       vt8500_rtc->regbase + VT8500_RTC_CR);  	vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, @@ -258,11 +258,11 @@ static int __devinit 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); @@ -273,31 +273,19 @@ static int __devinit 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_free: -	kfree(vt8500_rtc); +err_return:  	return ret;  } -static int __devexit vt8500_rtc_remove(struct platform_device *pdev) +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)); -	kfree(vt8500_rtc);  	platform_set_drvdata(pdev, NULL);  	return 0; @@ -310,7 +298,7 @@ static const struct of_device_id wmt_dt_ids[] = {  static struct platform_driver vt8500_rtc_driver = {  	.probe		= vt8500_rtc_probe, -	.remove		= __devexit_p(vt8500_rtc_remove), +	.remove		= vt8500_rtc_remove,  	.driver		= {  		.name	= "vt8500-rtc",  		.owner	= THIS_MODULE, diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index ea5c6f857ca..2f0ac7b30a0 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); @@ -459,12 +460,10 @@ err:  	return ret;  } -static int __devexit wm831x_rtc_remove(struct platform_device *pdev) +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; @@ -483,7 +482,7 @@ static const struct dev_pm_ops wm831x_rtc_pm_ops = {  static struct platform_driver wm831x_rtc_driver = {  	.probe = wm831x_rtc_probe, -	.remove = __devexit_p(wm831x_rtc_remove), +	.remove = wm831x_rtc_remove,  	.driver = {  		.name = "wm831x-rtc",  		.pm = &wm831x_rtc_pm_ops, diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c2e52d15abb..8ad86ae0d30 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -459,7 +459,7 @@ static int wm8350_rtc_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit wm8350_rtc_remove(struct platform_device *pdev) +static int wm8350_rtc_remove(struct platform_device *pdev)  {  	struct wm8350 *wm8350 = platform_get_drvdata(pdev);  	struct wm8350_rtc *wm_rtc = &wm8350->rtc; @@ -479,7 +479,7 @@ static struct dev_pm_ops wm8350_rtc_pm_ops = {  static struct platform_driver wm8350_rtc_driver = {  	.probe = wm8350_rtc_probe, -	.remove = __devexit_p(wm8350_rtc_remove), +	.remove = wm8350_rtc_remove,  	.driver = {  		.name = "wm8350-rtc",  		.pm = &wm8350_rtc_pm_ops, diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c new file mode 100644 index 00000000000..bf3e242ccc5 --- /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; +}  |