From 874532cdeefefa4c531189ceaf57d05d2daafdbb Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 16:12:17 +0800 Subject: [PATCH 01/51] rtc: mxc_v2: use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/20190717081217.30518-1-Anson.Huang@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc_v2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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); From f7234a9813b764d3d0ffa67c9f983316bab7a58d Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 16:14:11 +0800 Subject: [PATCH 02/51] rtc: imxdi: use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/20190717081411.30622-1-Anson.Huang@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-imxdi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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); From 564225415e7791f809122d8d16f089d276686bda Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 16:09:21 +0200 Subject: [PATCH 03/51] dt-bindings: rtc: Remove the PCF8563 from the trivial RTCs The PCF8563 has a binding of its own, with some, clocks related, additional properties. Remove it from the trivial RTC bindings. Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20190722140921.22681-1-maxime.ripard@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/trivial-rtc.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml index 0c12ce9a9b45..18cb456752f6 100644 --- a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml @@ -52,8 +52,6 @@ properties: - nxp,pcf2127 # Real-time clock - nxp,pcf2129 - # Real-time clock/calendar - - nxp,pcf8563 # Real-time Clock Module - pericom,pt7c4338 # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC From 46eabee1f6e6495ea465d7ad8bb971c40ba4dc9e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:15 +0200 Subject: [PATCH 04/51] rtc: isl12026: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190722172618.4061-2-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl12026.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); From 7150710f3084de8d35ce3221eeae2caee8813f92 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:16 +0200 Subject: [PATCH 05/51] rtc: max77686: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20190722172618.4061-3-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 4aff349ae301..3d924c34fd73 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -693,11 +693,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 = i2c_new_dummy_device(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, From ca83542cdb5c14dd369de2539bdca2670d89feea Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:17 +0200 Subject: [PATCH 06/51] rtc: s35390a: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190722172618.4061-4-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 84806ff763cf..d773fd597bd5 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -450,12 +450,12 @@ static int s35390a_probe(struct i2c_client *client, /* 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] = i2c_new_dummy_device(client->adapter, + client->addr + i); + if (IS_ERR(s35390a->client[i])) { dev_err(dev, "Address %02x unavailable\n", client->addr + i); - err = -EBUSY; + err = PTR_ERR(s35390a->client[i]); goto exit_dummy; } } From aae364d2a88897e1b3ac0f53414dab39726b80e9 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:18 +0200 Subject: [PATCH 07/51] rtc: s5m: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20190722172618.4061-5-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s5m.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); From cb3cab06142eaa157bf5666c4e514ef087bf4323 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 22:27:42 +0200 Subject: [PATCH 08/51] rtc: remove w90x900/nuc900 driver The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190809202749.742267-15-arnd@arndb.de Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 7 - drivers/rtc/Makefile | 1 - drivers/rtc/rtc-nuc900.c | 271 --------------------------------------- 3 files changed, 279 deletions(-) delete mode 100644 drivers/rtc/rtc-nuc900.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e72f65b61176..2805cbb32ade 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1247,13 +1247,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 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6b09c21dc1b6..9fe0e938272c 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -113,7 +113,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/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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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 "); -MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-rtc"); From 41a8e19f47dfe9154c56b35842700ad38a7c33e0 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 12 Aug 2019 09:36:11 +0300 Subject: [PATCH 09/51] rtc: bd70528: fix driver dependencies With CONFIG_BD70528_WATCHDOG=m, a built-in rtc driver cannot call into the low-level functions that are part of the watchdog module: drivers/rtc/rtc-bd70528.o: In function `bd70528_set_time': rtc-bd70528.c:(.text+0x22c): undefined reference to `bd70528_wdt_lock' rtc-bd70528.c:(.text+0x2a8): undefined reference to `bd70528_wdt_unlock' drivers/rtc/rtc-bd70528.o: In function `bd70528_set_rtc_based_timers': rtc-bd70528.c:(.text+0x50c): undefined reference to `bd70528_wdt_set' Add a Kconfig dependency which forces RTC to be a module if watchdog is a module. If watchdog is not compiled at all the stub functions for watchdog control are used. compiling the RTC without watchdog is fine. Fixes: 32a4a4ebf768 ("rtc: bd70528: Initial support for ROHM bd70528 RTC") Suggested-by: Arnd Bergmann Reported-by: kbuild test robot Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/84462e01e43d39024948a3bdd24087ff87dc2255.1565591387.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2805cbb32ade..24d16030d60c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -500,6 +500,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. From b0a3fa44659ccee87215600b4235982bc0f3e828 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Wed, 7 Aug 2019 16:23:10 +0800 Subject: [PATCH 10/51] rtc: mxc: use spin_lock_irqsave instead of spin_lock_irq in IRQ context As spin_unlock_irq will enable interrupts. mxc_rtc_irq_enable is called from interrupt handler mxc_rtc_interrupt. Interrupts are enabled in interrupt handler. Use spin_lock_irqsave/spin_unlock_irqrestore instead of spin_(un)lock_irq in IRQ context to avoid this. Signed-off-by: Fuqian Huang Link: https://lore.kernel.org/r/20190807082310.10135-1-huangfq.daxian@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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. */ From faac910201e9beb66530bd8c3fe8a02d907ee2a9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:39 -0700 Subject: [PATCH 11/51] rtc: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: linux-rtc@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-40-swboyd@chromium.org Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 1 - drivers/rtc/rtc-88pm860x.c | 4 +--- drivers/rtc/rtc-ac100.c | 4 +--- drivers/rtc/rtc-armada38x.c | 5 +---- drivers/rtc/rtc-asm9260.c | 4 +--- drivers/rtc/rtc-at91rm9200.c | 4 +--- drivers/rtc/rtc-at91sam9.c | 4 +--- drivers/rtc/rtc-bd70528.c | 5 +---- drivers/rtc/rtc-davinci.c | 4 +--- drivers/rtc/rtc-jz4740.c | 4 +--- drivers/rtc/rtc-max77686.c | 5 +---- drivers/rtc/rtc-mt7622.c | 1 - drivers/rtc/rtc-pic32.c | 4 +--- drivers/rtc/rtc-pm8xxx.c | 4 +--- drivers/rtc/rtc-puv3.c | 8 ++------ drivers/rtc/rtc-pxa.c | 8 ++------ drivers/rtc/rtc-rk808.c | 6 +----- drivers/rtc/rtc-s3c.c | 8 ++------ drivers/rtc/rtc-sc27xx.c | 4 +--- drivers/rtc/rtc-spear.c | 4 +--- drivers/rtc/rtc-stm32.c | 1 - drivers/rtc/rtc-sun6i.c | 4 +--- drivers/rtc/rtc-sunxi.c | 4 +--- drivers/rtc/rtc-tegra.c | 4 +--- drivers/rtc/rtc-vt8500.c | 4 +--- drivers/rtc/rtc-xgene.c | 4 +--- drivers/rtc/rtc-zynqmp.c | 8 ++------ 27 files changed, 28 insertions(+), 92 deletions(-) diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index e4d5a19fd1c9..9aa4a59dbf47 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; } 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-ac100.c b/drivers/rtc/rtc-ac100.c index 2e5a8b15b222..a4dcf2950396 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)) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 19d6980e90fb..8e8b8079b60a 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -530,11 +530,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)) 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-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..3e745c05bc22 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); 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-jz4740.c b/drivers/rtc/rtc-jz4740.c index 9e7b3a04debc..3ec6bb230cd5 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); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 3d924c34fd73..7a98e0744878 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; } 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-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..56a7cf1547a7 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); 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-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-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index b4eb3b3c6c2c..698e1e51efca 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -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)) 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..dbd676db431e 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -610,10 +610,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); diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index 6eeabb81106f..0bb69a7f9e46 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) { diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 8fa1b3febf69..14bf835229e6 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; 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); From 5bdf40dab622d301757f81325d9b80902b3bbae7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:48 +0200 Subject: [PATCH 12/51] rtc: pcf2123: don't use weekday alarm The week day may not be set properly by userspace. This would result is missed alarms. Disable alarm matching on weekday. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index fb542a930bf0..5f604d83289c 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 */ @@ -288,7 +288,7 @@ 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, sizeof(txbuf)); From d0ce6ef7146692a1540b4dd3a68970da6bcd5207 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:49 +0200 Subject: [PATCH 13/51] rtc; pcf2123: fix possible alarm race condition Clear the flag after disabling the alarm to ensure the alarm doesn't fire between clearing the flag and disabling the alarm. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-2-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 5f604d83289c..829d7a2dd950 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -274,13 +274,13 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 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(pdata->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(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); if (ret) return ret; From 577f648207e0ede8153997c7195d4cb31268f410 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:50 +0200 Subject: [PATCH 14/51] rtc: pcf2123: implement .alarm_irq_enable Implement .alarm_irq_enable so it is possible to use RTC_ALM_SET, RTC_AIE_ON and RTC_AIE_OFF. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-3-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 829d7a2dd950..809c35c8ba1a 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -238,6 +238,14 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) return 0; } +static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + + return regmap_update_bits(pdata->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); @@ -295,15 +303,7 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 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) @@ -372,6 +372,7 @@ 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) From d3bad6026f0bd34df11aedb1b41c432df8005eda Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:51 +0200 Subject: [PATCH 15/51] rtc: pcf2123: stop using dev.platform_data platform_data is for platform specific data, use driver_data instead. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-4-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 809c35c8ba1a..efbf3a371b5e 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -119,7 +119,7 @@ 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_plat_data *pdata = dev_get_drvdata(dev); int ret, val; unsigned int reg; @@ -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_plat_data *pdata = dev_get_drvdata(dev); s8 reg; if (offset > OFFSET_STEP * 127) @@ -174,7 +174,7 @@ static int pcf2123_set_offset(struct device *dev, long offset) static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_plat_data *pdata = dev_get_drvdata(dev); u8 rxbuf[7]; int ret; @@ -205,7 +205,7 @@ 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_plat_data *pdata = dev_get_drvdata(dev); u8 txbuf[7]; int ret; @@ -248,7 +248,7 @@ static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_plat_data *pdata = dev_get_drvdata(dev); u8 rxbuf[4]; int ret; unsigned int val = 0; @@ -276,7 +276,7 @@ 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_plat_data *pdata = dev_get_drvdata(dev); u8 txbuf[4]; int ret; @@ -308,7 +308,7 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_plat_data *pdata = dev_get_drvdata(dev); struct mutex *lock = &pdata->rtc->ops_lock; unsigned int val = 0; int ret = IRQ_NONE; @@ -333,7 +333,7 @@ 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_plat_data *pdata = dev_get_drvdata(dev); int ret; unsigned int val = 0; @@ -386,7 +386,8 @@ static int pcf2123_probe(struct spi_device *spi) GFP_KERNEL); if (!pdata) return -ENOMEM; - spi->dev.platform_data = pdata; + + dev_set_drvdata(&spi->dev, pdata); pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); @@ -419,6 +420,7 @@ static int pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; + /* Register alarm irq */ if (spi->irq > 0) { ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, @@ -440,7 +442,6 @@ static int pcf2123_probe(struct spi_device *spi) return 0; kfree_exit: - spi->dev.platform_data = NULL; return ret; } From 9126a2b16b678fd14fa2171e2f05395ecb229a2c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:52 +0200 Subject: [PATCH 16/51] rtc: pcf2123: rename struct and variables Rename struct pcf2123_plat_data to struct pcf2123_data and pdata to pcf2123 to make the driver use a more common subsystem style. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-5-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 76 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index efbf3a371b5e..df20dd229140 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -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_drvdata(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_drvdata(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_drvdata(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; @@ -205,14 +205,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_drvdata(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; @@ -225,13 +225,13 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) 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); - 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; @@ -240,20 +240,20 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); - return regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, + 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_drvdata(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; @@ -265,7 +265,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; @@ -276,19 +276,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_drvdata(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); /* Disable alarm interrupt */ - ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); + ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); if (ret) return ret; /* Ensure alarm flag is clear */ - ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); + ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); if (ret) return ret; @@ -298,7 +298,7 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F); 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; @@ -308,22 +308,22 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) { - struct pcf2123_plat_data *pdata = dev_get_drvdata(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 +333,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_drvdata(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 +358,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; @@ -379,19 +379,19 @@ 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; - dev_set_drvdata(&spi->dev, pdata); + dev_set_drvdata(&spi->dev, pcf2123); - pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); + pcf2123->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); - if (IS_ERR(pdata->map)) { + if (IS_ERR(pcf2123->map)) { dev_err(&spi->dev, "regmap init failed.\n"); goto kfree_exit; } @@ -418,7 +418,7 @@ static int pcf2123_probe(struct spi_device *spi) goto kfree_exit; } - pdata->rtc = rtc; + pcf2123->rtc = rtc; /* Register alarm irq */ @@ -437,7 +437,7 @@ 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; + pcf2123->rtc->uie_unsupported = 1; return 0; From 9a5aeaad73ece38c77bc4c955ab3c9a4c5e3277f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:53 +0200 Subject: [PATCH 17/51] rtc: pcf2123: remove useless error path goto kfree_exit only returns ret, remove it. This also fixes the devm_regmap_init_spi error case where the probe wouldn't actually fail because ret is initialized to 0. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-6-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index df20dd229140..aef02193dbcc 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -390,10 +390,9 @@ static int pcf2123_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, pcf2123); 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); @@ -401,7 +400,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; } } @@ -414,8 +413,7 @@ static int pcf2123_probe(struct spi_device *spi) if (IS_ERR(rtc)) { dev_err(&spi->dev, "failed to register.\n"); - ret = PTR_ERR(rtc); - goto kfree_exit; + return PTR_ERR(rtc); } pcf2123->rtc = rtc; @@ -440,9 +438,6 @@ static int pcf2123_probe(struct spi_device *spi) pcf2123->rtc->uie_unsupported = 1; return 0; - -kfree_exit: - return ret; } #ifdef CONFIG_OF From 935a7f45979067e98268546854bd7ef874207a60 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:54 +0200 Subject: [PATCH 18/51] rtc: pcf2123: convert to devm_rtc_allocate_device This allows further improvement of the driver. Also remove the unecessary error string as the core will already display error messages. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-7-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index aef02193dbcc..fd326fd2932e 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -408,17 +408,12 @@ 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"); + rtc = devm_rtc_allocate_device(&spi->dev); + if (IS_ERR(rtc)) return PTR_ERR(rtc); - } pcf2123->rtc = rtc; - /* Register alarm irq */ if (spi->irq > 0) { ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, @@ -435,7 +430,12 @@ static int pcf2123_probe(struct spi_device *spi) * support to this driver to generate interrupts more than once * per minute. */ - pcf2123->rtc->uie_unsupported = 1; + rtc->uie_unsupported = 1; + rtc->ops = &pcf2123_rtc_ops; + + ret = rtc_register_device(rtc); + if (ret) + return ret; return 0; } From d5b626e1350344db7fb1bf68f6089aaceb7df79a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:55 +0200 Subject: [PATCH 19/51] rtc: pcf2123: let the core handle range offsetting Set the RTC range properly and use the core windowing and offsetting to (unfortunately) map back to a 1970-2069 range. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-8-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2123.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index fd326fd2932e..bda4b1687318 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -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); @@ -223,7 +221,7 @@ 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(pcf2123->map, PCF2123_REG_SC, txbuf, sizeof(txbuf)); @@ -432,6 +430,9 @@ static int pcf2123_probe(struct spi_device *spi) */ 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; ret = rtc_register_device(rtc); if (ret) From cb36cf803f3f468baa22b165bc4e67ae88811ad1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 20:26:56 +0200 Subject: [PATCH 20/51] rtc: pcf2123: add proper compatible string nxp,rtc-pcf2123 is not a proper compatible strong for this RTC. The part name is only pcf2123 and is less confusing. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190819182656.29744-9-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt | 4 ++-- drivers/rtc/rtc-pcf2123.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt b/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt index 1994f601800a..7371f525a687 100644 --- a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt +++ b/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt @@ -1,7 +1,7 @@ NXP PCF2123 SPI Real Time Clock Required properties: -- compatible: should be: "nxp,rtc-pcf2123" +- compatible: should be: "nxp,pcf2123" or "microcrystal,rv2123" - reg: should be the SPI slave chipselect address @@ -11,7 +11,7 @@ Optional properties: Example: pcf2123: rtc@3 { - compatible = "nxp,rtc-pcf2123" + compatible = "nxp,pcf2123" reg = <3> spi-cs-high; }; diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index bda4b1687318..c3691fa4210e 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -443,8 +443,10 @@ static int pcf2123_probe(struct spi_device *spi) #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); From 924068e50a6ca426b8fda1d2c06d6d2bde212136 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 00:00:40 +0200 Subject: [PATCH 21/51] rtc: class: add debug message when registration fails Add a message when __rtc_register_device fails because rtc->ops is NULL. This may only happen when developing a new driver so use dev_dbg to avoid compiling it in by default. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190818220041.17833-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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); From 44c638ce4ec6fb9d33978348ebb90847b9aa274a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Aug 2019 00:00:41 +0200 Subject: [PATCH 22/51] rtc: remove superfluous error message The RTC core now has error messages in case of registration failure, there is no need to have other messages in the drivers. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190818220041.17833-2-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 5 ++--- drivers/rtc/rtc-ab-eoz9.c | 24 ++++++++---------------- drivers/rtc/rtc-ac100.c | 10 +--------- drivers/rtc/rtc-armada38x.c | 7 +------ drivers/rtc/rtc-aspeed.c | 7 +------ drivers/rtc/rtc-bd70528.c | 6 +----- drivers/rtc/rtc-brcmstb-waketimer.c | 4 +--- drivers/rtc/rtc-cadence.c | 13 +++---------- drivers/rtc/rtc-ds1305.c | 7 ++----- drivers/rtc/rtc-imx-sc.c | 4 +--- drivers/rtc/rtc-jz4740.c | 4 +--- drivers/rtc/rtc-mt6397.c | 4 +--- drivers/rtc/rtc-puv3.c | 4 +--- drivers/rtc/rtc-rv3028.c | 3 +-- drivers/rtc/rtc-rv8803.c | 3 +-- drivers/rtc/rtc-sc27xx.c | 1 - drivers/rtc/rtc-sd3078.c | 4 +--- drivers/rtc/rtc-sunxi.c | 10 +--------- drivers/rtc/rtc-tegra.c | 4 +--- drivers/rtc/rtc-tps6586x.c | 5 +---- drivers/rtc/rtc-tps65910.c | 8 +------- 21 files changed, 31 insertions(+), 106 deletions(-) diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 9aa4a59dbf47..75779e8501a3 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -295,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-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 a4dcf2950396..29223931aba7 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -610,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 8e8b8079b60a..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) @@ -561,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-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-bd70528.c b/drivers/rtc/rtc-bd70528.c index 3e745c05bc22..7744333b0f40 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -476,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-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-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-jz4740.c b/drivers/rtc/rtc-jz4740.c index 3ec6bb230cd5..3089645e0ce8 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -360,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-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-puv3.c b/drivers/rtc/rtc-puv3.c index 56a7cf1547a7..89ff713163dd 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -235,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-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-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-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 698e1e51efca..3474f7a20493 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -654,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-sunxi.c b/drivers/rtc/rtc-sunxi.c index 0bb69a7f9e46..9b6f2483c1c6 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -472,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 14bf835229e6..69d695bf9500 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -332,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 From 80ba93639b5dfde6b7897499b69fefc733a94a59 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 18 Aug 2019 23:52:32 +0200 Subject: [PATCH 23/51] rtc: ds1672: remove unnecessary check The rtc pointer is already checked earlier, it is not necessary to check it again. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190818215232.17320-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1672.c | 3 --- 1 file changed, 3 deletions(-) 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; From a6f26606ddd03c5eab8b2132f1bfaa768c06158f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 17 Aug 2019 09:56:04 +0300 Subject: [PATCH 24/51] rtc: rv3029: revert error handling patch to rv3029_eeprom_write() My error handling "cleanup" was totally wrong. Both the "err" and "ret" variables are required. The "err" variable holds the error codes for rv3029_eeprom_enter/exit() and the "ret" variable holds the error codes for if actual write fails. In my patch if the write failed, the function probably still returned success. Reported-by: Tom Evans Fixes: 97f5b0379c38 ("rtc: rv3029: Clean up error handling in rv3029_eeprom_write()") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20190817065604.GB29951@mwanda Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv3029c2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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, From ed16239637f6656d3e6656ed1753e70d7823d94f Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 12 Aug 2019 16:28:49 -0700 Subject: [PATCH 25/51] dt-bindings: rtc: new binding for Amlogic VRTC Add binding fo the new VRTC driver for Amlogic SoCs. The 64-bit family of SoCs only has an RTC managed by firmware, and this VRTC driver provides the simple, one-register firmware interface. Reviewed-by: Rob Herring Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20190812232850.8016-2-khilman@kernel.org Signed-off-by: Alexandre Belloni --- .../bindings/rtc/rtc-meson-vrtc.txt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-meson-vrtc.txt diff --git a/Documentation/devicetree/bindings/rtc/rtc-meson-vrtc.txt b/Documentation/devicetree/bindings/rtc/rtc-meson-vrtc.txt new file mode 100644 index 000000000000..c014f54a9853 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-meson-vrtc.txt @@ -0,0 +1,22 @@ +* Amlogic Virtual RTC (VRTC) + +This is a Linux interface to an RTC managed by firmware, hence it's +virtual from a Linux perspective. The interface is 1 register where +an alarm time (in seconds) is to be written. + +Required properties: +- compatible: should be "amlogic,meson-vrtc" +- reg: physical address for the alarm register + +The alarm register is a simple scratch register shared between the +application processors (AP) and the secure co-processor (SCP.) When +the AP suspends, the SCP will use the value of this register to +program an always-on timer before going sleep. When the timer expires, +the SCP will wake up and will then wake the AP. + +Example: + + vrtc: rtc@0a8 { + compatible = "amlogic,meson-vrtc"; + reg = <0x0 0x000a8 0x0 0x4>; + }; From 6ef35398e827dcf321a012c8f7a4d8d739674db6 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 12 Aug 2019 16:28:50 -0700 Subject: [PATCH 26/51] rtc: Add Amlogic Virtual Wake RTC The Amlogic Meson GX SoCs uses a special register to store the time in seconds to wakeup after a system suspend. In order to be able to reuse the RTC wakealarm feature, this driver implements a fake RTC device which uses the system time to deduce a suspend delay. Signed-off-by: Neil Armstrong [khilman: rebase to v5.3-rc, rework and modernization] Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20190812232850.8016-3-khilman@kernel.org Signed-off-by: Alexandre Belloni --- MAINTAINERS | 1 + drivers/rtc/Kconfig | 11 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-meson-vrtc.c | 156 +++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 drivers/rtc/rtc-meson-vrtc.c diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..2ae83e1acb05 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1443,6 +1443,7 @@ F: arch/arm64/boot/dts/amlogic/ F: drivers/pinctrl/meson/ F: drivers/mmc/host/meson* F: drivers/soc/amlogic/ +F: drivers/rtc/rtc-meson* N: meson ARM/Amlogic Meson SoC Sound Drivers diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 24d16030d60c..59fbf8b761b9 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 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9fe0e938272c..bd87a004b346 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -102,6 +102,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 diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c new file mode 100644 index 000000000000..4621a4715179 --- /dev/null +++ b/drivers/rtc/rtc-meson-vrtc.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +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; +} + +#ifdef CONFIG_PM_SLEEP +static int 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 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; +} +#endif +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"); From 1d74f0992991ca3b640d5290c2722e9acdb82c15 Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Tue, 13 Aug 2019 11:01:57 +0800 Subject: [PATCH 27/51] dt-bindings: rtc: add bindings for FlexTimer Module The patch adds bindings for FlexTimer Module Signed-off-by: Biwen Li Link: https://lore.kernel.org/r/20190813030157.48590-2-biwen.li@nxp.com Signed-off-by: Alexandre Belloni --- .../bindings/rtc/rtc-fsl-ftm-alarm.txt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt diff --git a/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt b/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt new file mode 100644 index 000000000000..fffac74999da --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt @@ -0,0 +1,36 @@ +Freescale FlexTimer Module (FTM) Alarm + +Required properties: +- compatible : Should be "fsl,-ftm-alarm", the + supported chips include + "fsl,ls1012a-ftm-alarm" + "fsl,ls1021a-ftm-alarm" + "fsl,ls1028a-ftm-alarm" + "fsl,ls1043a-ftm-alarm" + "fsl,ls1046a-ftm-alarm" + "fsl,ls1088a-ftm-alarm" + "fsl,ls208xa-ftm-alarm" + "fsl,lx2160a-ftm-alarm" +- reg : Specifies base physical address and size of the register sets for the + FlexTimer Module. +- interrupts : Should be the FlexTimer Module interrupt. +- fsl,rcpm-wakeup property and rcpm node : Please refer + Documentation/devicetree/bindings/soc/fsl/rcpm.txt + +Optional properties: +- big-endian: If the host controller is big-endian mode, specify this property. + The default endian mode is little-endian. + +Example: +rcpm: rcpm@1e34040 { + compatible = "fsl,ls1088a-rcpm", "fsl,qoriq-rcpm-2.1+"; + reg = <0x0 0x1e34040 0x0 0x18>; + #fsl,rcpm-wakeup-cells = <6>; +}; + +ftm_alarm0: timer@2800000 { + compatible = "fsl,ls1088a-ftm-alarm"; + reg = <0x0 0x2800000 0x0 0x10000>; + fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>; + interrupts = <0 44 4>; +}; From 7b0b551dbc1e0acb2a3a6a7fbebc3ab9cf68a050 Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Tue, 13 Aug 2019 11:01:56 +0800 Subject: [PATCH 28/51] rtc: fsl-ftm-alarm: add FTM alarm driver For the platforms including LS1012A, LS1021A, LS1028A, LS1043A, LS1046A, LS1088A, LS208xA that has the FlexTimer module, implementing alarm functions within RTC subsystem to wakeup the system when system going to sleep (work with RCPM driver). Signed-off-by: Biwen Li Link: https://lore.kernel.org/r/20190813030157.48590-1-biwen.li@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 15 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-fsl-ftm-alarm.c | 337 ++++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 drivers/rtc/rtc-fsl-ftm-alarm.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 59fbf8b761b9..63bd72a96210 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1328,6 +1328,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 bd87a004b346..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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_LICENSE("GPL"); From 903e259f9caf036cd9046884e5de9aa64447755c Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 20 Aug 2019 17:19:32 +0200 Subject: [PATCH 29/51] dt-bindings: rtc: sun6i: Add compatible for H6 RTC RTC on H6 is similar to the one on H5 SoC, but incompatible in small details. See the driver for description of differences. For example H6 RTC needs to enable the external low speed oscillator. Add new compatible for this RTC. Signed-off-by: Ondrej Jirman Link: https://lore.kernel.org/r/20190820151934.3860-2-megous@megous.com Signed-off-by: Alexandre Belloni --- .../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml index 924622f39c44..d7a57ec4a640 100644 --- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml @@ -25,6 +25,7 @@ properties: - items: - const: allwinner,sun50i-a64-rtc - const: allwinner,sun8i-h3-rtc + - const: allwinner,sun50i-h6-rtc reg: maxItems: 1 @@ -92,6 +93,18 @@ allOf: minItems: 3 maxItems: 3 + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-h6-rtc + + then: + properties: + clock-output-names: + minItems: 3 + maxItems: 3 + - if: properties: compatible: From b60ff2cfb598ddf03d8dcb43ed53c35aa563e04c Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 20 Aug 2019 17:19:33 +0200 Subject: [PATCH 30/51] rtc: sun6i: Add support for H6 RTC RTC on H6 is mostly the same as on H5 and H3. It has slight differences mostly in features that are not yet supported by this driver. Some differences are already stated in the comments in existing code. One other difference is that H6 has extra bit in LOSC_CTRL_REG, called EXT_LOSC_EN to enable/disable external low speed crystal oscillator. It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether external low speed oscillator is working correctly. This patch adds support for enabling LOSC when necessary: - during reparenting - when probing the clock H6 also has capacbility to automatically reparent RTC clock from external crystal oscillator, to internal RC oscillator, if external oscillator fails. This is enabled by default. Disable it during probe. Signed-off-by: Ondrej Jirman Reviewed-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20190820151934.3860-3-megous@megous.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index dbd676db431e..956c0846201f 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; @@ -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, @@ -673,6 +708,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); From e788771cacafa4ae5c4dbfc404cd3579e77a0816 Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Thu, 22 Aug 2019 15:19:32 +0200 Subject: [PATCH 31/51] rtc: pcf2127: convert to devm_rtc_allocate_device This allows further improvement of the driver. Signed-off-by: Bruno Thomsen Link: https://lore.kernel.org/r/20190822131936.18772-1-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2127.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 8632f58fed43..58eb96506e4b 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -237,11 +237,12 @@ 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; + if (has_nvmem) { struct nvmem_config nvmem_cfg = { .priv = pcf2127, @@ -253,7 +254,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg); } - return ret; + return rtc_register_device(pcf2127->rtc); } #ifdef CONFIG_OF From bbfe3a7a1d411888d86d8ab322d14dc93bae42db Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Thu, 22 Aug 2019 15:19:33 +0200 Subject: [PATCH 32/51] rtc: pcf2127: cleanup register and bit defines Cleanup of defines to follow kernel coding style and increase code readability by using same register and bit define style. Change PCF2127_REG_RAM_{addr_MSB,wrt_cmd,rd_cmd} to upper case as kernel coding guide section 12 'Macros, Enums and RTL' states "Names of macros defining constants and labels in enums are capitalized". Improve readability of RAM register comment by making whole sentences. Remove parentheses from register defines as they are only used for expressions and not constants. As there are no clear style for name of registers and bits in the kernel drivers, I suggest the following for at least this driver, but hopefully also other RTC drivers. Register name should follow this convention: [chip]_REG_[reg name] 0xXX Bit name should follow this convention, so it clearly states which chip register it's part of: [chip]_BIT_[reg name]_[bit name] BIT(X) Additionally I suggest bit defines are always placed right below its corresponding register define and using an extra tab indentation for the BIT(X) part. This will visually make it easy to see that bit defines are part of the complete register definition. Rename PCF2127_OSF to PCF2127_BIT_SC_OSF and move it right below PCF2127_REG_SC. This will improve readability of bit checks as it's easy to verify that it uses the correct register. Move end of line comments above register defines as it's more like a heading for 1 register define and up to 8 bit defines or a collection of registers that are close related like timestamp split across 6 registers. Signed-off-by: Bruno Thomsen Link: https://lore.kernel.org/r/20190822131936.18772-2-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2127.c | 59 ++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 58eb96506e4b..cd8def79b379 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -19,26 +19,32 @@ #include #include -#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */ -#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */ +/* Control register 1 */ +#define PCF2127_REG_CTRL1 0x00 +/* Control register 2 */ +#define PCF2127_REG_CTRL2 0x01 +/* Control register 3 */ +#define PCF2127_REG_CTRL3 0x02 +#define PCF2127_BIT_CTRL3_BLF BIT(2) +/* 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 +/* + * 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_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 */ struct pcf2127 { struct rtc_device *rtc; @@ -73,11 +79,12 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) 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 @@ -166,7 +173,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 +199,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,12 +217,12 @@ 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; From 7f43020e3bdb63d65661ed377682702f8b34d3ea Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Thu, 22 Aug 2019 15:19:34 +0200 Subject: [PATCH 33/51] rtc: pcf2127: bugfix: read rtc disables watchdog The previous fix listed bulk read of registers as root cause of accendential disabling of watchdog, since the watchdog counter register (WD_VAL) was zeroed. Fixes: 3769a375ab83 rtc: pcf2127: bulk read only date and time registers. Tested with the same PCF2127 chip as Sean reveled root cause of WD_VAL register value zeroing was caused by reading CTRL2 register which is one of the watchdog feature control registers. So the solution is to not read the first two control registers (CTRL1 and CTRL2) in pcf2127_rtc_read_time as they are not needed anyway. Size of local buf variable is kept to allow easy usage of register defines to improve readability of code. Debug trace line was updated after CTRL1 and CTRL2 are no longer read from the chip. Also replaced magic numbers in buf access with register defines. Signed-off-by: Bruno Thomsen Link: https://lore.kernel.org/r/20190822131936.18772-3-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2127.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index cd8def79b379..ee4921e4a47c 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -60,20 +60,14 @@ 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; @@ -95,14 +89,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); From 0e735eaae1650a2e26835cc776f496e06a87be9f Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Thu, 22 Aug 2019 15:19:35 +0200 Subject: [PATCH 34/51] rtc: pcf2127: add watchdog feature support Add partial support for the watchdog functionality of both PCF2127 and PCF2129 chips. The programmable watchdog timer is currently using a fixed clock source of 1Hz. This result in a selectable range of 1-255 seconds, which covers most embedded Linux use-cases. Clock sources of 4096Hz, 64Hz and 1/60Hz is mostly useful in MCU use-cases. Countdown timer not available when using watchdog feature. Signed-off-by: Bruno Thomsen Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20190822131936.18772-4-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 7 ++- drivers/rtc/rtc-pcf2127.c | 118 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 63bd72a96210..758f7a417470 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -888,7 +888,12 @@ config RTC_DRV_PCF2127 depends on RTC_I2C_AND_SPI 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. diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index ee4921e4a47c..8d6eda455d81 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -5,6 +5,9 @@ * * Author: Renaud Cerrato * + * Watchdog and tamper functions + * Author: Bruno Thomsen + * * based on the other drivers in this same directory. * * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf @@ -18,6 +21,7 @@ #include #include #include +#include /* Control register 1 */ #define PCF2127_REG_CTRL1 0x00 @@ -35,6 +39,13 @@ #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 /* * RAM registers * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is @@ -45,9 +56,15 @@ #define PCF2127_REG_RAM_WRT_CMD 0x1C #define PCF2127_REG_RAM_RD_CMD 0x1D +/* 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; }; @@ -220,6 +237,74 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset, 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, +}; + static int pcf2127_probe(struct device *dev, struct regmap *regmap, const char *name, bool has_nvmem) { @@ -242,6 +327,16 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, 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,6 +348,29 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg); } + /* + * 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; + } + + ret = devm_watchdog_register_device(dev, &pcf2127->wdd); + if (ret) + return ret; + return rtc_register_device(pcf2127->rtc); } From 03623b4b041cde396641399c343f52ce840d349d Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Thu, 22 Aug 2019 15:19:36 +0200 Subject: [PATCH 35/51] rtc: pcf2127: add tamper detection support Add support for integrated tamper detection function in both PCF2127 and PCF2129 chips. This patch implements the feature by adding an additional timestamp0 file to sysfs device path. This file contains seconds since epoch, if an event occurred, or is empty, if none occurred. Interface should match ISL1208 and RV3028 RTC drivers. Signed-off-by: Bruno Thomsen Link: https://lore.kernel.org/r/20190822131936.18772-5-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf2127.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 8d6eda455d81..3ec87d320766 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -25,11 +25,18 @@ /* 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) @@ -46,6 +53,16 @@ #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 @@ -305,6 +322,97 @@ static const struct watchdog_ops pcf2127_watchdog_ops = { .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) { @@ -371,6 +479,58 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + /* + * 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); } From 28abbba36a5a9f35bfaa75bf8ee0ebf2fe40b9e3 Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Tue, 27 Aug 2019 16:36:56 +0200 Subject: [PATCH 36/51] rtc: pcf2127: bugfix: watchdog build dependency Disable watchdog registation when kernel is build without watchdog functionality, and enable watchdog core otherwise. This removes compile errors like the one below: drivers/rtc/rtc-pcf2127.o: in function `pcf2127_probe.constprop.3': rtc-pcf2127.c:(.text.unlikely+0x2c8): undefined reference to `devm_watchdog_register_device' Watchdog feature in chip will always be configured as this is safe to do in both cases and minimize code churn. Reported-by: Hulk Robot Reported-by: YueHaibing Fixes: bbc597561ce1 ("rtc: pcf2127: add watchdog feature support") Signed-off-by: Bruno Thomsen Link: https://lore.kernel.org/r/20190827143656.4734-1-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-pcf2127.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 758f7a417470..da0aceb45095 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -886,6 +886,7 @@ 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 with integrated quartz crystal for industrial applications. diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 3ec87d320766..02b069caffd5 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -475,9 +475,11 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, 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. From 6fd4fe9b496d9ba3382992ff4fde3871d1b6f63d Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 16 Jul 2019 15:18:58 +0800 Subject: [PATCH 37/51] rtc: snvs: fix possible race condition The RTC IRQ is requested before the struct rtc_device is allocated, this may lead to a NULL pointer dereference in IRQ handler. To fix this issue, allocating the rtc_device struct before requesting the RTC IRQ using devm_rtc_allocate_device, and use rtc_register_device to register the RTC device. Signed-off-by: Anson Huang Reviewed-by: Dong Aisheng Link: https://lore.kernel.org/r/20190716071858.36750-1-Anson.Huang@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 7ee673a25fd0..4f9a107a0427 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -279,6 +279,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 +347,9 @@ 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; + ret = rtc_register_device(data->rtc); + if (ret) { dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); goto error_rtc_device_register; } From 79610340cac8840ad67572ca13afae03265edae6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 28 Aug 2019 22:50:55 +0200 Subject: [PATCH 38/51] rtc: snvs: set range The SNVS is a 47-bit counter incremented at 32768Hz, it is then a 32-bit second counter. Link: https://lore.kernel.org/r/20190828205056.31321-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 4f9a107a0427..50dd4b8492eb 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -348,6 +348,7 @@ static int snvs_rtc_probe(struct platform_device *pdev) } 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); From c59a9fc7272e56ba0575b9fcc346c5e4bf16b39d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 28 Aug 2019 22:50:56 +0200 Subject: [PATCH 39/51] rtc: snvs: switch to rtc_time64_to_tm/rtc_tm_to_time64 Call the 64bit versions of rtc_tm time conversion now that the range is enforced by the core. Link: https://lore.kernel.org/r/20190828205056.31321-2-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 50dd4b8492eb..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) From 7ef66122bdb3b839e9f51b76d7e600b6e21ef648 Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Thu, 29 Aug 2019 10:14:18 +0800 Subject: [PATCH 40/51] rtc: pcf85363/pcf85263: fix regmap error in set_time Issue: - # hwclock -w hwclock: RTC_SET_TIME: Invalid argument Why: - Relative commit: 8b9f9d4dc511 ("regmap: verify if register is writeable before writing operations"), this patch will always check for unwritable registers, it will compare reg with max_register in regmap_writeable. - The pcf85363/pcf85263 has the capability of address wrapping which means if you access an address outside the allowed range (0x00-0x2f) hardware actually wraps the access to a lower address. The rtc-pcf85363 driver will use this feature to configure the time and execute 2 actions in the same i2c write operation (stopping the clock and configure the time). However the driver has also configured the `regmap maxregister` protection mechanism that will block accessing addresses outside valid range (0x00-0x2f). How: - Split of writing regs to two parts, first part writes control registers about stop_enable and resets, second part writes RTC time and date registers. Signed-off-by: Biwen Li Link: https://lore.kernel.org/r/20190829021418.4607-1-biwen.li@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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; From 59a7f24fceb3aef6bd16f5aeb852c823dddab04d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 30 Aug 2019 15:31:23 +0200 Subject: [PATCH 41/51] rtc: max77686: convert to devm_i2c_new_dummy_device() I was about to simplify the call to i2c_unregister_device() when I realized that converting to devm_i2c_new_dummy_device() will simplify the driver a lot. So I took this approach. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190830133124.21633-2-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7a98e0744878..d5a0e27dd0a0 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -690,8 +690,8 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) goto add_rtc_irq; } - info->rtc = i2c_new_dummy_device(parent_i2c->adapter, - info->drv_data->rtc_i2c_addr); + 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 PTR_ERR(info->rtc); @@ -702,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: @@ -712,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) @@ -783,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; } @@ -795,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; } From 4053e74996b81902b2dd538717b4fd2fc1426d8b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 30 Aug 2019 15:31:24 +0200 Subject: [PATCH 42/51] rtc: s35390a: convert to devm_i2c_new_dummy_device() I was about to simplify the call to i2c_unregister_device() when I realized that converting to devm_i2c_new_dummy_device() will simplify the driver a lot. So I took this approach. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190830133124.21633-3-wsa+renesas@sang-engineering.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 54 ++++++++++----------------------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index d773fd597bd5..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_device(client->adapter, - client->addr + 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 = PTR_ERR(s35390a->client[i]); - 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, }; From cd646ec003c5a24b1d86d1ba032d2f4eb3aa8e49 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 29 Aug 2019 23:25:43 +0200 Subject: [PATCH 43/51] rtc: pcf8563: add Epson RTC8564 compatible Add a compatible string for the Epson RTC8564. Link: https://lore.kernel.org/r/20190829212547.19185-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/pcf8563.txt | 2 +- drivers/rtc/rtc-pcf8563.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt index 36984acbb383..cef61675312c 100644 --- a/Documentation/devicetree/bindings/rtc/pcf8563.txt +++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt @@ -3,7 +3,7 @@ Philips PCF8563/Epson RTC8564 Real Time Clock Required properties: -- compatible: Should contain "nxp,pcf8563". +- compatible: Should contain "nxp,pcf8563" or "epson,rtc8564". - reg: I2C address for chip. Optional property: diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index ac159d24286d..f72ec94acaf5 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -632,6 +632,7 @@ MODULE_DEVICE_TABLE(i2c, pcf8563_id); #ifdef CONFIG_OF static const struct of_device_id pcf8563_of_match[] = { { .compatible = "nxp,pcf8563" }, + { .compatible = "epson,rtc8564" }, {} }; MODULE_DEVICE_TABLE(of, pcf8563_of_match); From deaa3ff4984f85fd8957841c314b94bbf81c9cd7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 29 Aug 2019 23:25:44 +0200 Subject: [PATCH 44/51] rtc: pcf8563: add Microcrystal RV8564 compatible Add a compatible string for the Microcrystal RV8564. Link: https://lore.kernel.org/r/20190829212547.19185-2-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/pcf8563.txt | 4 +++- drivers/rtc/rtc-pcf8563.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt index cef61675312c..6076fe76dbfa 100644 --- a/Documentation/devicetree/bindings/rtc/pcf8563.txt +++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt @@ -3,7 +3,9 @@ Philips PCF8563/Epson RTC8564 Real Time Clock Required properties: -- compatible: Should contain "nxp,pcf8563" or "epson,rtc8564". +- compatible: Should contain "nxp,pcf8563", + "epson,rtc8564" or + "microcrystal,rv8564" - reg: I2C address for chip. Optional property: diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index f72ec94acaf5..1b452da75eb8 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -633,6 +633,7 @@ MODULE_DEVICE_TABLE(i2c, pcf8563_id); 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); From 8d3f805e6896798a1a40173d3734463363431b8e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 29 Aug 2019 23:25:45 +0200 Subject: [PATCH 45/51] rtc: pcf8563: convert to devm_rtc_allocate_device This allows further improvement of the driver. Link: https://lore.kernel.org/r/20190829212547.19185-3-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8563.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 1b452da75eb8..0e375e19c149 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -591,13 +591,14 @@ 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; + if (client->irq > 0) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8563_irq, @@ -608,17 +609,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; } From c7d5f6dbd9f9a68374f3d24c63a99691d792fd29 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 29 Aug 2019 23:25:46 +0200 Subject: [PATCH 46/51] rtc: pcf8563: remove useless indirection pcf8563_rtc_read_time and pcf8563_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Link: https://lore.kernel.org/r/20190829212547.19185-4-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8563.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 0e375e19c149..45462ec460a3 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; @@ -244,8 +245,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]; @@ -299,8 +301,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 +316,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); From f648d40b99ba7363bf4a1bbca5cc93904725dceb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 29 Aug 2019 23:25:47 +0200 Subject: [PATCH 47/51] rtc: pcf8563: let the core handle range offsetting Set the RTC range properly and use the core windowing and offsetting to (unfortunately) map back to a 1970-2069 range. Link: https://lore.kernel.org/r/20190829212547.19185-5-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8563.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 45462ec460a3..24baa4767b11 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -229,9 +229,7 @@ static int pcf8563_rtc_read_time(struct device *dev, 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); @@ -268,7 +266,7 @@ static int pcf8563_rtc_set_time(struct device *dev, 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; @@ -590,6 +588,9 @@ static int pcf8563_probe(struct i2c_client *client, 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, From d76a81d0c262154ed5ec0307bdd195f2758ccc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= Date: Wed, 21 Aug 2019 23:00:56 +0200 Subject: [PATCH 48/51] rtc: sun6i: Allow using as wakeup source from suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch allows userspace to set up wakeup alarms on any RTC handled by the sun6i driver, and adds the necessary PM operations to allow resuming from suspend when the configured wakeup alarm fires a IRQ. Of course, that the device actually resumes depends on the suspend state and how a particular hardware reacts to it, but that is out of scope for this patch. I've tested these changes on a Pine H64 model B, which contains a Allwinner H6 SoC, with the help of CONFIG_PM_TEST_SUSPEND kernel option. These are the interesting outputs from the kernel and commands which show that it works. As every RTC handled by this driver is largely the same, I think that it shouldn't introduce any regression on other SoCs, but I may be wrong. [ 1.092705] PM: test RTC wakeup from 'freeze' suspend [ 1.098230] PM: suspend entry (s2idle) [ 1.212907] PM: suspend devices took 0.080 seconds (The SoC freezes for some seconds) [ 3.197604] PM: resume devices took 0.104 seconds [ 3.215937] PM: suspend exit [ 1.092812] PM: test RTC wakeup from 'mem' suspend [ 1.098089] PM: suspend entry (deep) [ 1.102033] PM: suspend exit [ 1.105205] PM: suspend test failed, error -22 In any case, the RTC alarm interrupt gets fired as exptected: $ echo +5 > /sys/class/rtc/rtc0/wakealarm && sleep 5 && grep rtc /proc/interrupts 29: 1 0 0 0 GICv2 133 Level 7000000.rtc Signed-off-by: Alejandro González Acked-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20190821210056.11995-1-alejandro.gonzalez.correo@gmail.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sun6i.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 956c0846201f..04d74e59f3d5 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -633,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; @@ -683,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)) { @@ -718,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); From 4a9eb8154ffd26a56121a4a531b04cf32942a49b Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Fri, 30 Aug 2019 15:47:55 +0200 Subject: [PATCH 49/51] dt-bindings: rtc: ds1307: add rx8130 compatible The required OF entries were added with commit 47dd47292828 ("rtc: ds1307: add OF and ACPI entries for Epson RX8130"). Cc: devicetree@vger.kernel.org Signed-off-by: Bastian Krause Link: https://lore.kernel.org/r/20190830134755.1121-1-bst@pengutronix.de Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/rtc-ds1307.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt index eaee19b60960..66f0a31ae9ce 100644 --- a/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt +++ b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt @@ -19,6 +19,7 @@ Required properties: "pericom,pt7c4338", "epson,rx8025", "isil,isl12057" + "epson,rx8130" - reg: I2C bus address of the device Optional properties: From e02e3ddac7722b879b6f3c781b45beea2173f562 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 5 Sep 2019 15:03:30 +0800 Subject: [PATCH 50/51] rtc: sc27xx: Remove clearing SPRD_RTC_POWEROFF_ALM_FLAG flag The SPRD_RTC_POWEROFF_ALM_FLAG flag is used to indicate if a poweroff alarm is set, which can power on the system when system in power-off status. And the bootloader will validate this flag to check if the booting mode is alarm booting mode, thus we should not clear this flag in kernel, instead bootloader will clear this flag after checking the booting mode. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/1f75310242de75b14d8973538bf96efffb395daf.1567666894.git.baolin.wang@linaro.org Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 3474f7a20493..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 From b99a3120f9a30e1429d8d634e18da8dff93340c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 6 Sep 2019 17:24:29 +0200 Subject: [PATCH 51/51] rtc: meson: mark PM functions as __maybe_unused The meson_vrtc_set_wakeup_time() function is only used by the PM functions and causes a warning when they are disabled: drivers/rtc/rtc-meson-vrtc.c:32:13: error: unused function 'meson_vrtc_set_wakeup_time' [-Werror,-Wunused-function] Remove the #ifdef around the callers and add a __maybe_unused annotation as a more reliable way to avoid these warnings. Signed-off-by: Arnd Bergmann Reviewed-by: Kevin Hilman Link: https://lore.kernel.org/r/20190906152438.1533833-1-arnd@arndb.de Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-meson-vrtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c index 4621a4715179..89e5ba0dae69 100644 --- a/drivers/rtc/rtc-meson-vrtc.c +++ b/drivers/rtc/rtc-meson-vrtc.c @@ -91,8 +91,7 @@ static int meson_vrtc_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int meson_vrtc_suspend(struct device *dev) +static int __maybe_unused meson_vrtc_suspend(struct device *dev) { struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); @@ -121,7 +120,7 @@ static int meson_vrtc_suspend(struct device *dev) return 0; } -static int meson_vrtc_resume(struct device *dev) +static int __maybe_unused meson_vrtc_resume(struct device *dev) { struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); @@ -131,7 +130,7 @@ static int meson_vrtc_resume(struct device *dev) meson_vrtc_set_wakeup_time(vrtc, 0); return 0; } -#endif + static SIMPLE_DEV_PM_OPS(meson_vrtc_pm_ops, meson_vrtc_suspend, meson_vrtc_resume);