diff options
Diffstat (limited to 'drivers/rtc')
61 files changed, 1142 insertions, 736 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e72f65b61176..1adf9f815652 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -373,6 +373,17 @@ config RTC_DRV_MAX77686  	  This driver can also be built as a module. If so, the module  	  will be called rtc-max77686. +config RTC_DRV_MESON_VRTC +	tristate "Amlogic Meson Virtual RTC" +	depends on ARCH_MESON || COMPILE_TEST +	default m if ARCH_MESON +	help +	  If you say yes here you will get support for the +	  Virtual RTC of Amlogic SoCs. + +	  This driver can also be built as a module. If so, the module +	  will be called rtc-meson-vrtc. +  config RTC_DRV_RK808  	tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"  	depends on MFD_RK808 @@ -500,6 +511,7 @@ config RTC_DRV_M41T80_WDT  	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.  config RTC_DRV_BD70528  	tristate "ROHM BD70528 PMIC RTC" +	depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)  	help  	  If you say Y here you will get support for the RTC  	  on ROHM BD70528 Power Management IC. @@ -874,9 +886,15 @@ config RTC_DRV_DS3232_HWMON  config RTC_DRV_PCF2127  	tristate "NXP PCF2127"  	depends on RTC_I2C_AND_SPI +	select WATCHDOG_CORE if WATCHDOG  	help  	  If you say yes here you get support for the NXP PCF2127/29 RTC -	  chips. +	  chips with integrated quartz crystal for industrial applications. +	  Both chips also have watchdog timer and tamper switch detection +	  features. + +	  PCF2127 has an additional feature of 512 bytes battery backed +	  memory that's accessible using nvmem interface.  	  This driver can also be built as a module. If so, the module  	  will be called rtc-pcf2127. @@ -1247,13 +1265,6 @@ config RTC_DRV_AB8500  	  Select this to enable the ST-Ericsson AB8500 power management IC RTC  	  support. This chip contains a battery- and capacitor-backed RTC. -config RTC_DRV_NUC900 -	tristate "NUC910/NUC920 RTC driver" -	depends on ARCH_W90X900 || COMPILE_TEST -	help -	  If you say yes here you get support for the RTC subsystem of the -	  NUC910/NUC920 used in embedded systems. -  config RTC_DRV_OPAL  	tristate "IBM OPAL RTC driver"  	depends on PPC_POWERNV @@ -1274,7 +1285,7 @@ config RTC_DRV_ZYNQMP  config RTC_DRV_CROS_EC  	tristate "Chrome OS EC RTC driver" -	depends on MFD_CROS_EC +	depends on CROS_EC  	help  	  If you say yes here you will get support for the  	  Chrome OS Embedded Controller's RTC. @@ -1323,6 +1334,21 @@ config RTC_DRV_IMXDI  	   This driver can also be built as a module, if so, the module  	   will be called "rtc-imxdi". +config RTC_DRV_FSL_FTM_ALARM +	tristate "Freescale FlexTimer alarm timer" +	depends on ARCH_LAYERSCAPE || SOC_LS1021A +	select FSL_RCPM +	default y +	help +	   For the FlexTimer in LS1012A, LS1021A, LS1028A, LS1043A, LS1046A, +	   LS1088A, LS208xA, we can use FTM as the wakeup source. + +	   Say y here to enable FTM alarm support. The FTM alarm provides +	   alarm functions for wakeup system from deep sleep. + +	   This driver can also be built as a module, if so, the module +	   will be called "rtc-fsl-ftm-alarm". +  config RTC_DRV_MESON  	tristate "Amlogic Meson RTC"  	depends on (ARM && ARCH_MESON) || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6b09c21dc1b6..4ac8f19fb631 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o  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_FSL_FTM_ALARM)	+= rtc-fsl-ftm-alarm.o  obj-$(CONFIG_RTC_DRV_FTRTC010)	+= rtc-ftrtc010.o  obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o  obj-$(CONFIG_RTC_DRV_GOLDFISH)	+= rtc-goldfish.o @@ -102,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_MAX8907)	+= rtc-max8907.o  obj-$(CONFIG_RTC_DRV_MAX8925)	+= rtc-max8925.o  obj-$(CONFIG_RTC_DRV_MAX8997)	+= rtc-max8997.o  obj-$(CONFIG_RTC_DRV_MAX8998)	+= rtc-max8998.o +obj-$(CONFIG_RTC_DRV_MESON_VRTC)+= rtc-meson-vrtc.o  obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o  obj-$(CONFIG_RTC_DRV_MCP795)	+= rtc-mcp795.o  obj-$(CONFIG_RTC_DRV_MESON)	+= rtc-meson.o @@ -113,7 +115,6 @@ obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o  obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o  obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o  obj-$(CONFIG_RTC_DRV_MXC_V2)	+= rtc-mxc_v2.o -obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o  obj-$(CONFIG_RTC_DRV_OPAL)	+= rtc-opal.o  obj-$(CONFIG_RTC_DRV_PALMAS)	+= rtc-palmas.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 0f492b0940b3..9458e6d6686a 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -346,8 +346,10 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)  	struct rtc_wkalrm alrm;  	int err; -	if (!rtc->ops) +	if (!rtc->ops) { +		dev_dbg(&rtc->dev, "no ops set\n");  		return -EINVAL; +	}  	rtc->owner = owner;  	rtc_device_get_offset(rtc); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 72b7ddc43116..c93ef33b01d3 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -663,21 +663,12 @@ void rtc_update_irq(struct rtc_device *rtc,  }  EXPORT_SYMBOL_GPL(rtc_update_irq); -static int __rtc_match(struct device *dev, const void *data) -{ -	const char *name = data; - -	if (strcmp(dev_name(dev), name) == 0) -		return 1; -	return 0; -} -  struct rtc_device *rtc_class_open(const char *name)  {  	struct device *dev;  	struct rtc_device *rtc = NULL; -	dev = class_find_device(rtc_class, NULL, name, __rtc_match); +	dev = class_find_device_by_name(rtc_class, name);  	if (dev)  		rtc = to_rtc_device(dev); diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index e4d5a19fd1c9..75779e8501a3 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -264,7 +264,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev)  		return -ENOMEM;  	info->irq = platform_get_irq(pdev, 0);  	if (info->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource!\n");  		ret = -EINVAL;  		goto out;  	} @@ -296,10 +295,9 @@ static int pm80x_rtc_probe(struct platform_device *pdev)  	info->rtc_dev->range_max = U32_MAX;  	ret = rtc_register_device(info->rtc_dev); -	if (ret) { -		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); +	if (ret)  		goto out_rtc; -	} +  	/*  	 * enable internal XO instead of internal 3.25MHz clock since it can  	 * free running in PMIC power-down state. diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 434285f495e0..4743b16a8d84 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -328,10 +328,8 @@ static int pm860x_rtc_probe(struct platform_device *pdev)  	if (!info)  		return -ENOMEM;  	info->irq = platform_get_irq(pdev, 0); -	if (info->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource!\n"); +	if (info->irq < 0)  		return info->irq; -	}  	info->chip = chip;  	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index e4f6e0061ccf..d690985caa4c 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -390,35 +390,31 @@ static int abeoz9_probe(struct i2c_client *client,  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |  				     I2C_FUNC_SMBUS_BYTE_DATA | -				     I2C_FUNC_SMBUS_I2C_BLOCK)) { -		ret = -ENODEV; -		goto err; -	} +				     I2C_FUNC_SMBUS_I2C_BLOCK)) +		return -ENODEV;  	regmap = devm_regmap_init_i2c(client, &abeoz9_rtc_regmap_config);  	if (IS_ERR(regmap)) {  		ret = PTR_ERR(regmap);  		dev_err(dev, "regmap allocation failed: %d\n", ret); -		goto err; +		return ret;  	}  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); -	if (!data) { -		ret = -ENOMEM; -		goto err; -	} +	if (!data) +		return -ENOMEM;  	data->regmap = regmap;  	dev_set_drvdata(dev, data);  	ret = abeoz9_rtc_setup(dev, client->dev.of_node);  	if (ret) -		goto err; +		return ret;  	data->rtc = devm_rtc_allocate_device(dev);  	ret = PTR_ERR_OR_ZERO(data->rtc);  	if (ret) -		goto err; +		return ret;  	data->rtc->ops = &rtc_ops;  	data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; @@ -426,14 +422,10 @@ static int abeoz9_probe(struct i2c_client *client,  	ret = rtc_register_device(data->rtc);  	if (ret) -		goto err; +		return ret;  	abeoz9_hwmon_register(dev, data);  	return 0; - -err: -	dev_err(dev, "unable to register RTC device (%d)\n", ret); -	return ret;  }  #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index 2e5a8b15b222..29223931aba7 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -578,10 +578,8 @@ static int ac100_rtc_probe(struct platform_device *pdev)  	chip->regmap = ac100->regmap;  	chip->irq = platform_get_irq(pdev, 0); -	if (chip->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource\n"); +	if (chip->irq < 0)  		return chip->irq; -	}  	chip->rtc = devm_rtc_allocate_device(&pdev->dev);  	if (IS_ERR(chip->rtc)) @@ -612,15 +610,7 @@ static int ac100_rtc_probe(struct platform_device *pdev)  	if (ret)  		return ret; -	ret = rtc_register_device(chip->rtc); -	if (ret) { -		dev_err(&pdev->dev, "unable to register device\n"); -		return ret; -	} - -	dev_info(&pdev->dev, "RTC enabled\n"); - -	return 0; +	return rtc_register_device(chip->rtc);  }  static int ac100_rtc_remove(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 19d6980e90fb..9351bd52477e 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -502,7 +502,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)  	struct resource *res;  	struct armada38x_rtc *rtc;  	const struct of_device_id *match; -	int ret;  	match = of_match_device(armada38x_rtc_of_match_table, &pdev->dev);  	if (!match) @@ -530,11 +529,8 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)  		return PTR_ERR(rtc->regs_soc);  	rtc->irq = platform_get_irq(pdev, 0); - -	if (rtc->irq < 0) { -		dev_err(&pdev->dev, "no irq\n"); +	if (rtc->irq < 0)  		return rtc->irq; -	}  	rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);  	if (IS_ERR(rtc->rtc_dev)) @@ -564,11 +560,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)  	rtc->rtc_dev->range_max = U32_MAX; -	ret = rtc_register_device(rtc->rtc_dev); -	if (ret) -		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - -	return ret; +	return rtc_register_device(rtc->rtc_dev);  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index d45a44936308..10413d803caa 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -257,10 +257,8 @@ static int asm9260_rtc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, priv);  	irq_alarm = platform_get_irq(pdev, 0); -	if (irq_alarm < 0) { -		dev_err(dev, "No alarm IRQ resource defined\n"); +	if (irq_alarm < 0)  		return irq_alarm; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	priv->iobase = devm_ioremap_resource(dev, res); diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c index af3eb676d7c3..e351d35b29a3 100644 --- a/drivers/rtc/rtc-aspeed.c +++ b/drivers/rtc/rtc-aspeed.c @@ -86,7 +86,6 @@ static int aspeed_rtc_probe(struct platform_device *pdev)  {  	struct aspeed_rtc *rtc;  	struct resource *res; -	int ret;  	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);  	if (!rtc) @@ -107,11 +106,7 @@ static int aspeed_rtc_probe(struct platform_device *pdev)  	rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;  	rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ -	ret = rtc_register_device(rtc->rtc_dev); -	if (ret) -		return ret; - -	return 0; +	return rtc_register_device(rtc->rtc_dev);  }  static const struct of_device_id aspeed_rtc_match[] = { diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 82a54e93ff04..d119c6e6353e 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -378,10 +378,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)  	}  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "no irq resource defined\n"); +	if (irq < 0)  		return -ENXIO; -	}  	at91_rtc_regs = devm_ioremap(&pdev->dev, regs->start,  				     resource_size(regs)); diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 4daf3789b978..bb3ba7bfe6a5 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -342,10 +342,8 @@ static int at91_rtc_probe(struct platform_device *pdev)  	struct of_phandle_args args;  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "failed to get interrupt resource\n"); +	if (irq < 0)  		return irq; -	}  	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);  	if (!rtc) diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index f9bdd555e1a2..7744333b0f40 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -416,11 +416,8 @@ static int bd70528_probe(struct platform_device *pdev)  	bd_rtc->dev = &pdev->dev;  	irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm"); - -	if (irq < 0) { -		dev_err(&pdev->dev, "Failed to get irq\n"); +	if (irq < 0)  		return irq; -	}  	platform_set_drvdata(pdev, bd_rtc); @@ -479,11 +476,7 @@ static int bd70528_probe(struct platform_device *pdev)  		return ret;  	} -	ret = rtc_register_device(rtc); -	if (ret) -		dev_err(&pdev->dev, "Registering RTC failed\n"); - -	return ret; +	return rtc_register_device(rtc);  }  static struct platform_driver bd70528_rtc = { diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index 2f65943867f5..3e9800f9878a 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -255,10 +255,8 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)  	timer->rtc->range_max = U32_MAX;  	ret = rtc_register_device(timer->rtc); -	if (ret) { -		dev_err(dev, "unable to register device\n"); +	if (ret)  		goto err_notifier; -	}  	dev_info(dev, "registered, with irq %d\n", timer->irq); diff --git a/drivers/rtc/rtc-cadence.c b/drivers/rtc/rtc-cadence.c index 3b7d643c8a63..592aae23cbaf 100644 --- a/drivers/rtc/rtc-cadence.c +++ b/drivers/rtc/rtc-cadence.c @@ -289,12 +289,8 @@ static int cdns_rtc_probe(struct platform_device *pdev)  	}  	crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); -	if (IS_ERR(crtc->rtc_dev)) { -		ret = PTR_ERR(crtc->rtc_dev); -		dev_err(&pdev->dev, -			"Failed to allocate the RTC device, %d\n", ret); -		return ret; -	} +	if (IS_ERR(crtc->rtc_dev)) +		return PTR_ERR(crtc->rtc_dev);  	platform_set_drvdata(pdev, crtc); @@ -343,11 +339,8 @@ static int cdns_rtc_probe(struct platform_device *pdev)  	writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);  	ret = rtc_register_device(crtc->rtc_dev); -	if (ret) { -		dev_err(&pdev->dev, -			"Failed to register the RTC device, %d\n", ret); +	if (ret)  		goto err_disable_wakeup; -	}  	return 0; diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index 4d6bf9304ceb..6909e01936d9 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c @@ -6,8 +6,9 @@  #include <linux/kernel.h>  #include <linux/mfd/cros_ec.h> -#include <linux/mfd/cros_ec_commands.h>  #include <linux/module.h> +#include <linux/platform_data/cros_ec_commands.h> +#include <linux/platform_data/cros_ec_proto.h>  #include <linux/platform_device.h>  #include <linux/rtc.h>  #include <linux/slab.h> diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index fcb71bf4d492..d8e0db2e7fc6 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -477,10 +477,8 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)  		return -ENOMEM;  	davinci_rtc->irq = platform_get_irq(pdev, 0); -	if (davinci_rtc->irq < 0) { -		dev_err(dev, "no RTC irq\n"); +	if (davinci_rtc->irq < 0)  		return davinci_rtc->irq; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	davinci_rtc->base = devm_ioremap_resource(dev, res); diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index e04d6e862c42..4420fbf2f8fe 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -690,19 +690,16 @@ static int ds1305_probe(struct spi_device *spi)  	/* register RTC ... from here on, ds1305->ctrl needs locking */  	ds1305->rtc = devm_rtc_allocate_device(&spi->dev); -	if (IS_ERR(ds1305->rtc)) { +	if (IS_ERR(ds1305->rtc))  		return PTR_ERR(ds1305->rtc); -	}  	ds1305->rtc->ops = &ds1305_ops;  	ds1305_nvmem_cfg.priv = ds1305;  	ds1305->rtc->nvram_old_abi = true;  	status = rtc_register_device(ds1305->rtc); -	if (status) { -		dev_dbg(&spi->dev, "register rtc --> %d\n", status); +	if (status)  		return status; -	}  	rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg); diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 225a8df1d4e9..367497914c10 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -14,7 +14,7 @@   */  /*   * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section + * recommended in .../Documentation/i2c/writing-clients.rst section   * "Sending and receiving", using SMBus level communication is preferred.   */ diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index e9e8d02743ee..9da84df9f152 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -128,9 +128,6 @@ static int ds1672_probe(struct i2c_client *client,  	if (err)  		return err; -	if (IS_ERR(rtc)) -		return PTR_ERR(rtc); -  	i2c_set_clientdata(client, rtc);  	return 0; diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c new file mode 100644 index 000000000000..8df2075af9a2 --- /dev/null +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale FlexTimer Module (FTM) alarm device driver. + * + * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2019 NXP + * + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/module.h> +#include <linux/fsl/ftm.h> +#include <linux/rtc.h> +#include <linux/time.h> + +#define FTM_SC_CLK(c)		((c) << FTM_SC_CLK_MASK_SHIFT) + +/* + * Select Fixed frequency clock (32KHz) as clock source + * of FlexTimer Module + */ +#define FTM_SC_CLKS_FIXED_FREQ	0x02 +#define FIXED_FREQ_CLK		32000 + +/* Select 128 (2^7) as divider factor */ +#define MAX_FREQ_DIV		(1 << FTM_SC_PS_MASK) + +/* Maximum counter value in FlexTimer's CNT registers */ +#define MAX_COUNT_VAL		0xffff + +struct ftm_rtc { +	struct rtc_device *rtc_dev; +	void __iomem *base; +	bool big_endian; +	u32 alarm_freq; +}; + +static inline u32 rtc_readl(struct ftm_rtc *dev, u32 reg) +{ +	if (dev->big_endian) +		return ioread32be(dev->base + reg); +	else +		return ioread32(dev->base + reg); +} + +static inline void rtc_writel(struct ftm_rtc *dev, u32 reg, u32 val) +{ +	if (dev->big_endian) +		iowrite32be(val, dev->base + reg); +	else +		iowrite32(val, dev->base + reg); +} + +static inline void ftm_counter_enable(struct ftm_rtc *rtc) +{ +	u32 val; + +	/* select and enable counter clock source */ +	val = rtc_readl(rtc, FTM_SC); +	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); +	val |= (FTM_SC_PS_MASK | FTM_SC_CLK(FTM_SC_CLKS_FIXED_FREQ)); +	rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_counter_disable(struct ftm_rtc *rtc) +{ +	u32 val; + +	/* disable counter clock source */ +	val = rtc_readl(rtc, FTM_SC); +	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); +	rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_irq_acknowledge(struct ftm_rtc *rtc) +{ +	unsigned int timeout = 100; + +	/* +	 *Fix errata A-007728 for flextimer +	 *	If the FTM counter reaches the FTM_MOD value between +	 *	the reading of the TOF bit and the writing of 0 to +	 *	the TOF bit, the process of clearing the TOF bit +	 *	does not work as expected when FTMx_CONF[NUMTOF] != 0 +	 *	and the current TOF count is less than FTMx_CONF[NUMTOF]. +	 *	If the above condition is met, the TOF bit remains set. +	 *	If the TOF interrupt is enabled (FTMx_SC[TOIE] = 1),the +	 *	TOF interrupt also remains asserted. +	 * +	 *	Above is the errata discription +	 * +	 *	In one word: software clearing TOF bit not works when +	 *	FTMx_CONF[NUMTOF] was seted as nonzero and FTM counter +	 *	reaches the FTM_MOD value. +	 * +	 *	The workaround is clearing TOF bit until it works +	 *	(FTM counter doesn't always reache the FTM_MOD anyway), +	 *	which may cost some cycles. +	 */ +	while ((FTM_SC_TOF & rtc_readl(rtc, FTM_SC)) && timeout--) +		rtc_writel(rtc, FTM_SC, rtc_readl(rtc, FTM_SC) & (~FTM_SC_TOF)); +} + +static inline void ftm_irq_enable(struct ftm_rtc *rtc) +{ +	u32 val; + +	val = rtc_readl(rtc, FTM_SC); +	val |= FTM_SC_TOIE; +	rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_irq_disable(struct ftm_rtc *rtc) +{ +	u32 val; + +	val = rtc_readl(rtc, FTM_SC); +	val &= ~FTM_SC_TOIE; +	rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_reset_counter(struct ftm_rtc *rtc) +{ +	/* +	 * The CNT register contains the FTM counter value. +	 * Reset clears the CNT register. Writing any value to COUNT +	 * updates the counter with its initial value, CNTIN. +	 */ +	rtc_writel(rtc, FTM_CNT, 0x00); +} + +static void ftm_clean_alarm(struct ftm_rtc *rtc) +{ +	ftm_counter_disable(rtc); + +	rtc_writel(rtc, FTM_CNTIN, 0x00); +	rtc_writel(rtc, FTM_MOD, ~0U); + +	ftm_reset_counter(rtc); +} + +static irqreturn_t ftm_rtc_alarm_interrupt(int irq, void *dev) +{ +	struct ftm_rtc *rtc = dev; + +	ftm_irq_acknowledge(rtc); +	ftm_irq_disable(rtc); +	ftm_clean_alarm(rtc); + +	return IRQ_HANDLED; +} + +static int ftm_rtc_alarm_irq_enable(struct device *dev, +		unsigned int enabled) +{ +	struct ftm_rtc *rtc = dev_get_drvdata(dev); + +	if (enabled) +		ftm_irq_enable(rtc); +	else +		ftm_irq_disable(rtc); + +	return 0; +} + +/* + * Note: + *	The function is not really getting time from the RTC + *	since FlexTimer is not a RTC device, but we need to + *	get time to setup alarm, so we are using system time + *	for now. + */ +static int ftm_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct timespec64 ts64; + +	ktime_get_real_ts64(&ts64); +	rtc_time_to_tm(ts64.tv_sec, tm); + +	return 0; +} + +static int ftm_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ +	return 0; +} + +/* + * 1. Select fixed frequency clock (32KHz) as clock source; + * 2. Select 128 (2^7) as divider factor; + * So clock is 250 Hz (32KHz/128). + * + * 3. FlexTimer's CNT register is a 32bit register, + * but the register's 16 bit as counter value,it's other 16 bit + * is reserved.So minimum counter value is 0x0,maximum counter + * value is 0xffff. + * So max alarm value is 262 (65536 / 250) seconds + */ +static int ftm_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ +	struct rtc_time tm; +	unsigned long now, alm_time, cycle; +	struct ftm_rtc *rtc = dev_get_drvdata(dev); + +	ftm_rtc_read_time(dev, &tm); +	rtc_tm_to_time(&tm, &now); +	rtc_tm_to_time(&alm->time, &alm_time); + +	ftm_clean_alarm(rtc); +	cycle = (alm_time - now) * rtc->alarm_freq; +	if (cycle > MAX_COUNT_VAL) { +		pr_err("Out of alarm range {0~262} seconds.\n"); +		return -ERANGE; +	} + +	ftm_irq_disable(rtc); + +	/* +	 * The counter increments until the value of MOD is reached, +	 * at which point the counter is reloaded with the value of CNTIN. +	 * The TOF (the overflow flag) bit is set when the FTM counter +	 * changes from MOD to CNTIN. So we should using the cycle - 1. +	 */ +	rtc_writel(rtc, FTM_MOD, cycle - 1); + +	ftm_counter_enable(rtc); +	ftm_irq_enable(rtc); + +	return 0; + +} + +static const struct rtc_class_ops ftm_rtc_ops = { +	.read_time		= ftm_rtc_read_time, +	.read_alarm		= ftm_rtc_read_alarm, +	.set_alarm		= ftm_rtc_set_alarm, +	.alarm_irq_enable	= ftm_rtc_alarm_irq_enable, +}; + +static int ftm_rtc_probe(struct platform_device *pdev) +{ +	struct device_node *np = pdev->dev.of_node; +	struct resource *r; +	int irq; +	int ret; +	struct ftm_rtc *rtc; + +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); +	if (unlikely(!rtc)) { +		dev_err(&pdev->dev, "cannot alloc memory for rtc\n"); +		return -ENOMEM; +	} + +	platform_set_drvdata(pdev, rtc); + +	rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); +	if (IS_ERR(rtc->rtc_dev)) +		return PTR_ERR(rtc->rtc_dev); + +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!r) { +		dev_err(&pdev->dev, "cannot get resource for rtc\n"); +		return -ENODEV; +	} + +	rtc->base = devm_ioremap_resource(&pdev->dev, r); +	if (IS_ERR(rtc->base)) { +		dev_err(&pdev->dev, "cannot ioremap resource for rtc\n"); +		return PTR_ERR(rtc->base); +	} + +	irq = irq_of_parse_and_map(np, 0); +	if (irq <= 0) { +		dev_err(&pdev->dev, "unable to get IRQ from DT, %d\n", irq); +		return -EINVAL; +	} + +	ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt, +			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), rtc); +	if (ret < 0) { +		dev_err(&pdev->dev, "failed to request irq\n"); +		return ret; +	} + +	rtc->big_endian = of_property_read_bool(np, "big-endian"); +	rtc->alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV; +	rtc->rtc_dev->ops = &ftm_rtc_ops; + +	device_init_wakeup(&pdev->dev, true); + +	ret = rtc_register_device(rtc->rtc_dev); +	if (ret) { +		dev_err(&pdev->dev, "can't register rtc device\n"); +		return ret; +	} + +	return 0; +} + +static const struct of_device_id ftm_rtc_match[] = { +	{ .compatible = "fsl,ls1012a-ftm-alarm", }, +	{ .compatible = "fsl,ls1021a-ftm-alarm", }, +	{ .compatible = "fsl,ls1028a-ftm-alarm", }, +	{ .compatible = "fsl,ls1043a-ftm-alarm", }, +	{ .compatible = "fsl,ls1046a-ftm-alarm", }, +	{ .compatible = "fsl,ls1088a-ftm-alarm", }, +	{ .compatible = "fsl,ls208xa-ftm-alarm", }, +	{ .compatible = "fsl,lx2160a-ftm-alarm", }, +	{ }, +}; + +static struct platform_driver ftm_rtc_driver = { +	.probe		= ftm_rtc_probe, +	.driver		= { +		.name	= "ftm-alarm", +		.of_match_table = ftm_rtc_match, +	}, +}; + +static int __init ftm_alarm_init(void) +{ +	return platform_driver_register(&ftm_rtc_driver); +} + +device_initcall(ftm_alarm_init); + +MODULE_DESCRIPTION("NXP/Freescale FlexTimer alarm driver"); +MODULE_AUTHOR("Biwen Li <[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index c933045fe04b..cf2c12107f2b 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -167,10 +167,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev)  	imx_sc_rtc->range_max = U32_MAX;  	ret = rtc_register_device(imx_sc_rtc); -	if (ret) { -		dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); +	if (ret)  		return ret; -	}  	imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 3f3d652a0b0f..f21dc6b16d88 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -740,7 +740,6 @@ static void dryice_work(struct work_struct *work)   */  static int __init dryice_rtc_probe(struct platform_device *pdev)  { -	struct resource *res;  	struct imxdi_dev *imxdi;  	int norm_irq, sec_irq;  	int rc; @@ -751,8 +750,7 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)  	imxdi->pdev = pdev; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	imxdi->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(imxdi->ioaddr))  		return PTR_ERR(imxdi->ioaddr); diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c index 97f594f9667c..5b6b17fb6d62 100644 --- a/drivers/rtc/rtc-isl12026.c +++ b/drivers/rtc/rtc-isl12026.c @@ -454,9 +454,9 @@ static int isl12026_probe_new(struct i2c_client *client)  	isl12026_force_power_modes(client); -	priv->nvm_client = i2c_new_dummy(client->adapter, ISL12026_EEPROM_ADDR); -	if (!priv->nvm_client) -		return -ENOMEM; +	priv->nvm_client = i2c_new_dummy_device(client->adapter, ISL12026_EEPROM_ADDR); +	if (IS_ERR(priv->nvm_client)) +		return PTR_ERR(priv->nvm_client);  	priv->rtc = devm_rtc_allocate_device(&client->dev);  	ret = PTR_ERR_OR_ZERO(priv->rtc); diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 9e7b3a04debc..3089645e0ce8 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -323,10 +323,8 @@ static int jz4740_rtc_probe(struct platform_device *pdev)  		rtc->type = id->driver_data;  	rtc->irq = platform_get_irq(pdev, 0); -	if (rtc->irq < 0) { -		dev_err(&pdev->dev, "Failed to get platform irq\n"); +	if (rtc->irq < 0)  		return -ENOENT; -	}  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	rtc->base = devm_ioremap_resource(&pdev->dev, mem); @@ -362,10 +360,8 @@ static int jz4740_rtc_probe(struct platform_device *pdev)  	rtc->rtc->range_max = U32_MAX;  	ret = rtc_register_device(rtc->rtc); -	if (ret) { -		dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); +	if (ret)  		return ret; -	}  	ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0,  				pdev->name, rtc); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 4aff349ae301..d5a0e27dd0a0 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -673,11 +673,8 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)  		struct platform_device *pdev = to_platform_device(info->dev);  		info->rtc_irq = platform_get_irq(pdev, 0); -		if (info->rtc_irq < 0) { -			dev_err(info->dev, "Failed to get rtc interrupts: %d\n", -				info->rtc_irq); +		if (info->rtc_irq < 0)  			return info->rtc_irq; -		}  	} else {  		info->rtc_irq =  parent_i2c->irq;  	} @@ -693,11 +690,11 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)  		goto add_rtc_irq;  	} -	info->rtc = i2c_new_dummy(parent_i2c->adapter, -				  info->drv_data->rtc_i2c_addr); -	if (!info->rtc) { +	info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, +					      info->drv_data->rtc_i2c_addr); +	if (IS_ERR(info->rtc)) {  		dev_err(info->dev, "Failed to allocate I2C device for RTC\n"); -		return -ENODEV; +		return PTR_ERR(info->rtc);  	}  	info->rtc_regmap = devm_regmap_init_i2c(info->rtc, @@ -705,7 +702,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)  	if (IS_ERR(info->rtc_regmap)) {  		ret = PTR_ERR(info->rtc_regmap);  		dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); -		goto err_unregister_i2c; +		return ret;  	}  add_rtc_irq: @@ -715,15 +712,10 @@ add_rtc_irq:  				  &info->rtc_irq_data);  	if (ret < 0) {  		dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret); -		goto err_unregister_i2c; +		return ret;  	}  	return 0; - -err_unregister_i2c: -	if (info->rtc) -		i2c_unregister_device(info->rtc); -	return ret;  }  static int max77686_rtc_probe(struct platform_device *pdev) @@ -786,8 +778,6 @@ static int max77686_rtc_probe(struct platform_device *pdev)  err_rtc:  	regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data); -	if (info->rtc) -		i2c_unregister_device(info->rtc);  	return ret;  } @@ -798,8 +788,6 @@ static int max77686_rtc_remove(struct platform_device *pdev)  	free_irq(info->virq, info);  	regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data); -	if (info->rtc) -		i2c_unregister_device(info->rtc);  	return 0;  } diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c new file mode 100644 index 000000000000..89e5ba0dae69 --- /dev/null +++ b/drivers/rtc/rtc-meson-vrtc.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong <[email protected]> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/time64.h> + +struct meson_vrtc_data { +	void __iomem *io_alarm; +	struct rtc_device *rtc; +	unsigned long alarm_time; +	bool enabled; +}; + +static int meson_vrtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct timespec64 time; + +	dev_dbg(dev, "%s\n", __func__); +	ktime_get_raw_ts64(&time); +	rtc_time64_to_tm(time.tv_sec, tm); + +	return 0; +} + +static void meson_vrtc_set_wakeup_time(struct meson_vrtc_data *vrtc, +				       unsigned long time) +{ +	writel_relaxed(time, vrtc->io_alarm); +} + +static int meson_vrtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + +	dev_dbg(dev, "%s: alarm->enabled=%d\n", __func__, alarm->enabled); +	if (alarm->enabled) +		vrtc->alarm_time = rtc_tm_to_time64(&alarm->time); +	else +		vrtc->alarm_time = 0; + +	return 0; +} + +static int meson_vrtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ +	struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + +	vrtc->enabled = enabled; +	return 0; +} + +static const struct rtc_class_ops meson_vrtc_ops = { +	.read_time = meson_vrtc_read_time, +	.set_alarm = meson_vrtc_set_alarm, +	.alarm_irq_enable = meson_vrtc_alarm_irq_enable, +}; + +static int meson_vrtc_probe(struct platform_device *pdev) +{ +	struct meson_vrtc_data *vrtc; +	int ret; + +	vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); +	if (!vrtc) +		return -ENOMEM; + +	vrtc->io_alarm = devm_platform_ioremap_resource(pdev, 0); +	if (IS_ERR(vrtc->io_alarm)) +		return PTR_ERR(vrtc->io_alarm); + +	device_init_wakeup(&pdev->dev, 1); + +	platform_set_drvdata(pdev, vrtc); + +	vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); +	if (IS_ERR(vrtc->rtc)) +		return PTR_ERR(vrtc->rtc); + +	vrtc->rtc->ops = &meson_vrtc_ops; +	ret = rtc_register_device(vrtc->rtc); +	if (ret) +		return ret; + +	return 0; +} + +static int __maybe_unused meson_vrtc_suspend(struct device *dev) +{ +	struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + +	dev_dbg(dev, "%s\n", __func__); +	if (vrtc->alarm_time) { +		unsigned long local_time; +		long alarm_secs; +		struct timespec64 time; + +		ktime_get_raw_ts64(&time); +		local_time = time.tv_sec; + +		dev_dbg(dev, "alarm_time = %lus, local_time=%lus\n", +			vrtc->alarm_time, local_time); +		alarm_secs = vrtc->alarm_time - local_time; +		if (alarm_secs > 0) { +			meson_vrtc_set_wakeup_time(vrtc, alarm_secs); +			dev_dbg(dev, "system will wakeup in %lds.\n", +				alarm_secs); +		} else { +			dev_err(dev, "alarm time already passed: %lds.\n", +				alarm_secs); +		} +	} + +	return 0; +} + +static int __maybe_unused meson_vrtc_resume(struct device *dev) +{ +	struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + +	dev_dbg(dev, "%s\n", __func__); + +	vrtc->alarm_time = 0; +	meson_vrtc_set_wakeup_time(vrtc, 0); +	return 0; +} + +static SIMPLE_DEV_PM_OPS(meson_vrtc_pm_ops, +			 meson_vrtc_suspend, meson_vrtc_resume); + +static const struct of_device_id meson_vrtc_dt_match[] = { +	{ .compatible = "amlogic,meson-vrtc"}, +	{}, +}; +MODULE_DEVICE_TABLE(of, meson_vrtc_dt_match); + +static struct platform_driver meson_vrtc_driver = { +	.probe = meson_vrtc_probe, +	.driver = { +		.name = "meson-vrtc", +		.of_match_table = meson_vrtc_dt_match, +		.pm = &meson_vrtc_pm_ops, +	}, +}; + +module_platform_driver(meson_vrtc_driver); + +MODULE_DESCRIPTION("Amlogic Virtual Wakeup RTC Timer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index b46ed4dc7015..704229eb0cac 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -343,10 +343,8 @@ static int mtk_rtc_probe(struct platform_device *pdev)  	rtc->rtc_dev->ops = &mtk_rtc_ops;  	ret = rtc_register_device(rtc->rtc_dev); -	if (ret) { -		dev_err(&pdev->dev, "register rtc device failed\n"); +	if (ret)  		goto out_free_irq; -	}  	return 0; diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c index 82b0816ec6c1..16bd26b5aa6f 100644 --- a/drivers/rtc/rtc-mt7622.c +++ b/drivers/rtc/rtc-mt7622.c @@ -329,7 +329,6 @@ static int mtk_rtc_probe(struct platform_device *pdev)  	hw->irq = platform_get_irq(pdev, 0);  	if (hw->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource\n");  		ret = hw->irq;  		goto err;  	} diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index e697e96612bb..902d57dcd0d4 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -184,8 +184,9 @@ static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,  	struct rtc_plat_data *pdata = dev_get_drvdata(dev);  	void __iomem *ioaddr = pdata->ioaddr;  	u32 reg; +	unsigned long flags; -	spin_lock_irq(&pdata->rtc->irq_lock); +	spin_lock_irqsave(&pdata->rtc->irq_lock, flags);  	reg = readw(ioaddr + RTC_RTCIENR);  	if (enabled) @@ -194,7 +195,7 @@ static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,  		reg &= ~bit;  	writew(reg, ioaddr + RTC_RTCIENR); -	spin_unlock_irq(&pdata->rtc->irq_lock); +	spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);  }  /* This function is the RTC interrupt service routine. */ diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 5b970a816631..91534560fe2a 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -279,7 +279,6 @@ static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag)  static int mxc_rtc_probe(struct platform_device *pdev)  {  	struct mxc_rtc_data *pdata; -	struct resource *res;  	void __iomem *ioaddr;  	int ret = 0; @@ -287,8 +286,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)  	if (!pdata)  		return -ENOMEM; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	pdata->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(pdata->ioaddr))  		return PTR_ERR(pdata->ioaddr); diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c deleted file mode 100644 index 49cc4058614d..000000000000 --- a/drivers/rtc/rtc-nuc900.c +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2008-2009 Nuvoton technology corporation. - * - * Wan ZongShun <[email protected]> - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/rtc.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/bcd.h> - -/* RTC Control Registers */ -#define REG_RTC_INIR		0x00 -#define REG_RTC_AER		0x04 -#define REG_RTC_FCR		0x08 -#define REG_RTC_TLR		0x0C -#define REG_RTC_CLR		0x10 -#define REG_RTC_TSSR		0x14 -#define REG_RTC_DWR		0x18 -#define REG_RTC_TAR		0x1C -#define REG_RTC_CAR		0x20 -#define REG_RTC_LIR		0x24 -#define REG_RTC_RIER		0x28 -#define REG_RTC_RIIR		0x2C -#define REG_RTC_TTR		0x30 - -#define RTCSET			0x01 -#define AERRWENB		0x10000 -#define INIRRESET		0xa5eb1357 -#define AERPOWERON		0xA965 -#define AERPOWEROFF		0x0000 -#define LEAPYEAR		0x0001 -#define TICKENB			0x80 -#define TICKINTENB		0x0002 -#define ALARMINTENB		0x0001 -#define MODE24			0x0001 - -struct nuc900_rtc { -	int			irq_num; -	void __iomem		*rtc_reg; -	struct rtc_device	*rtcdev; -}; - -struct nuc900_bcd_time { -	int bcd_sec; -	int bcd_min; -	int bcd_hour; -	int bcd_mday; -	int bcd_mon; -	int bcd_year; -}; - -static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) -{ -	struct nuc900_rtc *rtc = _rtc; -	unsigned long events = 0, rtc_irq; - -	rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR); - -	if (rtc_irq & ALARMINTENB) { -		rtc_irq &= ~ALARMINTENB; -		__raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); -		events |= RTC_AF | RTC_IRQF; -	} - -	if (rtc_irq & TICKINTENB) { -		rtc_irq &= ~TICKINTENB; -		__raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); -		events |= RTC_UF | RTC_IRQF; -	} - -	rtc_update_irq(rtc->rtcdev, 1, events); - -	return IRQ_HANDLED; -} - -static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) -{ -	unsigned int timeout = 0x1000; -	__raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); - -	mdelay(10); - -	__raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); - -	while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) -								&& --timeout) -		mdelay(1); - -	if (!timeout) -		return ERR_PTR(-EPERM); - -	return NULL; -} - -static void nuc900_rtc_bcd2bin(unsigned int timereg, -			       unsigned int calreg, struct rtc_time *tm) -{ -	tm->tm_mday	= bcd2bin(calreg >> 0); -	tm->tm_mon	= bcd2bin(calreg >> 8); -	tm->tm_year	= bcd2bin(calreg >> 16) + 100; - -	tm->tm_sec	= bcd2bin(timereg >> 0); -	tm->tm_min	= bcd2bin(timereg >> 8); -	tm->tm_hour	= bcd2bin(timereg >> 16); -} - -static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, -						struct nuc900_bcd_time *gettm) -{ -	gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; -	gettm->bcd_mon  = bin2bcd(settm->tm_mon) << 8; - -	if (settm->tm_year < 100) { -		dev_warn(dev, "The year will be between 1970-1999, right?\n"); -		gettm->bcd_year = bin2bcd(settm->tm_year) << 16; -	} else { -		gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; -	} - -	gettm->bcd_sec  = bin2bcd(settm->tm_sec) << 0; -	gettm->bcd_min  = bin2bcd(settm->tm_min) << 8; -	gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16; -} - -static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ -	struct nuc900_rtc *rtc = dev_get_drvdata(dev); - -	if (enabled) -		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| -				(ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); -	else -		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& -				(~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); - -	return 0; -} - -static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ -	struct nuc900_rtc *rtc = dev_get_drvdata(dev); -	unsigned int timeval, clrval; - -	timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); -	clrval	= __raw_readl(rtc->rtc_reg + REG_RTC_CLR); - -	nuc900_rtc_bcd2bin(timeval, clrval, tm); - -	return 0; -} - -static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ -	struct nuc900_rtc *rtc = dev_get_drvdata(dev); -	struct nuc900_bcd_time gettm; -	unsigned long val; -	int *err; - -	nuc900_rtc_bin2bcd(dev, tm, &gettm); - -	err = check_rtc_access_enable(rtc); -	if (IS_ERR(err)) -		return PTR_ERR(err); - -	val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; -	__raw_writel(val, rtc->rtc_reg + REG_RTC_CLR); - -	val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; -	__raw_writel(val, rtc->rtc_reg + REG_RTC_TLR); - -	return 0; -} - -static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ -	struct nuc900_rtc *rtc = dev_get_drvdata(dev); -	unsigned int timeval, carval; - -	timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); -	carval	= __raw_readl(rtc->rtc_reg + REG_RTC_CAR); - -	nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); - -	return rtc_valid_tm(&alrm->time); -} - -static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ -	struct nuc900_rtc *rtc = dev_get_drvdata(dev); -	struct nuc900_bcd_time tm; -	unsigned long val; -	int *err; - -	nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); - -	err = check_rtc_access_enable(rtc); -	if (IS_ERR(err)) -		return PTR_ERR(err); - -	val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; -	__raw_writel(val, rtc->rtc_reg + REG_RTC_CAR); - -	val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; -	__raw_writel(val, rtc->rtc_reg + REG_RTC_TAR); - -	return 0; -} - -static const struct rtc_class_ops nuc900_rtc_ops = { -	.read_time = nuc900_rtc_read_time, -	.set_time = nuc900_rtc_set_time, -	.read_alarm = nuc900_rtc_read_alarm, -	.set_alarm = nuc900_rtc_set_alarm, -	.alarm_irq_enable = nuc900_alarm_irq_enable, -}; - -static int __init nuc900_rtc_probe(struct platform_device *pdev) -{ -	struct resource *res; -	struct nuc900_rtc *nuc900_rtc; - -	nuc900_rtc = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_rtc), -				GFP_KERNEL); -	if (!nuc900_rtc) -		return -ENOMEM; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	nuc900_rtc->rtc_reg = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(nuc900_rtc->rtc_reg)) -		return PTR_ERR(nuc900_rtc->rtc_reg); - -	platform_set_drvdata(pdev, nuc900_rtc); - -	nuc900_rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name, -						&nuc900_rtc_ops, THIS_MODULE); -	if (IS_ERR(nuc900_rtc->rtcdev)) { -		dev_err(&pdev->dev, "rtc device register failed\n"); -		return PTR_ERR(nuc900_rtc->rtcdev); -	} - -	__raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, -					nuc900_rtc->rtc_reg + REG_RTC_TSSR); - -	nuc900_rtc->irq_num = platform_get_irq(pdev, 0); -	if (devm_request_irq(&pdev->dev, nuc900_rtc->irq_num, -			nuc900_rtc_interrupt, 0, "nuc900rtc", nuc900_rtc)) { -		dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); -		return -EBUSY; -	} - -	return 0; -} - -static struct platform_driver nuc900_rtc_driver = { -	.driver		= { -		.name	= "nuc900-rtc", -	}, -}; - -module_platform_driver_probe(nuc900_rtc_driver, nuc900_rtc_probe); - -MODULE_AUTHOR("Wan ZongShun <[email protected]>"); -MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-rtc"); diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index fb542a930bf0..c3691fa4210e 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -82,7 +82,7 @@  #define OSC_HAS_STOPPED		BIT(7)	/* Clock has been stopped */  /* PCF2123_REG_ALRM_XX BITS */ -#define ALRM_ENABLE		BIT(7)	/* MN, HR, DM, or DW alarm enable */ +#define ALRM_DISABLE		BIT(7)	/* MN, HR, DM, or DW alarm matching */  /* PCF2123_REG_TMR_CLKOUT BITS */  #define CD_TMR_4096KHZ		(0)	/* 4096 KHz countdown timer */ @@ -104,7 +104,7 @@  static struct spi_driver pcf2123_driver; -struct pcf2123_plat_data { +struct pcf2123_data {  	struct rtc_device *rtc;  	struct regmap *map;  }; @@ -119,11 +119,11 @@ static const struct regmap_config pcf2123_regmap_config = {  static int pcf2123_read_offset(struct device *dev, long *offset)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	int ret, val;  	unsigned int reg; -	ret = regmap_read(pdata->map, PCF2123_REG_OFFSET, ®); +	ret = regmap_read(pcf2123->map, PCF2123_REG_OFFSET, ®);  	if (ret)  		return ret; @@ -149,7 +149,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)   */  static int pcf2123_set_offset(struct device *dev, long offset)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	s8 reg;  	if (offset > OFFSET_STEP * 127) @@ -169,16 +169,16 @@ static int pcf2123_set_offset(struct device *dev, long offset)  		reg |= OFFSET_COARSE;  	} -	return regmap_write(pdata->map, PCF2123_REG_OFFSET, (unsigned int)reg); +	return regmap_write(pcf2123->map, PCF2123_REG_OFFSET, (unsigned int)reg);  }  static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	u8 rxbuf[7];  	int ret; -	ret = regmap_bulk_read(pdata->map, PCF2123_REG_SC, rxbuf, +	ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_SC, rxbuf,  				sizeof(rxbuf));  	if (ret)  		return ret; @@ -194,9 +194,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)  	tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F);  	tm->tm_wday = rxbuf[4] & 0x07;  	tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */ -	tm->tm_year = bcd2bin(rxbuf[6]); -	if (tm->tm_year < 70) -		tm->tm_year += 100;	/* assume we are in 1970...2069 */ +	tm->tm_year = bcd2bin(rxbuf[6]) + 100;  	dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); @@ -205,14 +203,14 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)  static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	u8 txbuf[7];  	int ret;  	dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm);  	/* Stop the counter first */ -	ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); +	ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_STOP);  	if (ret)  		return ret; @@ -223,29 +221,37 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)  	txbuf[3] = bin2bcd(tm->tm_mday & 0x3F);  	txbuf[4] = tm->tm_wday & 0x07;  	txbuf[5] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ -	txbuf[6] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); +	txbuf[6] = bin2bcd(tm->tm_year - 100); -	ret = regmap_bulk_write(pdata->map, PCF2123_REG_SC, txbuf, +	ret = regmap_bulk_write(pcf2123->map, PCF2123_REG_SC, txbuf,  				sizeof(txbuf));  	if (ret)  		return ret;  	/* Start the counter */ -	ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); +	ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR);  	if (ret)  		return ret;  	return 0;  } +static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) +{ +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); + +	return regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, +				  en ? CTRL2_AIE : 0); +} +  static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	u8 rxbuf[4];  	int ret;  	unsigned int val = 0; -	ret = regmap_bulk_read(pdata->map, PCF2123_REG_ALRM_MN, rxbuf, +	ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_ALRM_MN, rxbuf,  				sizeof(rxbuf));  	if (ret)  		return ret; @@ -257,7 +263,7 @@ static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  	dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); -	ret = regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); +	ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val);  	if (ret)  		return ret; @@ -268,19 +274,19 @@ static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)  static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	u8 txbuf[4];  	int ret;  	dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); -	/* Ensure alarm flag is clear */ -	ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); +	/* Disable alarm interrupt */ +	ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0);  	if (ret)  		return ret; -	/* Disable alarm interrupt */ -	ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); +	/* Ensure alarm flag is clear */ +	ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0);  	if (ret)  		return ret; @@ -288,42 +294,34 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)  	txbuf[0] = bin2bcd(alm->time.tm_min & 0x7F);  	txbuf[1] = bin2bcd(alm->time.tm_hour & 0x3F);  	txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F); -	txbuf[3] = bin2bcd(alm->time.tm_wday & 0x07); +	txbuf[3] = ALRM_DISABLE; -	ret = regmap_bulk_write(pdata->map, PCF2123_REG_ALRM_MN, txbuf, +	ret = regmap_bulk_write(pcf2123->map, PCF2123_REG_ALRM_MN, txbuf,  				sizeof(txbuf));  	if (ret)  		return ret; -	/* Enable alarm interrupt */ -	if (alm->enabled)	{ -		ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, -						CTRL2_AIE, CTRL2_AIE); -		if (ret) -			return ret; -	} - -	return 0; +	return pcf2123_rtc_alarm_irq_enable(dev, alm->enabled);  }  static irqreturn_t pcf2123_rtc_irq(int irq, void *dev)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); -	struct mutex *lock = &pdata->rtc->ops_lock; +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); +	struct mutex *lock = &pcf2123->rtc->ops_lock;  	unsigned int val = 0;  	int ret = IRQ_NONE;  	mutex_lock(lock); -	regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); +	regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val);  	/* Alarm? */  	if (val & CTRL2_AF) {  		ret = IRQ_HANDLED;  		/* Clear alarm flag */ -		regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); +		regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); -		rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); +		rtc_update_irq(pcf2123->rtc, 1, RTC_IRQF | RTC_AF);  	}  	mutex_unlock(lock); @@ -333,23 +331,23 @@ static irqreturn_t pcf2123_rtc_irq(int irq, void *dev)  static int pcf2123_reset(struct device *dev)  { -	struct pcf2123_plat_data *pdata = dev_get_platdata(dev); +	struct pcf2123_data *pcf2123 = dev_get_drvdata(dev);  	int ret;  	unsigned int val = 0; -	ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); +	ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET);  	if (ret)  		return ret;  	/* Stop the counter */  	dev_dbg(dev, "stopping RTC\n"); -	ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); +	ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_STOP);  	if (ret)  		return ret;  	/* See if the counter was actually stopped */  	dev_dbg(dev, "checking for presence of RTC\n"); -	ret = regmap_read(pdata->map, PCF2123_REG_CTRL1, &val); +	ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL1, &val);  	if (ret)  		return ret; @@ -358,7 +356,7 @@ static int pcf2123_reset(struct device *dev)  		return -ENODEV;  	/* Start the counter */ -	ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); +	ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR);  	if (ret)  		return ret; @@ -372,26 +370,27 @@ static const struct rtc_class_ops pcf2123_rtc_ops = {  	.set_offset	= pcf2123_set_offset,  	.read_alarm	= pcf2123_rtc_read_alarm,  	.set_alarm	= pcf2123_rtc_set_alarm, +	.alarm_irq_enable = pcf2123_rtc_alarm_irq_enable,  };  static int pcf2123_probe(struct spi_device *spi)  {  	struct rtc_device *rtc;  	struct rtc_time tm; -	struct pcf2123_plat_data *pdata; +	struct pcf2123_data *pcf2123;  	int ret = 0; -	pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data), +	pcf2123 = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_data),  				GFP_KERNEL); -	if (!pdata) +	if (!pcf2123)  		return -ENOMEM; -	spi->dev.platform_data = pdata; -	pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); +	dev_set_drvdata(&spi->dev, pcf2123); -	if (IS_ERR(pdata->map)) { +	pcf2123->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); +	if (IS_ERR(pcf2123->map)) {  		dev_err(&spi->dev, "regmap init failed.\n"); -		goto kfree_exit; +		return PTR_ERR(pcf2123->map);  	}  	ret = pcf2123_rtc_read_time(&spi->dev, &tm); @@ -399,7 +398,7 @@ static int pcf2123_probe(struct spi_device *spi)  		ret = pcf2123_reset(&spi->dev);  		if (ret < 0) {  			dev_err(&spi->dev, "chip not found\n"); -			goto kfree_exit; +			return ret;  		}  	} @@ -407,16 +406,11 @@ static int pcf2123_probe(struct spi_device *spi)  			(spi->max_speed_hz + 500) / 1000);  	/* Finalize the initialization */ -	rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name, -			&pcf2123_rtc_ops, THIS_MODULE); - -	if (IS_ERR(rtc)) { -		dev_err(&spi->dev, "failed to register.\n"); -		ret = PTR_ERR(rtc); -		goto kfree_exit; -	} +	rtc = devm_rtc_allocate_device(&spi->dev); +	if (IS_ERR(rtc)) +		return PTR_ERR(rtc); -	pdata->rtc = rtc; +	pcf2123->rtc = rtc;  	/* Register alarm irq */  	if (spi->irq > 0) { @@ -434,19 +428,25 @@ static int pcf2123_probe(struct spi_device *spi)  	 * support to this driver to generate interrupts more than once  	 * per minute.  	 */ -	pdata->rtc->uie_unsupported = 1; +	rtc->uie_unsupported = 1; +	rtc->ops = &pcf2123_rtc_ops; +	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; +	rtc->range_max = RTC_TIMESTAMP_END_2099; +	rtc->set_start_time = true; -	return 0; +	ret = rtc_register_device(rtc); +	if (ret) +		return ret; -kfree_exit: -	spi->dev.platform_data = NULL; -	return ret; +	return 0;  }  #ifdef CONFIG_OF  static const struct of_device_id pcf2123_dt_ids[] = { -	{ .compatible = "nxp,rtc-pcf2123", }, +	{ .compatible = "nxp,pcf2123", },  	{ .compatible = "microcrystal,rv2123", }, +	/* Deprecated, do not use */ +	{ .compatible = "nxp,rtc-pcf2123", },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 8632f58fed43..02b069caffd5 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -5,6 +5,9 @@   *   * Author: Renaud Cerrato <[email protected]>   * + * Watchdog and tamper functions + * Author: Bruno Thomsen <[email protected]> + *   * based on the other drivers in this same directory.   *   * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf @@ -18,30 +21,67 @@  #include <linux/module.h>  #include <linux/of.h>  #include <linux/regmap.h> +#include <linux/watchdog.h> + +/* Control register 1 */ +#define PCF2127_REG_CTRL1		0x00 +#define PCF2127_BIT_CTRL1_TSF1			BIT(4) +/* Control register 2 */ +#define PCF2127_REG_CTRL2		0x01 +#define PCF2127_BIT_CTRL2_TSIE			BIT(2) +#define PCF2127_BIT_CTRL2_TSF2			BIT(5) +/* Control register 3 */ +#define PCF2127_REG_CTRL3		0x02 +#define PCF2127_BIT_CTRL3_BLIE			BIT(0) +#define PCF2127_BIT_CTRL3_BIE			BIT(1) +#define PCF2127_BIT_CTRL3_BLF			BIT(2) +#define PCF2127_BIT_CTRL3_BF			BIT(3) +#define PCF2127_BIT_CTRL3_BTSE			BIT(4) +/* Time and date registers */ +#define PCF2127_REG_SC			0x03 +#define PCF2127_BIT_SC_OSF			BIT(7) +#define PCF2127_REG_MN			0x04 +#define PCF2127_REG_HR			0x05 +#define PCF2127_REG_DM			0x06 +#define PCF2127_REG_DW			0x07 +#define PCF2127_REG_MO			0x08 +#define PCF2127_REG_YR			0x09 +/* Watchdog registers */ +#define PCF2127_REG_WD_CTL		0x10 +#define PCF2127_BIT_WD_CTL_TF0			BIT(0) +#define PCF2127_BIT_WD_CTL_TF1			BIT(1) +#define PCF2127_BIT_WD_CTL_CD0			BIT(6) +#define PCF2127_BIT_WD_CTL_CD1			BIT(7) +#define PCF2127_REG_WD_VAL		0x11 +/* Tamper timestamp registers */ +#define PCF2127_REG_TS_CTRL		0x12 +#define PCF2127_BIT_TS_CTRL_TSOFF		BIT(6) +#define PCF2127_BIT_TS_CTRL_TSM			BIT(7) +#define PCF2127_REG_TS_SC		0x13 +#define PCF2127_REG_TS_MN		0x14 +#define PCF2127_REG_TS_HR		0x15 +#define PCF2127_REG_TS_DM		0x16 +#define PCF2127_REG_TS_MO		0x17 +#define PCF2127_REG_TS_YR		0x18 +/* + * RAM registers + * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is + * battery backed and can survive a power outage. + * PCF2129 doesn't have this feature. + */ +#define PCF2127_REG_RAM_ADDR_MSB	0x1A +#define PCF2127_REG_RAM_WRT_CMD		0x1C +#define PCF2127_REG_RAM_RD_CMD		0x1D -#define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */ -#define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */ - -#define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */ -#define PCF2127_REG_CTRL3_BLF		BIT(2) - -#define PCF2127_REG_SC          (0x03)  /* datetime */ -#define PCF2127_REG_MN          (0x04) -#define PCF2127_REG_HR          (0x05) -#define PCF2127_REG_DM          (0x06) -#define PCF2127_REG_DW          (0x07) -#define PCF2127_REG_MO          (0x08) -#define PCF2127_REG_YR          (0x09) - -/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */ -#define PCF2127_REG_RAM_addr_MSB       0x1a -#define PCF2127_REG_RAM_wrt_cmd        0x1c -#define PCF2127_REG_RAM_rd_cmd         0x1d - -#define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */ +/* Watchdog timer value constants */ +#define PCF2127_WD_VAL_STOP		0 +#define PCF2127_WD_VAL_MIN		2 +#define PCF2127_WD_VAL_MAX		255 +#define PCF2127_WD_VAL_DEFAULT		60  struct pcf2127 {  	struct rtc_device *rtc; +	struct watchdog_device wdd;  	struct regmap *regmap;  }; @@ -54,30 +94,25 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)  	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);  	unsigned char buf[10];  	int ret; -	int i; -	for (i = 0; i <= PCF2127_REG_CTRL3; i++) { -		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1 + i, -				  (unsigned int *)(buf + i)); -		if (ret) { -			dev_err(dev, "%s: read error\n", __func__); -			return ret; -		} -	} - -	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_SC, -			       (buf + PCF2127_REG_SC), -			       ARRAY_SIZE(buf) - PCF2127_REG_SC); +	/* +	 * Avoid reading CTRL2 register as it causes WD_VAL register +	 * value to reset to 0 which means watchdog is stopped. +	 */ +	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL3, +			       (buf + PCF2127_REG_CTRL3), +			       ARRAY_SIZE(buf) - PCF2127_REG_CTRL3);  	if (ret) {  		dev_err(dev, "%s: read error\n", __func__);  		return ret;  	} -	if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF) +	if (buf[PCF2127_REG_CTRL3] & PCF2127_BIT_CTRL3_BLF)  		dev_info(dev,  			"low voltage detected, check/replace RTC battery.\n"); -	if (buf[PCF2127_REG_SC] & PCF2127_OSF) { +	/* Clock integrity is not guaranteed when OSF flag is set. */ +	if (buf[PCF2127_REG_SC] & PCF2127_BIT_SC_OSF) {  		/*  		 * no need clear the flag here,  		 * it will be cleared once the new date is saved @@ -88,14 +123,12 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)  	}  	dev_dbg(dev, -		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, " -		"sec=%02x, min=%02x, hr=%02x, " +		"%s: raw data is cr3=%02x, sec=%02x, min=%02x, hr=%02x, "  		"mday=%02x, wday=%02x, mon=%02x, year=%02x\n", -		__func__, -		buf[0], buf[1], buf[2], -		buf[3], buf[4], buf[5], -		buf[6], buf[7], buf[8], buf[9]); - +		__func__, buf[PCF2127_REG_CTRL3], buf[PCF2127_REG_SC], +		buf[PCF2127_REG_MN], buf[PCF2127_REG_HR], +		buf[PCF2127_REG_DM], buf[PCF2127_REG_DW], +		buf[PCF2127_REG_MO], buf[PCF2127_REG_YR]);  	tm->tm_sec = bcd2bin(buf[PCF2127_REG_SC] & 0x7F);  	tm->tm_min = bcd2bin(buf[PCF2127_REG_MN] & 0x7F); @@ -166,7 +199,7 @@ static int pcf2127_rtc_ioctl(struct device *dev,  		if (ret)  			return ret; -		touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0; +		touser = touser & PCF2127_BIT_CTRL3_BLF ? 1 : 0;  		if (copy_to_user((void __user *)arg, &touser, sizeof(int)))  			return -EFAULT; @@ -192,12 +225,12 @@ static int pcf2127_nvmem_read(void *priv, unsigned int offset,  	int ret;  	unsigned char offsetbuf[] = { offset >> 8, offset }; -	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB, +	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,  				offsetbuf, 2);  	if (ret)  		return ret; -	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd, +	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,  			       val, bytes);  	return ret ?: bytes; @@ -210,17 +243,176 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset,  	int ret;  	unsigned char offsetbuf[] = { offset >> 8, offset }; -	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB, +	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,  				offsetbuf, 2);  	if (ret)  		return ret; -	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd, +	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,  				val, bytes);  	return ret ?: bytes;  } +/* watchdog driver */ + +static int pcf2127_wdt_ping(struct watchdog_device *wdd) +{ +	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); + +	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, wdd->timeout); +} + +/* + * Restart watchdog timer if feature is active. + * + * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate, + * since register also contain control/status flags for other features. + * Always call this function after reading CTRL2 register. + */ +static int pcf2127_wdt_active_ping(struct watchdog_device *wdd) +{ +	int ret = 0; + +	if (watchdog_active(wdd)) { +		ret = pcf2127_wdt_ping(wdd); +		if (ret) +			dev_err(wdd->parent, +				"%s: watchdog restart failed, ret=%d\n", +				__func__, ret); +	} + +	return ret; +} + +static int pcf2127_wdt_start(struct watchdog_device *wdd) +{ +	return pcf2127_wdt_ping(wdd); +} + +static int pcf2127_wdt_stop(struct watchdog_device *wdd) +{ +	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); + +	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, +			    PCF2127_WD_VAL_STOP); +} + +static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd, +				   unsigned int new_timeout) +{ +	dev_dbg(wdd->parent, "new watchdog timeout: %is (old: %is)\n", +		new_timeout, wdd->timeout); + +	wdd->timeout = new_timeout; + +	return pcf2127_wdt_active_ping(wdd); +} + +static const struct watchdog_info pcf2127_wdt_info = { +	.identity = "NXP PCF2127/PCF2129 Watchdog", +	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, +}; + +static const struct watchdog_ops pcf2127_watchdog_ops = { +	.owner = THIS_MODULE, +	.start = pcf2127_wdt_start, +	.stop = pcf2127_wdt_stop, +	.ping = pcf2127_wdt_ping, +	.set_timeout = pcf2127_wdt_set_timeout, +}; + +/* sysfs interface */ + +static ssize_t timestamp0_store(struct device *dev, +				struct device_attribute *attr, +				const char *buf, size_t count) +{ +	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); +	int ret; + +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, +				 PCF2127_BIT_CTRL1_TSF1, 0); +	if (ret) { +		dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret); +		return ret; +	} + +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, +				 PCF2127_BIT_CTRL2_TSF2, 0); +	if (ret) { +		dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret); +		return ret; +	} + +	ret = pcf2127_wdt_active_ping(&pcf2127->wdd); +	if (ret) +		return ret; + +	return count; +}; + +static ssize_t timestamp0_show(struct device *dev, +			       struct device_attribute *attr, char *buf) +{ +	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); +	struct rtc_time tm; +	int ret; +	unsigned char data[25]; + +	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data, +			       sizeof(data)); +	if (ret) { +		dev_err(dev, "%s: read error ret=%d\n", __func__, ret); +		return ret; +	} + +	dev_dbg(dev, +		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, " +		"ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n", +		__func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2], +		data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC], +		data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR], +		data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO], +		data[PCF2127_REG_TS_YR]); + +	ret = pcf2127_wdt_active_ping(&pcf2127->wdd); +	if (ret) +		return ret; + +	if (!(data[PCF2127_REG_CTRL1] & PCF2127_BIT_CTRL1_TSF1) && +	    !(data[PCF2127_REG_CTRL2] & PCF2127_BIT_CTRL2_TSF2)) +		return 0; + +	tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F); +	tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F); +	tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F); +	tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F); +	/* TS_MO register (month) value range: 1-12 */ +	tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1; +	tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]); +	if (tm.tm_year < 70) +		tm.tm_year += 100; /* assume we are in 1970...2069 */ + +	ret = rtc_valid_tm(&tm); +	if (ret) +		return ret; + +	return sprintf(buf, "%llu\n", +		       (unsigned long long)rtc_tm_to_time64(&tm)); +}; + +static DEVICE_ATTR_RW(timestamp0); + +static struct attribute *pcf2127_attrs[] = { +	&dev_attr_timestamp0.attr, +	NULL +}; + +static const struct attribute_group pcf2127_attr_group = { +	.attrs	= pcf2127_attrs, +}; +  static int pcf2127_probe(struct device *dev, struct regmap *regmap,  			const char *name, bool has_nvmem)  { @@ -237,11 +429,22 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,  	dev_set_drvdata(dev, pcf2127); -	pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops, -						THIS_MODULE); +	pcf2127->rtc = devm_rtc_allocate_device(dev);  	if (IS_ERR(pcf2127->rtc))  		return PTR_ERR(pcf2127->rtc); +	pcf2127->rtc->ops = &pcf2127_rtc_ops; + +	pcf2127->wdd.parent = dev; +	pcf2127->wdd.info = &pcf2127_wdt_info; +	pcf2127->wdd.ops = &pcf2127_watchdog_ops; +	pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN; +	pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX; +	pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT; +	pcf2127->wdd.min_hw_heartbeat_ms = 500; + +	watchdog_set_drvdata(&pcf2127->wdd, pcf2127); +  	if (has_nvmem) {  		struct nvmem_config nvmem_cfg = {  			.priv = pcf2127, @@ -253,7 +456,84 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,  		ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);  	} -	return ret; +	/* +	 * Watchdog timer enabled and reset pin /RST activated when timed out. +	 * Select 1Hz clock source for watchdog timer. +	 * Timer is not started until WD_VAL is loaded with a valid value. +	 * Note: Countdown timer disabled and not available. +	 */ +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL, +				 PCF2127_BIT_WD_CTL_CD1 | +				 PCF2127_BIT_WD_CTL_CD0 | +				 PCF2127_BIT_WD_CTL_TF1 | +				 PCF2127_BIT_WD_CTL_TF0, +				 PCF2127_BIT_WD_CTL_CD1 | +				 PCF2127_BIT_WD_CTL_CD0 | +				 PCF2127_BIT_WD_CTL_TF1); +	if (ret) { +		dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__); +		return ret; +	} + +#ifdef CONFIG_WATCHDOG +	ret = devm_watchdog_register_device(dev, &pcf2127->wdd); +	if (ret) +		return ret; +#endif /* CONFIG_WATCHDOG */ + +	/* +	 * Disable battery low/switch-over timestamp and interrupts. +	 * Clear battery interrupt flags which can block new trigger events. +	 * Note: This is the default chip behaviour but added to ensure +	 * correct tamper timestamp and interrupt function. +	 */ +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, +				 PCF2127_BIT_CTRL3_BTSE | +				 PCF2127_BIT_CTRL3_BF | +				 PCF2127_BIT_CTRL3_BIE | +				 PCF2127_BIT_CTRL3_BLIE, 0); +	if (ret) { +		dev_err(dev, "%s: interrupt config (ctrl3) failed\n", +			__func__); +		return ret; +	} + +	/* +	 * Enable timestamp function and store timestamp of first trigger +	 * event until TSF1 and TFS2 interrupt flags are cleared. +	 */ +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL, +				 PCF2127_BIT_TS_CTRL_TSOFF | +				 PCF2127_BIT_TS_CTRL_TSM, +				 PCF2127_BIT_TS_CTRL_TSM); +	if (ret) { +		dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n", +			__func__); +		return ret; +	} + +	/* +	 * Enable interrupt generation when TSF1 or TSF2 timestamp flags +	 * are set. Interrupt signal is an open-drain output and can be +	 * left floating if unused. +	 */ +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, +				 PCF2127_BIT_CTRL2_TSIE, +				 PCF2127_BIT_CTRL2_TSIE); +	if (ret) { +		dev_err(dev, "%s: tamper detection config (ctrl2) failed\n", +			__func__); +		return ret; +	} + +	ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group); +	if (ret) { +		dev_err(dev, "%s: tamper sysfs registering failed\n", +			__func__); +		return ret; +	} + +	return rtc_register_device(pcf2127->rtc);  }  #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index a075e77617dc..3450d615974d 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -166,7 +166,12 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)  	buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);  	ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN, -				tmp, sizeof(tmp)); +				tmp, 2); +	if (ret) +		return ret; + +	ret = regmap_bulk_write(pcf85363->regmap, DT_100THS, +				buf, sizeof(tmp) - 2);  	if (ret)  		return ret; diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index ac159d24286d..24baa4767b11 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -196,8 +196,9 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)   * In the routines that deal directly with the pcf8563 hardware, we use   * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.   */ -static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)  { +	struct i2c_client *client = to_i2c_client(dev);  	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);  	unsigned char buf[9];  	int err; @@ -228,9 +229,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)  	tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);  	tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;  	tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ -	tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]); -	if (tm->tm_year < 70) -		tm->tm_year += 100;	/* assume we are in 1970...2069 */ +	tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]) + 100;  	/* detect the polarity heuristically. see note above. */  	pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?  		(tm->tm_year >= 100) : (tm->tm_year < 100); @@ -244,8 +243,9 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)  	return 0;  } -static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)  { +	struct i2c_client *client = to_i2c_client(dev);  	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);  	unsigned char buf[9]; @@ -266,7 +266,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)  	buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);  	/* year and century */ -	buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100); +	buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year - 100);  	if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))  		buf[PCF8563_REG_MO] |= PCF8563_MO_C; @@ -299,8 +299,8 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long  		 * because of the cached voltage_low value but do it  		 * anyway for consistency.  		 */ -		if (pcf8563_get_datetime(to_i2c_client(dev), &tm)) -			pcf8563_set_datetime(to_i2c_client(dev), &tm); +		if (pcf8563_rtc_read_time(dev, &tm)) +			pcf8563_rtc_set_time(dev, &tm);  		/* Clear the cached value. */  		pcf8563->voltage_low = 0; @@ -314,16 +314,6 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long  #define pcf8563_rtc_ioctl NULL  #endif -static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ -	return pcf8563_get_datetime(to_i2c_client(dev), tm); -} - -static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ -	return pcf8563_set_datetime(to_i2c_client(dev), tm); -} -  static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)  {  	struct i2c_client *client = to_i2c_client(dev); @@ -591,13 +581,17 @@ static int pcf8563_probe(struct i2c_client *client,  		return err;  	} -	pcf8563->rtc = devm_rtc_device_register(&client->dev, -				pcf8563_driver.driver.name, -				&pcf8563_rtc_ops, THIS_MODULE); - +	pcf8563->rtc = devm_rtc_allocate_device(&client->dev);  	if (IS_ERR(pcf8563->rtc))  		return PTR_ERR(pcf8563->rtc); +	pcf8563->rtc->ops = &pcf8563_rtc_ops; +	/* the pcf8563 alarm only supports a minute accuracy */ +	pcf8563->rtc->uie_unsupported = 1; +	pcf8563->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; +	pcf8563->rtc->range_max = RTC_TIMESTAMP_END_2099; +	pcf8563->rtc->set_start_time = true; +  	if (client->irq > 0) {  		err = devm_request_threaded_irq(&client->dev, client->irq,  				NULL, pcf8563_irq, @@ -608,17 +602,17 @@ static int pcf8563_probe(struct i2c_client *client,  								client->irq);  			return err;  		} -  	} +	err = rtc_register_device(pcf8563->rtc); +	if (err) +		return err; +  #ifdef CONFIG_COMMON_CLK  	/* register clk in common clk framework */  	pcf8563_clkout_register_clk(pcf8563);  #endif -	/* the pcf8563 alarm only supports a minute accuracy */ -	pcf8563->rtc->uie_unsupported = 1; -  	return 0;  } @@ -632,6 +626,8 @@ MODULE_DEVICE_TABLE(i2c, pcf8563_id);  #ifdef CONFIG_OF  static const struct of_device_id pcf8563_of_match[] = {  	{ .compatible = "nxp,pcf8563" }, +	{ .compatible = "epson,rtc8564" }, +	{ .compatible = "microcrystal,rv8564" },  	{}  };  MODULE_DEVICE_TABLE(of, pcf8563_of_match); diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c index 1c4de6e90da0..17653ed52ebb 100644 --- a/drivers/rtc/rtc-pic32.c +++ b/drivers/rtc/rtc-pic32.c @@ -308,10 +308,8 @@ static int pic32_rtc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, pdata);  	pdata->alarm_irq = platform_get_irq(pdev, 0); -	if (pdata->alarm_irq < 0) { -		dev_err(&pdev->dev, "no irq for alarm\n"); +	if (pdata->alarm_irq < 0)  		return pdata->alarm_irq; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	pdata->reg_base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 9f9839c47e2f..f5a30e0f16c2 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -468,10 +468,8 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)  	}  	rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); -	if (rtc_dd->rtc_alarm_irq < 0) { -		dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); +	if (rtc_dd->rtc_alarm_irq < 0)  		return -ENXIO; -	}  	rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node,  						      "allow-set-time"); diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 63b9e73fb97d..89ff713163dd 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -186,16 +186,12 @@ static int puv3_rtc_probe(struct platform_device *pdev)  	/* find the IRQs */  	puv3_rtc_tickno = platform_get_irq(pdev, 1); -	if (puv3_rtc_tickno < 0) { -		dev_err(&pdev->dev, "no irq for rtc tick\n"); +	if (puv3_rtc_tickno < 0)  		return -ENOENT; -	}  	puv3_rtc_alarmno = platform_get_irq(pdev, 0); -	if (puv3_rtc_alarmno < 0) { -		dev_err(&pdev->dev, "no irq for alarm\n"); +	if (puv3_rtc_alarmno < 0)  		return -ENOENT; -	}  	dev_dbg(&pdev->dev, "PKUnity_rtc: tick irq %d, alarm irq %d\n",  		 puv3_rtc_tickno, puv3_rtc_alarmno); @@ -239,10 +235,8 @@ static int puv3_rtc_probe(struct platform_device *pdev)  	/* register RTC and exit */  	rtc->ops = &puv3_rtcops;  	ret = rtc_register_device(rtc); -	if (ret) { -		dev_err(&pdev->dev, "cannot attach rtc\n"); +	if (ret)  		goto err_nortc; -	}  	/* platform setup code should have handled this; sigh */  	if (!device_can_wakeup(&pdev->dev)) diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index a7827fe7fb7b..d2f1d8f754bf 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -324,15 +324,11 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)  	}  	sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0); -	if (sa1100_rtc->irq_1hz < 0) { -		dev_err(dev, "No 1Hz IRQ resource defined\n"); +	if (sa1100_rtc->irq_1hz < 0)  		return -ENXIO; -	}  	sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1); -	if (sa1100_rtc->irq_alarm < 0) { -		dev_err(dev, "No alarm IRQ resource defined\n"); +	if (sa1100_rtc->irq_alarm < 0)  		return -ENXIO; -	}  	pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start,  				resource_size(pxa_rtc->ress)); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index c34540baa12a..c0334c602e88 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -434,12 +434,8 @@ static int rk808_rtc_probe(struct platform_device *pdev)  	rk808_rtc->rtc->ops = &rk808_rtc_ops;  	rk808_rtc->irq = platform_get_irq(pdev, 0); -	if (rk808_rtc->irq < 0) { -		if (rk808_rtc->irq != -EPROBE_DEFER) -			dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n", -				rk808_rtc->irq); +	if (rk808_rtc->irq < 0)  		return rk808_rtc->irq; -	}  	/* request alarm irq of rk808 */  	ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL, diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index 06884ebb7a61..2b316661a578 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -639,9 +639,8 @@ static int rv3028_probe(struct i2c_client *client)  		dev_warn(&client->dev, "An alarm may have been missed.\n");  	rv3028->rtc = devm_rtc_allocate_device(&client->dev); -	if (IS_ERR(rv3028->rtc)) { +	if (IS_ERR(rv3028->rtc))  		return PTR_ERR(rv3028->rtc); -	}  	if (client->irq > 0) {  		ret = devm_request_threaded_irq(&client->dev, client->irq, diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 4a0e8ec015cc..4cdf6588e1d9 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -278,13 +278,13 @@ static int rv3029_eeprom_read(struct device *dev, u8 reg,  static int rv3029_eeprom_write(struct device *dev, u8 reg,  			       u8 const buf[], size_t len)  { -	int ret; +	int ret, err;  	size_t i;  	u8 tmp; -	ret = rv3029_eeprom_enter(dev); -	if (ret < 0) -		return ret; +	err = rv3029_eeprom_enter(dev); +	if (err < 0) +		return err;  	for (i = 0; i < len; i++, reg++) {  		ret = rv3029_read_regs(dev, reg, &tmp, 1); @@ -300,11 +300,11 @@ static int rv3029_eeprom_write(struct device *dev, u8 reg,  			break;  	} -	ret = rv3029_eeprom_exit(dev); -	if (ret < 0) -		return ret; +	err = rv3029_eeprom_exit(dev); +	if (err < 0) +		return err; -	return 0; +	return ret;  }  static int rv3029_eeprom_update_bits(struct device *dev, diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index fc5243400108..4960f0a2b249 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -564,9 +564,8 @@ static int rv8803_probe(struct i2c_client *client,  		dev_warn(&client->dev, "An alarm maybe have been missed.\n");  	rv8803->rtc = devm_rtc_allocate_device(&client->dev); -	if (IS_ERR(rv8803->rtc)) { +	if (IS_ERR(rv8803->rtc))  		return PTR_ERR(rv8803->rtc); -	}  	if (client->irq > 0) {  		err = devm_request_threaded_irq(&client->dev, client->irq, diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 84806ff763cf..da34cfd70f95 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -434,37 +434,32 @@ static int s35390a_probe(struct i2c_client *client,  	char buf, status1;  	struct device *dev = &client->dev; -	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { -		err = -ENODEV; -		goto exit; -	} +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) +		return -ENODEV;  	s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL); -	if (!s35390a) { -		err = -ENOMEM; -		goto exit; -	} +	if (!s35390a) +		return -ENOMEM;  	s35390a->client[0] = client;  	i2c_set_clientdata(client, s35390a);  	/* This chip uses multiple addresses, use dummy devices for them */  	for (i = 1; i < 8; ++i) { -		s35390a->client[i] = i2c_new_dummy(client->adapter, -					client->addr + i); -		if (!s35390a->client[i]) { +		s35390a->client[i] = devm_i2c_new_dummy_device(dev, +							       client->adapter, +							       client->addr + i); +		if (IS_ERR(s35390a->client[i])) {  			dev_err(dev, "Address %02x unavailable\n",  				client->addr + i); -			err = -EBUSY; -			goto exit_dummy; +			return PTR_ERR(s35390a->client[i]);  		}  	}  	err_read = s35390a_read_status(s35390a, &status1);  	if (err_read < 0) { -		err = err_read;  		dev_err(dev, "error resetting chip\n"); -		goto exit_dummy; +		return err_read;  	}  	if (status1 & S35390A_FLAG_24H) @@ -478,13 +473,13 @@ static int s35390a_probe(struct i2c_client *client,  		err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);  		if (err < 0) {  			dev_err(dev, "error disabling alarm"); -			goto exit_dummy; +			return err;  		}  	} else {  		err = s35390a_disable_test_mode(s35390a);  		if (err < 0) {  			dev_err(dev, "error disabling test mode\n"); -			goto exit_dummy; +			return err;  		}  	} @@ -493,10 +488,8 @@ static int s35390a_probe(struct i2c_client *client,  	s35390a->rtc = devm_rtc_device_register(dev, s35390a_driver.driver.name,  						&s35390a_rtc_ops, THIS_MODULE); -	if (IS_ERR(s35390a->rtc)) { -		err = PTR_ERR(s35390a->rtc); -		goto exit_dummy; -	} +	if (IS_ERR(s35390a->rtc)) +		return PTR_ERR(s35390a->rtc);  	/* supports per-minute alarms only, therefore set uie_unsupported */  	s35390a->rtc->uie_unsupported = 1; @@ -505,26 +498,6 @@ static int s35390a_probe(struct i2c_client *client,  		rtc_update_irq(s35390a->rtc, 1, RTC_AF);  	return 0; - -exit_dummy: -	for (i = 1; i < 8; ++i) -		if (s35390a->client[i]) -			i2c_unregister_device(s35390a->client[i]); - -exit: -	return err; -} - -static int s35390a_remove(struct i2c_client *client) -{ -	unsigned int i; -	struct s35390a *s35390a = i2c_get_clientdata(client); - -	for (i = 1; i < 8; ++i) -		if (s35390a->client[i]) -			i2c_unregister_device(s35390a->client[i]); - -	return 0;  }  static struct i2c_driver s35390a_driver = { @@ -533,7 +506,6 @@ static struct i2c_driver s35390a_driver = {  		.of_match_table = of_match_ptr(s35390a_of_match),  	},  	.probe		= s35390a_probe, -	.remove		= s35390a_remove,  	.id_table	= s35390a_id,  }; diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 74bf6473a05d..7801249c254b 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -453,10 +453,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)  	/* find the IRQs */  	info->irq_tick = platform_get_irq(pdev, 1); -	if (info->irq_tick < 0) { -		dev_err(&pdev->dev, "no irq for rtc tick\n"); +	if (info->irq_tick < 0)  		return info->irq_tick; -	}  	info->dev = &pdev->dev;  	info->data = of_device_get_match_data(&pdev->dev); @@ -470,10 +468,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, info);  	info->irq_alarm = platform_get_irq(pdev, 0); -	if (info->irq_alarm < 0) { -		dev_err(&pdev->dev, "no irq for alarm\n"); +	if (info->irq_alarm < 0)  		return info->irq_alarm; -	}  	dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",  		info->irq_tick, info->irq_alarm); diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index c7f1bf823ea0..eb9dde4095a9 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -760,10 +760,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	info->i2c = i2c_new_dummy(s5m87xx->i2c->adapter, RTC_I2C_ADDR); -	if (!info->i2c) { +	info->i2c = i2c_new_dummy_device(s5m87xx->i2c->adapter, RTC_I2C_ADDR); +	if (IS_ERR(info->i2c)) {  		dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); -		return -ENODEV; +		return PTR_ERR(info->i2c);  	}  	info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index b4eb3b3c6c2c..b95676899750 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -138,7 +138,7 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock)  	if (ret)  		return ret; -	val &= ~(SPRD_RTC_ALMLOCK_MASK | SPRD_RTC_POWEROFF_ALM_FLAG); +	val &= ~SPRD_RTC_ALMLOCK_MASK;  	if (lock)  		val |= SPRD_RTC_ALM_LOCK;  	else @@ -614,10 +614,8 @@ static int sprd_rtc_probe(struct platform_device *pdev)  	}  	rtc->irq = platform_get_irq(pdev, 0); -	if (rtc->irq < 0) { -		dev_err(&pdev->dev, "failed to get RTC irq number\n"); +	if (rtc->irq < 0)  		return rtc->irq; -	}  	rtc->rtc = devm_rtc_allocate_device(&pdev->dev);  	if (IS_ERR(rtc->rtc)) @@ -656,7 +654,6 @@ static int sprd_rtc_probe(struct platform_device *pdev)  	rtc->rtc->range_max = 5662310399LL;  	ret = rtc_register_device(rtc->rtc);  	if (ret) { -		dev_err(&pdev->dev, "failed to register rtc device\n");  		device_init_wakeup(&pdev->dev, 0);  		return ret;  	} diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index 42cb90db7f94..a7aa943c1183 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -193,10 +193,8 @@ static int sd3078_probe(struct i2c_client *client,  	sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099;  	ret = rtc_register_device(sd3078->rtc); -	if (ret) { -		dev_err(&client->dev, "failed to register rtc device\n"); +	if (ret)  		return ret; -	}  	sd3078_enable_reg_write(sd3078); diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 7ee673a25fd0..757f4daa7181 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -151,7 +151,7 @@ static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)  	struct snvs_rtc_data *data = dev_get_drvdata(dev);  	unsigned long time = rtc_read_lp_counter(data); -	rtc_time_to_tm(time, tm); +	rtc_time64_to_tm(time, tm);  	return 0;  } @@ -159,11 +159,9 @@ static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)  static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)  {  	struct snvs_rtc_data *data = dev_get_drvdata(dev); -	unsigned long time; +	unsigned long time = rtc_tm_to_time64(tm);  	int ret; -	rtc_tm_to_time(tm, &time); -  	/* Disable RTC first */  	ret = snvs_rtc_enable(data, false);  	if (ret) @@ -185,7 +183,7 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)  	u32 lptar, lpsr;  	regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar); -	rtc_time_to_tm(lptar, &alrm->time); +	rtc_time64_to_tm(lptar, &alrm->time);  	regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);  	alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; @@ -207,12 +205,9 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)  static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)  {  	struct snvs_rtc_data *data = dev_get_drvdata(dev); -	struct rtc_time *alrm_tm = &alrm->time; -	unsigned long time; +	unsigned long time = rtc_tm_to_time64(&alrm->time);  	int ret; -	rtc_tm_to_time(alrm_tm, &time); -  	regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);  	ret = rtc_write_sync_lp(data);  	if (ret) @@ -279,6 +274,10 @@ static int snvs_rtc_probe(struct platform_device *pdev)  	if (!data)  		return -ENOMEM; +	data->rtc = devm_rtc_allocate_device(&pdev->dev); +	if (IS_ERR(data->rtc)) +		return PTR_ERR(data->rtc); +  	data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");  	if (IS_ERR(data->regmap)) { @@ -343,10 +342,10 @@ static int snvs_rtc_probe(struct platform_device *pdev)  		goto error_rtc_device_register;  	} -	data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, -					&snvs_rtc_ops, THIS_MODULE); -	if (IS_ERR(data->rtc)) { -		ret = PTR_ERR(data->rtc); +	data->rtc->ops = &snvs_rtc_ops; +	data->rtc->range_max = U32_MAX; +	ret = rtc_register_device(data->rtc); +	if (ret) {  		dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);  		goto error_rtc_device_register;  	} diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 0567944fd4f8..9f23b24f466c 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -358,10 +358,8 @@ static int spear_rtc_probe(struct platform_device *pdev)  	/* alarm irqs */  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "no update irq?\n"); +	if (irq < 0)  		return irq; -	}  	status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name,  			config); diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 773a1990b93f..2999e33a7e37 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -776,7 +776,6 @@ static int stm32_rtc_probe(struct platform_device *pdev)  	rtc->irq_alarm = platform_get_irq(pdev, 0);  	if (rtc->irq_alarm <= 0) { -		dev_err(&pdev->dev, "no alarm irq\n");  		ret = rtc->irq_alarm;  		goto err;  	} diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index c0e75c373605..5e2bd9f1d01e 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -32,9 +32,11 @@  /* Control register */  #define SUN6I_LOSC_CTRL				0x0000  #define SUN6I_LOSC_CTRL_KEY			(0x16aa << 16) +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS		BIT(15)  #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC		BIT(9)  #define SUN6I_LOSC_CTRL_RTC_HMS_ACC		BIT(8)  #define SUN6I_LOSC_CTRL_RTC_YMD_ACC		BIT(7) +#define SUN6I_LOSC_CTRL_EXT_LOSC_EN		BIT(4)  #define SUN6I_LOSC_CTRL_EXT_OSC			BIT(0)  #define SUN6I_LOSC_CTRL_ACC_MASK		GENMASK(9, 7) @@ -128,6 +130,8 @@ struct sun6i_rtc_clk_data {  	unsigned int has_prescaler : 1;  	unsigned int has_out_clk : 1;  	unsigned int export_iosc : 1; +	unsigned int has_losc_en : 1; +	unsigned int has_auto_swt : 1;  };  struct sun6i_rtc_dev { @@ -190,6 +194,10 @@ static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index)  	val &= ~SUN6I_LOSC_CTRL_EXT_OSC;  	val |= SUN6I_LOSC_CTRL_KEY;  	val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0; +	if (rtc->data->has_losc_en) { +		val &= ~SUN6I_LOSC_CTRL_EXT_LOSC_EN; +		val |= index ? SUN6I_LOSC_CTRL_EXT_LOSC_EN : 0; +	}  	writel(val, rtc->base + SUN6I_LOSC_CTRL);  	spin_unlock_irqrestore(&rtc->lock, flags); @@ -215,6 +223,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,  	const char *iosc_name = "rtc-int-osc";  	const char *clkout_name = "osc32k-out";  	const char *parents[2]; +	u32 reg;  	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);  	if (!rtc) @@ -235,9 +244,18 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,  		goto err;  	} +	reg = SUN6I_LOSC_CTRL_KEY; +	if (rtc->data->has_auto_swt) { +		/* Bypass auto-switch to int osc, on ext losc failure */ +		reg |= SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS; +		writel(reg, rtc->base + SUN6I_LOSC_CTRL); +	} +  	/* Switch to the external, more precise, oscillator */ -	writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC, -	       rtc->base + SUN6I_LOSC_CTRL); +	reg |= SUN6I_LOSC_CTRL_EXT_OSC; +	if (rtc->data->has_losc_en) +		reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; +	writel(reg, rtc->base + SUN6I_LOSC_CTRL);  	/* Yes, I know, this is ugly. */  	sun6i_rtc = rtc; @@ -279,7 +297,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,  	of_property_read_string_index(node, "clock-output-names", 1,  				      &clkout_name); -	rtc->ext_losc = clk_register_gate(NULL, clkout_name, rtc->hw.init->name, +	rtc->ext_losc = clk_register_gate(NULL, clkout_name, init.name,  					  0, rtc->base + SUN6I_LOSC_OUT_GATING,  					  SUN6I_LOSC_OUT_GATING_EN_OFFSET, 0,  					  &rtc->lock); @@ -345,6 +363,23 @@ CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc",  CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc",  		      sun8i_h3_rtc_clk_init); +static const struct sun6i_rtc_clk_data sun50i_h6_rtc_data = { +	.rc_osc_rate = 16000000, +	.fixed_prescaler = 32, +	.has_prescaler = 1, +	.has_out_clk = 1, +	.export_iosc = 1, +	.has_losc_en = 1, +	.has_auto_swt = 1, +}; + +static void __init sun50i_h6_rtc_clk_init(struct device_node *node) +{ +	sun6i_rtc_clk_init(node, &sun50i_h6_rtc_data); +} +CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc", +		      sun50i_h6_rtc_clk_init); +  static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {  	.rc_osc_rate = 32000,  	.has_out_clk = 1, @@ -598,6 +633,33 @@ static const struct rtc_class_ops sun6i_rtc_ops = {  	.alarm_irq_enable	= sun6i_rtc_alarm_irq_enable  }; +#ifdef CONFIG_PM_SLEEP +/* Enable IRQ wake on suspend, to wake up from RTC. */ +static int sun6i_rtc_suspend(struct device *dev) +{ +	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		enable_irq_wake(chip->irq); + +	return 0; +} + +/* Disable IRQ wake on resume. */ +static int sun6i_rtc_resume(struct device *dev) +{ +	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + +	if (device_may_wakeup(dev)) +		disable_irq_wake(chip->irq); + +	return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(sun6i_rtc_pm_ops, +	sun6i_rtc_suspend, sun6i_rtc_resume); +  static int sun6i_rtc_probe(struct platform_device *pdev)  {  	struct sun6i_rtc_dev *chip = sun6i_rtc; @@ -610,10 +672,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)  	chip->dev = &pdev->dev;  	chip->irq = platform_get_irq(pdev, 0); -	if (chip->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource\n"); +	if (chip->irq < 0)  		return chip->irq; -	}  	ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq,  			       0, dev_name(&pdev->dev), chip); @@ -650,6 +710,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)  	clk_prepare_enable(chip->losc); +	device_init_wakeup(&pdev->dev, 1); +  	chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i",  					     &sun6i_rtc_ops, THIS_MODULE);  	if (IS_ERR(chip->rtc)) { @@ -675,6 +737,7 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {  	{ .compatible = "allwinner,sun8i-r40-rtc" },  	{ .compatible = "allwinner,sun8i-v3-rtc" },  	{ .compatible = "allwinner,sun50i-h5-rtc" }, +	{ .compatible = "allwinner,sun50i-h6-rtc" },  	{ /* sentinel */ },  };  MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); @@ -684,6 +747,7 @@ static struct platform_driver sun6i_rtc_driver = {  	.driver		= {  		.name		= "sun6i-rtc",  		.of_match_table = sun6i_rtc_dt_ids, +		.pm = &sun6i_rtc_pm_ops,  	},  };  builtin_platform_driver(sun6i_rtc_driver); diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index 6eeabb81106f..9b6f2483c1c6 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -442,10 +442,8 @@ static int sunxi_rtc_probe(struct platform_device *pdev)  		return PTR_ERR(chip->base);  	chip->irq = platform_get_irq(pdev, 0); -	if (chip->irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource\n"); +	if (chip->irq < 0)  		return chip->irq; -	}  	ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq,  			0, dev_name(&pdev->dev), chip);  	if (ret) { @@ -474,15 +472,7 @@ static int sunxi_rtc_probe(struct platform_device *pdev)  	chip->rtc->ops = &sunxi_rtc_ops; -	ret = rtc_register_device(chip->rtc); -	if (ret) { -		dev_err(&pdev->dev, "unable to register device\n"); -		return ret; -	} - -	dev_info(&pdev->dev, "RTC enabled\n"); - -	return 0; +	return rtc_register_device(chip->rtc);  }  static struct platform_driver sunxi_rtc_driver = { diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 8fa1b3febf69..69d695bf9500 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -290,10 +290,8 @@ static int tegra_rtc_probe(struct platform_device *pdev)  		return PTR_ERR(info->base);  	ret = platform_get_irq(pdev, 0); -	if (ret <= 0) { -		dev_err(&pdev->dev, "failed to get platform IRQ: %d\n", ret); +	if (ret <= 0)  		return ret; -	}  	info->irq = ret; @@ -334,10 +332,8 @@ static int tegra_rtc_probe(struct platform_device *pdev)  	}  	ret = rtc_register_device(info->rtc); -	if (ret) { -		dev_err(&pdev->dev, "failed to register device: %d\n", ret); +	if (ret)  		goto disable_clk; -	}  	dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index d6434e514a52..859d901fa6cb 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -259,7 +259,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)  	rtc->rtc = devm_rtc_allocate_device(&pdev->dev);  	if (IS_ERR(rtc->rtc)) {  		ret = PTR_ERR(rtc->rtc); -		dev_err(&pdev->dev, "RTC allocate device: ret %d\n", ret);  		goto fail_rtc_register;  	} @@ -280,10 +279,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)  	disable_irq(rtc->irq);  	ret = rtc_register_device(rtc->rtc); -	if (ret) { -		dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); +	if (ret)  		goto fail_rtc_register; -	}  	return 0; diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 7078f6da1cbc..2c0467a9e717 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -425,13 +425,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)  	tps_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;  	tps_rtc->rtc->range_max = RTC_TIMESTAMP_END_2099; -	ret = rtc_register_device(tps_rtc->rtc); -	if (ret) { -		dev_err(&pdev->dev, "RTC device register: err %d\n", ret); -		return ret; -	} - -	return 0; +	return rtc_register_device(tps_rtc->rtc);  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index f59d232810de..d5d14cf86e0d 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -212,10 +212,8 @@ static int vt8500_rtc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, vt8500_rtc);  	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"); +	if (vt8500_rtc->irq_alarm < 0)  		return vt8500_rtc->irq_alarm; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	vt8500_rtc->regbase = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index 9888383f0088..9683fbf7c78d 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -157,10 +157,8 @@ static int xgene_rtc_probe(struct platform_device *pdev)  		return PTR_ERR(pdata->rtc);  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "No IRQ resource\n"); +	if (irq < 0)  		return irq; -	}  	ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0,  			       dev_name(&pdev->dev), pdata);  	if (ret) { diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 00639594de0c..2c762757fb54 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -218,10 +218,8 @@ static int xlnx_rtc_probe(struct platform_device *pdev)  		return PTR_ERR(xrtcdev->reg_base);  	xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm"); -	if (xrtcdev->alarm_irq < 0) { -		dev_err(&pdev->dev, "no irq resource\n"); +	if (xrtcdev->alarm_irq < 0)  		return xrtcdev->alarm_irq; -	}  	ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq,  			       xlnx_rtc_interrupt, 0,  			       dev_name(&pdev->dev), xrtcdev); @@ -231,10 +229,8 @@ static int xlnx_rtc_probe(struct platform_device *pdev)  	}  	xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec"); -	if (xrtcdev->sec_irq < 0) { -		dev_err(&pdev->dev, "no irq resource\n"); +	if (xrtcdev->sec_irq < 0)  		return xrtcdev->sec_irq; -	}  	ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq,  			       xlnx_rtc_interrupt, 0,  			       dev_name(&pdev->dev), xrtcdev);  |