From c6b5eb8dd33480104683d838da10c7ec77d32e8a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 30 Jul 2018 21:59:03 +0800 Subject: [PATCH 01/54] rtc: rtc-mrst: Replace mdelay() with msleep() in mrst_read_time() mrst_read_time() is never called in atomic context. It calls mdelay() to busily wait, which is not necessary. mdelay() can be replaced with msleep(). This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mrst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 1925aaf090937..bf2d7af03d075 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -90,7 +90,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time) unsigned long flags; if (vrtc_is_updating()) - mdelay(20); + msleep(20); spin_lock_irqsave(&rtc_lock, flags); time->tm_sec = vrtc_cmos_read(RTC_SECONDS); From 0438002ac52637cef5f5734bab56d8d8750e1f37 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 16 Aug 2018 10:38:59 +0530 Subject: [PATCH 02/54] rtc: omap: use of_device_is_system_power_controller function Use of_device_is_system_power_controller instead of manually reading the system-power-controller property from the device tree node. Reviewed-by: Johan Hovold Signed-off-by: Keerthy Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 323ff55cc1656..44ff4cc62a617 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -721,8 +721,7 @@ static int omap_rtc_probe(struct platform_device *pdev) if (of_id) { rtc->type = of_id->data; rtc->is_pmic_controller = rtc->type->has_pmic_mode && - of_property_read_bool(pdev->dev.of_node, - "system-power-controller"); + of_device_is_system_power_controller(pdev->dev.of_node); } else { id_entry = platform_get_device_id(pdev); rtc->type = (void *)id_entry->driver_data; From 09058eab4b4f77b721572da5291532e751b63931 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 16 Aug 2018 10:39:00 +0530 Subject: [PATCH 03/54] rtc: omap: Cut down the shutdown time from 2 seconds to 1 sec Cut down the shutdown time from 2 seconds to 1 sec. In case of roll over try again. Signed-off-by: Keerthy Reviewed-by: Johan Hovold Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 44ff4cc62a617..320b4a520eb34 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -421,12 +421,6 @@ static struct omap_rtc *omap_rtc_power_off_rtc; * The RTC can be used to control an external PMIC via the pmic_power_en pin, * which can be configured to transition to OFF on ALARM2 events. * - * Notes: - * The two-second alarm offset is the shortest offset possible as the alarm - * registers must be set before the next timer update and the offset - * calculation is too heavy for everything to be done within a single access - * period (~15 us). - * * Called with local interrupts disabled. */ static void omap_rtc_power_off(void) @@ -434,6 +428,7 @@ static void omap_rtc_power_off(void) struct omap_rtc *rtc = omap_rtc_power_off_rtc; struct rtc_time tm; unsigned long now; + int seconds; u32 val; rtc->type->unlock(rtc); @@ -441,11 +436,13 @@ static void omap_rtc_power_off(void) val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); - /* set alarm two seconds from now */ +again: + /* set alarm one second from now */ omap_rtc_read_time_raw(rtc, &tm); + seconds = tm.tm_sec; bcd2tm(&tm); rtc_tm_to_time(&tm, &now); - rtc_time_to_tm(now + 2, &tm); + rtc_time_to_tm(now + 1, &tm); if (tm2bcd(&tm) < 0) { dev_err(&rtc->rtc->dev, "power off failed\n"); @@ -470,14 +467,22 @@ static void omap_rtc_power_off(void) val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, val | OMAP_RTC_INTERRUPTS_IT_ALARM2); + + /* Retry in case roll over happened before alarm was armed. */ + if (rtc_read(rtc, OMAP_RTC_SECONDS_REG) != seconds) { + val = rtc_read(rtc, OMAP_RTC_STATUS_REG); + if (!(val & OMAP_RTC_STATUS_ALARM2)) + goto again; + } + rtc->type->lock(rtc); /* - * Wait for alarm to trigger (within two seconds) and external PMIC to + * Wait for alarm to trigger (within one second) and external PMIC to * power off the system. Add a 500 ms margin for external latencies * (e.g. debounce circuits). */ - mdelay(2500); + mdelay(1500); } static const struct rtc_class_ops omap_rtc_ops = { From 1e6e4e169a8aef8127ff9ffece6290fafe0d92bf Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 20 Aug 2018 20:07:16 +0200 Subject: [PATCH 04/54] rtc: jz4740: Drop dependency on MACH_INGENIC Depending on MACH_INGENIC prevent us from creating a generic kernel that works on more than one MIPS board. Instead, we just depend on MIPS being set. Signed-off-by: Paul Cercueil Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 7d7be60a2413f..a0f291c052bca 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1587,7 +1587,7 @@ config RTC_DRV_MPC5121 config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" - depends on MACH_INGENIC || COMPILE_TEST + depends on MIPS || COMPILE_TEST help If you say yes here you get support for the Ingenic JZ47xx SoCs RTC controllers. From 725e0e15f84bb30e83fad8fa4b4dd1f335506172 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Aug 2018 13:51:40 -0500 Subject: [PATCH 05/54] rtc: sun6i: Use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sun6i.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 2cd5a7b1a2e30..fe07310952dfa 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -199,8 +199,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) if (!rtc) return; - clk_data = kzalloc(sizeof(*clk_data) + (sizeof(*clk_data->hws) * 2), - GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL); if (!clk_data) { kfree(rtc); return; From 777d8ae56da18fb6440acd941edb3597c1b02bf0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Aug 2018 12:22:34 +0300 Subject: [PATCH 06/54] rtc: sysfs: fix NULL check in rtc_add_groups() devm_kcalloc() returns NULL, it never returns error pointers. In the current code we would return PTR_ERR(NULL) which is success, instead of returning the -ENOMEM error code. Fixes: a0a1a1ba3032 ("rtc: sysfs: facilitate attribute add to rtc device") Signed-off-by: Dan Carpenter Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index f1ff30ade5343..9746c32eee2eb 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -338,8 +338,8 @@ int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) new_cnt = old_cnt + add_cnt + 1; groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL); - if (IS_ERR_OR_NULL(groups)) - return PTR_ERR(groups); + if (!groups) + return -ENOMEM; memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups)); memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups)); groups[old_cnt + add_cnt] = NULL; From c856618d20662695fcdb47bf4d560dc457662aec Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 27 Aug 2018 23:23:43 +0200 Subject: [PATCH 07/54] rtc: rv8803: fix the rv8803 id in the OF table The ID for RV8803 must be rv_8803 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 29fc3d2103923..17ccef5d5db1a 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(i2c, rv8803_id); static const struct of_device_id rv8803_of_match[] = { { .compatible = "microcrystal,rv8803", - .data = (void *)rx_8900 + .data = (void *)rv_8803 }, { .compatible = "epson,rx8900", From ac771ed746c800749ec5adbb4b7c22ce1d89943e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 27 Aug 2018 23:23:44 +0200 Subject: [PATCH 08/54] rtc: rv8803: add Epson RX8803 support The Epson rx8803 is mostly similar to the Microcrystal RV8803 but the size of the offset register is 4 bits vs 6 bits but it has a configurable temperature compensation. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 17ccef5d5db1a..450a0b831a2da 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -615,6 +615,7 @@ static int rv8803_probe(struct i2c_client *client, static const struct i2c_device_id rv8803_id[] = { { "rv8803", rv_8803 }, + { "rx8803", rv_8803 }, { "rx8900", rx_8900 }, { } }; @@ -625,6 +626,10 @@ static const struct of_device_id rv8803_of_match[] = { .compatible = "microcrystal,rv8803", .data = (void *)rv_8803 }, + { + .compatible = "epson,rx8803", + .data = (void *)rv_8803 + }, { .compatible = "epson,rx8900", .data = (void *)rx_8900 From de96bc39951f106a074d5ee1db927ad8abbfe7fe Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 31 Aug 2018 02:15:39 +0000 Subject: [PATCH 09/54] rtc: mrst: remove set but not used variable 'valid' Fixes gcc '-Wunused-but-set-variable' warning: drivers/rtc/rtc-mrst.c: In function 'mrst_procfs': drivers/rtc/rtc-mrst.c:264:29: warning: variable 'valid' set but not used [-Wunused-but-set-variable] unsigned char rtc_control, valid; Signed-off-by: YueHaibing Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mrst.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index bf2d7af03d075..daf354a6a853f 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -261,11 +261,10 @@ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int mrst_procfs(struct device *dev, struct seq_file *seq) { - unsigned char rtc_control, valid; + unsigned char rtc_control; spin_lock_irq(&rtc_lock); rtc_control = vrtc_cmos_read(RTC_CONTROL); - valid = vrtc_cmos_read(RTC_VALID); spin_unlock_irq(&rtc_lock); seq_printf(seq, From 05a0a34418699ea2ced1fe6e081b91c0e1065690 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Aug 2018 16:26:30 +0200 Subject: [PATCH 10/54] rtc: mips: default to rtc-cmos on mips The old rtc driver is getting in the way of some compat_ioctl simplification. Looking up the loongson64 git history, it seems that everyone uses the more modern but compatible RTC_CMOS driver anyway, so let's remove the special case for loongson64. Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- arch/mips/Kconfig | 2 +- drivers/char/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 35511999156af..c695825d93771 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -75,7 +75,7 @@ config MIPS select MODULES_USE_ELF_RELA if MODULES && 64BIT select MODULES_USE_ELF_REL if MODULES select PERF_USE_VMALLOC - select RTC_LIB if !MACH_LOONGSON64 + select RTC_LIB select SYSCTL_EXCEPTION_TRACE select VIRT_TO_BUS diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index ce277ee0a28a2..131b4c3000501 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -268,7 +268,7 @@ if RTC_LIB=n config RTC tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" - depends on ALPHA || (MIPS && MACH_LOONGSON64) + depends on ALPHA ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you From babab2f86440352d24e76118fdd7d40cab5fd7bf Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 9 Sep 2018 22:38:46 +0200 Subject: [PATCH 11/54] rtc: mt6397: fix possible race condition The IRQ is requested before the struct rtc is allocated and registered, but this struct is used in the IRQ handler. This may lead to a NULL pointer dereference. Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before requesting the IRQ. Acked-by: Eddie Huang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mt6397.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 385f8303bb412..e9a25ec4d434f 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -332,6 +332,10 @@ static int mtk_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); + rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + ret = request_threaded_irq(rtc->irq, NULL, mtk_rtc_irq_handler_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH, @@ -344,11 +348,11 @@ static int mtk_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, - &mtk_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc_dev)) { + 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"); - ret = PTR_ERR(rtc->rtc_dev); goto out_free_irq; } @@ -365,7 +369,6 @@ static int mtk_rtc_remove(struct platform_device *pdev) { struct mt6397_rtc *rtc = platform_get_drvdata(pdev); - rtc_device_unregister(rtc->rtc_dev); free_irq(rtc->irq, rtc->rtc_dev); irq_dispose_mapping(rtc->irq); From c778ec85825dc895936940072aea9fe9037db684 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 9 Sep 2018 22:38:47 +0200 Subject: [PATCH 12/54] rtc: pl030: fix possible race condition The IRQ is requested before the struct rtc is allocated and registered, but this struct is used in the IRQ handler. This may lead to a NULL pointer dereference. Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before requesting the IRQ. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl030.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index f85a1a93e669f..343bb6ed17839 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -112,6 +112,13 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) goto err_rtc; } + rtc->rtc = devm_rtc_allocate_device(&dev->dev); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + goto err_rtc; + } + + rtc->rtc->ops = &pl030_ops; rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!rtc->base) { ret = -ENOMEM; @@ -128,12 +135,9 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) if (ret) goto err_irq; - rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, - THIS_MODULE); - if (IS_ERR(rtc->rtc)) { - ret = PTR_ERR(rtc->rtc); + ret = rtc_register_device(rtc->rtc); + if (ret) goto err_reg; - } return 0; @@ -154,7 +158,6 @@ static int pl030_remove(struct amba_device *dev) writel(0, rtc->base + RTC_CR); free_irq(dev->irq[0], rtc); - rtc_device_unregister(rtc->rtc); iounmap(rtc->base); amba_release_regions(dev); From b7aff107f34f007f32f45136c9a935912a481d32 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 9 Sep 2018 22:38:48 +0200 Subject: [PATCH 13/54] rtc: pl031: switch to devm_rtc_allocate_device/rtc_register_device Switch to devm_rtc_allocate_device to simplify the erro and driver removal paths. Acked-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl031.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 82eb7da2c4783..30943d200c5e1 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -310,7 +310,6 @@ static int pl031_remove(struct amba_device *adev) device_init_wakeup(&adev->dev, false); if (adev->irq[0]) free_irq(adev->irq[0], ldata); - rtc_device_unregister(ldata->rtc); amba_release_regions(adev); return 0; @@ -383,24 +382,25 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } device_init_wakeup(&adev->dev, true); - ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, - THIS_MODULE); - if (IS_ERR(ldata->rtc)) { - ret = PTR_ERR(ldata->rtc); + ldata->rtc = devm_rtc_allocate_device(&adev->dev); + if (IS_ERR(ldata->rtc)) + return PTR_ERR(ldata->rtc); + + ldata->rtc->ops = ops; + + ret = rtc_register_device(ldata->rtc); + if (ret) goto out; - } if (adev->irq[0]) { ret = request_irq(adev->irq[0], pl031_interrupt, vendor->irqflags, "rtc-pl031", ldata); if (ret) - goto out_no_irq; + goto out; dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); } return 0; -out_no_irq: - rtc_device_unregister(ldata->rtc); out: amba_release_regions(adev); err_req: From af69f9a7878413ccdb47a28b024748fd0381a035 Mon Sep 17 00:00:00 2001 From: Jeremy Gebben Date: Tue, 11 Sep 2018 11:28:25 -0600 Subject: [PATCH 14/54] rtc: abx80x: use a 'priv' struct for client data This will allow additional data to be tracked, for future improvements. Signed-off-by: Jeremy Gebben Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 2cefa67a1132d..9d49054a0a4a0 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -94,6 +94,11 @@ static struct abx80x_cap abx80x_caps[] = { [ABX80X] = {.pn = 0} }; +struct abx80x_priv { + struct rtc_device *rtc; + struct i2c_client *client; +}; + static int abx80x_is_rc_mode(struct i2c_client *client) { int flags = 0; @@ -218,7 +223,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) { struct i2c_client *client = dev_id; - struct rtc_device *rtc = i2c_get_clientdata(client); + struct abx80x_priv *priv = i2c_get_clientdata(client); + struct rtc_device *rtc = priv->rtc; int status; status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); @@ -533,7 +539,7 @@ static int abx80x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *np = client->dev.of_node; - struct rtc_device *rtc; + struct abx80x_priv *priv; int i, data, err, trickle_cfg = -EINVAL; char buf[7]; unsigned int part = id->driver_data; @@ -610,13 +616,18 @@ static int abx80x_probe(struct i2c_client *client, if (err) return err; - rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(priv->rtc)) + return PTR_ERR(priv->rtc); - rtc->ops = &abx80x_rtc_ops; + priv->rtc->ops = &abx80x_rtc_ops; + priv->client = client; - i2c_set_clientdata(client, rtc); + i2c_set_clientdata(client, priv); if (client->irq > 0) { dev_info(&client->dev, "IRQ %d supplied\n", client->irq); @@ -649,7 +660,7 @@ static int abx80x_probe(struct i2c_client *client, return err; } - err = rtc_register_device(rtc); + err = rtc_register_device(priv->rtc); return err; } From 749e36d0a0d725a3fc2dc8d6261557b9e06d210d Mon Sep 17 00:00:00 2001 From: Jeremy Gebben Date: Tue, 11 Sep 2018 11:28:26 -0600 Subject: [PATCH 15/54] rtc: abx80x: add basic watchdog support The abx804 and abx805 chips have support for a simple watchdog function that can trigger an external reset. Signed-off-by: Jeremy Gebben Reviewed-by: Guenter Roeck Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-abx80x.c | 116 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a0f291c052bca..4df9a3ec064bd 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -187,6 +187,7 @@ config RTC_DRV_ABB5ZES3 config RTC_DRV_ABX80X tristate "Abracon ABx80x" + select WATCHDOG_CORE if WATCHDOG help If you say yes here you get support for Abracon AB080X and AB180X families of ultra-low-power battery- and capacitor-backed real-time diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 9d49054a0a4a0..d8e94edcb0ba9 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -17,6 +17,7 @@ #include #include #include +#include #define ABX8XX_REG_HTH 0x00 #define ABX8XX_REG_SC 0x01 @@ -37,6 +38,7 @@ #define ABX8XX_REG_STATUS 0x0f #define ABX8XX_STATUS_AF BIT(2) +#define ABX8XX_STATUS_WDT BIT(6) #define ABX8XX_REG_CTRL1 0x10 #define ABX8XX_CTRL_WRITE BIT(0) @@ -61,6 +63,14 @@ #define ABX8XX_OSS_OF BIT(1) #define ABX8XX_OSS_OMODE BIT(4) +#define ABX8XX_REG_WDT 0x1b +#define ABX8XX_WDT_WDS BIT(7) +#define ABX8XX_WDT_BMB_MASK 0x7c +#define ABX8XX_WDT_BMB_SHIFT 2 +#define ABX8XX_WDT_MAX_TIME (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT) +#define ABX8XX_WDT_WRB_MASK 0x03 +#define ABX8XX_WDT_WRB_1HZ 0x02 + #define ABX8XX_REG_CFG_KEY 0x1f #define ABX8XX_CFG_KEY_OSC 0xa1 #define ABX8XX_CFG_KEY_MISC 0x9d @@ -80,23 +90,25 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, struct abx80x_cap { u16 pn; bool has_tc; + bool has_wdog; }; static struct abx80x_cap abx80x_caps[] = { [AB0801] = {.pn = 0x0801}, [AB0803] = {.pn = 0x0803}, - [AB0804] = {.pn = 0x0804, .has_tc = true}, - [AB0805] = {.pn = 0x0805, .has_tc = true}, + [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true}, + [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true}, [AB1801] = {.pn = 0x1801}, [AB1803] = {.pn = 0x1803}, - [AB1804] = {.pn = 0x1804, .has_tc = true}, - [AB1805] = {.pn = 0x1805, .has_tc = true}, + [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true}, + [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, [ABX80X] = {.pn = 0} }; struct abx80x_priv { struct rtc_device *rtc; struct i2c_client *client; + struct watchdog_device wdog; }; static int abx80x_is_rc_mode(struct i2c_client *client) @@ -234,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) if (status & ABX8XX_STATUS_AF) rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); + /* + * It is unclear if we'll get an interrupt before the external + * reset kicks in. + */ + if (status & ABX8XX_STATUS_WDT) + dev_alert(&client->dev, "watchdog timeout interrupt.\n"); + i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0); return IRQ_HANDLED; @@ -535,6 +554,89 @@ static void rtc_calib_remove_sysfs_group(void *_dev) sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group); } +#ifdef CONFIG_WATCHDOG + +static inline u8 timeout_bits(unsigned int timeout) +{ + return ((timeout << ABX8XX_WDT_BMB_SHIFT) & ABX8XX_WDT_BMB_MASK) | + ABX8XX_WDT_WRB_1HZ; +} + +static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog, + unsigned int timeout) +{ + struct abx80x_priv *priv = watchdog_get_drvdata(wdog); + u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout); + + /* + * Writing any timeout to the WDT register resets the watchdog timer. + * Writing 0 disables it. + */ + return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val); +} + +static int abx80x_wdog_set_timeout(struct watchdog_device *wdog, + unsigned int new_timeout) +{ + int err = 0; + + if (watchdog_hw_running(wdog)) + err = __abx80x_wdog_set_timeout(wdog, new_timeout); + + if (err == 0) + wdog->timeout = new_timeout; + + return err; +} + +static int abx80x_wdog_ping(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, wdog->timeout); +} + +static int abx80x_wdog_start(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, wdog->timeout); +} + +static int abx80x_wdog_stop(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, 0); +} + +static const struct watchdog_info abx80x_wdog_info = { + .identity = "abx80x watchdog", + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, +}; + +static const struct watchdog_ops abx80x_wdog_ops = { + .owner = THIS_MODULE, + .start = abx80x_wdog_start, + .stop = abx80x_wdog_stop, + .ping = abx80x_wdog_ping, + .set_timeout = abx80x_wdog_set_timeout, +}; + +static int abx80x_setup_watchdog(struct abx80x_priv *priv) +{ + priv->wdog.parent = &priv->client->dev; + priv->wdog.ops = &abx80x_wdog_ops; + priv->wdog.info = &abx80x_wdog_info; + priv->wdog.min_timeout = 1; + priv->wdog.max_timeout = ABX8XX_WDT_MAX_TIME; + priv->wdog.timeout = ABX8XX_WDT_MAX_TIME; + + watchdog_set_drvdata(&priv->wdog, priv); + + return devm_watchdog_register_device(&priv->client->dev, &priv->wdog); +} +#else +static int abx80x_setup_watchdog(struct abx80x_priv *priv) +{ + return 0; +} +#endif + static int abx80x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -629,6 +731,12 @@ static int abx80x_probe(struct i2c_client *client, i2c_set_clientdata(client, priv); + if (abx80x_caps[part].has_wdog) { + err = abx80x_setup_watchdog(priv); + if (err) + return err; + } + if (client->irq > 0) { dev_info(&client->dev, "IRQ %d supplied\n", client->irq); err = devm_request_threaded_irq(&client->dev, client->irq, NULL, From 1e479c619b2ac983fdea1a8212c7b822b5098da0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 12 Sep 2018 22:22:45 +0200 Subject: [PATCH 16/54] rtc: unexport non devm managed registration Ensure the non managed version of the un/registration functions is not used anymore. No driver is using it anymore and they should not be necessary. Signed-off-by: Alexandre Belloni --- drivers/rtc/class.c | 12 +++++------- include/linux/rtc.h | 5 ----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 0fca4d74c76b3..3b43787f154b1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -286,9 +286,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc) * * Returns the pointer to the new struct class device. */ -struct rtc_device *rtc_device_register(const char *name, struct device *dev, - const struct rtc_class_ops *ops, - struct module *owner) +static struct rtc_device *rtc_device_register(const char *name, + struct device *dev, + const struct rtc_class_ops *ops, + struct module *owner) { struct rtc_device *rtc; struct rtc_wkalrm alrm; @@ -351,15 +352,13 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, name, err); return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(rtc_device_register); - /** * rtc_device_unregister - removes the previously registered RTC class device * * @rtc: the RTC class device to destroy */ -void rtc_device_unregister(struct rtc_device *rtc) +static void rtc_device_unregister(struct rtc_device *rtc) { mutex_lock(&rtc->ops_lock); /* @@ -372,7 +371,6 @@ void rtc_device_unregister(struct rtc_device *rtc) mutex_unlock(&rtc->ops_lock); put_device(&rtc->dev); } -EXPORT_SYMBOL_GPL(rtc_device_unregister); static void devm_rtc_device_release(struct device *dev, void *res) { diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 6aedc30003e73..faf00a1472d45 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -167,17 +167,12 @@ struct rtc_device { #define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */ #define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */ -extern struct rtc_device *rtc_device_register(const char *name, - struct device *dev, - const struct rtc_class_ops *ops, - struct module *owner); extern struct rtc_device *devm_rtc_device_register(struct device *dev, const char *name, const struct rtc_class_ops *ops, struct module *owner); struct rtc_device *devm_rtc_allocate_device(struct device *dev); int __rtc_register_device(struct module *owner, struct rtc_device *rtc); -extern void rtc_device_unregister(struct rtc_device *rtc); extern void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc); From f1c8bc332e6dacac221d0d6304f4a3e99b756e2f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 12 Sep 2018 22:43:07 +0200 Subject: [PATCH 17/54] rtc: remove irq_task from kerneldoc Stale mentions of irq_task are left in the kerneldoc after its removal. Remove them. There is still one indirect mention left but commit 3c8bb90efb6e ("rtc: Fix hrtimer deadlock") can probably be reverted now. Reported-by: Linus Torvalds Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3d577e259e91b..612a83d3ddcc0 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -596,7 +596,6 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); * This function is called when an AIE, UIE or PIE mode interrupt * has occurred (or been emulated). * - * Triggers the registered irq_task function callback. */ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) { @@ -741,7 +740,6 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) /** * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() * @enabled: true to enable periodic IRQs * Context: any * @@ -764,7 +762,6 @@ int rtc_irq_set_state(struct rtc_device *rtc, int enabled) /** * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() * @freq: positive frequency * Context: any * From 1b4c794fda583edabe864ac466e9cd43c707be80 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 15 Sep 2018 13:29:56 +0200 Subject: [PATCH 18/54] rtc: isl1208: avoid possible sysfs race Use rtc_add_group to add the common sysfs group to avoid a possible race condition. [Denis.Osterland@diehl.com: use to_i2c_client(dev->parent)] Signed-off-by: Denis Osterland Signed-off-by: Alexandre Belloni The move of atrim, dtrim usr sysfs properties from i2c device to rtc device require to access them via dev->parent. This patch also aligns timestamp0. --- drivers/rtc/rtc-isl1208.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index ea18a8f4bce06..033f65aef5788 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -518,7 +518,7 @@ static ssize_t timestamp0_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev->parent); int sr; sr = isl1208_i2c_get_sr(client); @@ -540,7 +540,7 @@ static ssize_t timestamp0_store(struct device *dev, static ssize_t timestamp0_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev->parent); u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, }; struct rtc_time tm; int sr; @@ -650,7 +650,7 @@ static ssize_t isl1208_sysfs_show_atrim(struct device *dev, struct device_attribute *attr, char *buf) { - int atr = isl1208_i2c_get_atr(to_i2c_client(dev)); + int atr = isl1208_i2c_get_atr(to_i2c_client(dev->parent)); if (atr < 0) return atr; @@ -663,7 +663,7 @@ static ssize_t isl1208_sysfs_show_dtrim(struct device *dev, struct device_attribute *attr, char *buf) { - int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev)); + int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev->parent)); if (dtr < 0) return dtr; @@ -676,7 +676,7 @@ static ssize_t isl1208_sysfs_show_usr(struct device *dev, struct device_attribute *attr, char *buf) { - int usr = isl1208_i2c_get_usr(to_i2c_client(dev)); + int usr = isl1208_i2c_get_usr(to_i2c_client(dev->parent)); if (usr < 0) return usr; @@ -701,7 +701,10 @@ isl1208_sysfs_store_usr(struct device *dev, if (usr < 0 || usr > 0xffff) return -EINVAL; - return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count; + if (isl1208_i2c_set_usr(to_i2c_client(dev->parent), usr)) + return -EIO; + + return count; } static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, @@ -765,7 +768,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) rtc->ops = &isl1208_rtc_ops; i2c_set_clientdata(client, rtc); - dev_set_drvdata(&rtc->dev, client); rc = isl1208_i2c_get_sr(client); if (rc < 0) { @@ -804,7 +806,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) evdet_irq = of_irq_get_byname(np, "evdet"); } - rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); + rc = rtc_add_group(rtc, &isl1208_rtc_sysfs_files); if (rc) return rc; @@ -821,14 +823,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) return rtc_register_device(rtc); } -static int -isl1208_remove(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); - - return 0; -} - static const struct i2c_device_id isl1208_id[] = { { "isl1208", TYPE_ISL1208 }, { "isl1218", TYPE_ISL1218 }, @@ -851,7 +845,6 @@ static struct i2c_driver isl1208_driver = { .of_match_table = of_match_ptr(isl1208_of_match), }, .probe = isl1208_probe, - .remove = isl1208_remove, .id_table = isl1208_id, }; From 79230ff64167586b2a556470c7934083afea930e Mon Sep 17 00:00:00 2001 From: Giulio Benetti Date: Wed, 25 Jul 2018 19:26:04 +0200 Subject: [PATCH 19/54] rtc: ds1307: add offset sysfs for mt41txx chips. m41txx chips can hold a calibration value to get correct clock bias. Add offset handling (ranging between -63ppm and 126ppm) via sysfs. Signed-off-by: Giulio Benetti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4b2b4627daebf..8268813f15c30 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -114,6 +114,20 @@ enum ds_type { # define RX8025_BIT_VDET 0x40 # define RX8025_BIT_XST 0x20 +#define M41TXX_REG_CONTROL 0x07 +# define M41TXX_BIT_OUT BIT(7) +# define M41TXX_BIT_FT BIT(6) +# define M41TXX_BIT_CALIB_SIGN BIT(5) +# define M41TXX_M_CALIBRATION GENMASK(4, 0) + +/* negative offset step is -2.034ppm */ +#define M41TXX_NEG_OFFSET_STEP_PPB 2034 +/* positive offset step is +4.068ppm */ +#define M41TXX_POS_OFFSET_STEP_PPB 4068 +/* Min and max values supported with 'offset' interface by M41TXX */ +#define M41TXX_MIN_OFFSET ((-31) * M41TXX_NEG_OFFSET_STEP_PPB) +#define M41TXX_MAX_OFFSET ((31) * M41TXX_POS_OFFSET_STEP_PPB) + struct ds1307 { enum ds_type type; unsigned long flags; @@ -146,6 +160,9 @@ struct chip_desc { static int ds1307_get_time(struct device *dev, struct rtc_time *t); static int ds1307_set_time(struct device *dev, struct rtc_time *t); +static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t); +static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t); +static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled); static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode); static irqreturn_t rx8130_irq(int irq, void *dev_id); static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t); @@ -155,6 +172,8 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id); static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled); +static int m41txx_rtc_read_offset(struct device *dev, long *offset); +static int m41txx_rtc_set_offset(struct device *dev, long offset); static const struct rtc_class_ops rx8130_rtc_ops = { .read_time = ds1307_get_time, @@ -172,6 +191,16 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = { .alarm_irq_enable = mcp794xx_alarm_irq_enable, }; +static const struct rtc_class_ops m41txx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = ds1337_read_alarm, + .set_alarm = ds1337_set_alarm, + .alarm_irq_enable = ds1307_alarm_irq_enable, + .read_offset = m41txx_rtc_read_offset, + .set_offset = m41txx_rtc_set_offset, +}; + static const struct chip_desc chips[last_ds_type] = { [ds_1307] = { .nvram_offset = 8, @@ -228,10 +257,17 @@ static const struct chip_desc chips[last_ds_type] = { .irq_handler = rx8130_irq, .rtc_ops = &rx8130_rtc_ops, }, + [m41t0] = { + .rtc_ops = &m41txx_rtc_ops, + }, + [m41t00] = { + .rtc_ops = &m41txx_rtc_ops, + }, [m41t11] = { /* this is battery backed SRAM */ .nvram_offset = 8, .nvram_size = 56, + .rtc_ops = &m41txx_rtc_ops, }, [mcp794xx] = { .alarm = 1, @@ -973,6 +1009,47 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled) enabled ? MCP794XX_BIT_ALM0_EN : 0); } +static int m41txx_rtc_read_offset(struct device *dev, long *offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + u8 val; + + regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); + + val = ctrl_reg & M41TXX_M_CALIBRATION; + + /* check if positive */ + if (ctrl_reg & M41TXX_BIT_CALIB_SIGN) + *offset = (val * M41TXX_POS_OFFSET_STEP_PPB); + else + *offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB); + + return 0; +} + +static int m41txx_rtc_set_offset(struct device *dev, long offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + + if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET)) + return -ERANGE; + + if (offset >= 0) { + ctrl_reg = DIV_ROUND_CLOSEST(offset, + M41TXX_POS_OFFSET_STEP_PPB); + ctrl_reg |= M41TXX_BIT_CALIB_SIGN; + } else { + ctrl_reg = DIV_ROUND_CLOSEST(abs(offset), + M41TXX_NEG_OFFSET_STEP_PPB); + } + + return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, + M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN, + ctrl_reg); +} + /*----------------------------------------------------------------------*/ static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, From b41c23e152f2852ff7a299676af4f642bbe94abf Mon Sep 17 00:00:00 2001 From: Giulio Benetti Date: Wed, 25 Jul 2018 19:26:05 +0200 Subject: [PATCH 20/54] rtc: ds1307: add frequency_test_enable attribute on m41txx On m41txx you can enable open-drain OUT pin to check if offset is ok. Enabling OUT pin with frequency_test_enable attribute, OUT pin will tick 512 times faster than 1s tick base. Enable or Disable FT bit on CONTROL register if freq_test is 1 or 0. Signed-off-by: Giulio Benetti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 92 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 8268813f15c30..edccd0c0da250 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1050,6 +1050,94 @@ static int m41txx_rtc_set_offset(struct device *dev, long offset) ctrl_reg); } +static ssize_t frequency_test_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + bool freq_test_en; + int ret; + + ret = kstrtobool(buf, &freq_test_en); + if (ret) { + dev_err(dev, "Failed to store RTC Frequency Test attribute\n"); + return ret; + } + + regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, M41TXX_BIT_FT, + freq_test_en ? M41TXX_BIT_FT : 0); + + return count; +} + +static ssize_t frequency_test_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + + regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); + + return scnprintf(buf, PAGE_SIZE, (ctrl_reg & M41TXX_BIT_FT) ? "on\n" : + "off\n"); +} + +static DEVICE_ATTR_RW(frequency_test_enable); + +static struct attribute *rtc_freq_test_attrs[] = { + &dev_attr_frequency_test_enable.attr, + NULL, +}; + +static const struct attribute_group rtc_freq_test_attr_group = { + .attrs = rtc_freq_test_attrs, +}; + +static void rtc_calib_remove_sysfs_group(void *_dev) +{ + struct device *dev = _dev; + + sysfs_remove_group(&dev->kobj, &rtc_freq_test_attr_group); +} + +static int ds1307_add_frequency_test(struct ds1307 *ds1307) +{ + int err; + + switch (ds1307->type) { + case m41t0: + case m41t00: + case m41t11: + /* Export sysfs entries */ + err = sysfs_create_group(&(ds1307->dev)->kobj, + &rtc_freq_test_attr_group); + if (err) { + dev_err(ds1307->dev, + "Failed to create sysfs group: %d\n", + err); + return err; + } + + err = devm_add_action_or_reset(ds1307->dev, + rtc_calib_remove_sysfs_group, + ds1307->dev); + if (err) { + dev_err(ds1307->dev, + "Failed to add sysfs cleanup action: %d\n", + err); + sysfs_remove_group(&(ds1307->dev)->kobj, + &rtc_freq_test_attr_group); + return err; + } + break; + default: + break; + } + + return 0; +} + /*----------------------------------------------------------------------*/ static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, @@ -1792,6 +1880,10 @@ static int ds1307_probe(struct i2c_client *client, if (err) return err; + err = ds1307_add_frequency_test(ds1307); + if (err) + return err; + if (chip->nvram_size) { struct nvmem_config nvmem_cfg = { .name = "ds1307_nvram", From db7a67b9c3482bcc8314e42647f60b6f77f5afe4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:11:52 +0200 Subject: [PATCH 21/54] rtc: reorder Makefile entries A few entries are not placed correctly, reorder them. Signed-off-by: Alexandre Belloni --- drivers/rtc/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 5ff2fc0c361a8..290c1730fb0a7 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -36,9 +36,9 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o -obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o +obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o @@ -71,6 +71,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.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 obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o @@ -78,10 +79,10 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o +obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o -obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o @@ -100,7 +101,6 @@ obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o -obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o @@ -116,8 +116,8 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o -obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o +obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o @@ -154,9 +154,9 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o +obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o -obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o @@ -169,10 +169,10 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o +obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o -obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o From eb2bccb70b979d996ecb769d692b92ff12eabbb7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:13:21 +0200 Subject: [PATCH 22/54] rtc: move rtc_add_group/s definitions Move rtc_add_group and rtc_add_groups definition to rtc.h that is available for all RTC drivers. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-core.h | 14 -------------- include/linux/rtc.h | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h index ccc17a2e293d1..0abf98983e13f 100644 --- a/drivers/rtc/rtc-core.h +++ b/drivers/rtc/rtc-core.h @@ -40,23 +40,9 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc) #ifdef CONFIG_RTC_INTF_SYSFS const struct attribute_group **rtc_get_dev_attribute_groups(void); -int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp); -int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps); #else static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) { return NULL; } - -static inline -int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp) -{ - return 0; -} - -static inline -int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) -{ - return 0; -} #endif diff --git a/include/linux/rtc.h b/include/linux/rtc.h index faf00a1472d45..c8bb4a2b48c33 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -272,4 +272,20 @@ static inline int rtc_nvmem_register(struct rtc_device *rtc, static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} #endif +#ifdef CONFIG_RTC_INTF_SYSFS +int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp); +int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps); +#else +static inline +int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp) +{ + return 0; +} + +static inline +int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) +{ + return 0; +} +#endif #endif /* _LINUX_RTC_H_ */ From 4b3a6a3ac559d8f81d79e661ccde6bdd08395225 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:13:22 +0200 Subject: [PATCH 23/54] rtc: isl1208: don't include core header file The core header file is reserved for the core, stop including it. Also reorder includes alphabetically. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl1208.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 033f65aef5788..ec5ef518a09b2 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -10,12 +10,11 @@ * */ -#include -#include #include -#include -#include "rtc-core.h" +#include +#include #include +#include /* Register map */ /* rtc section */ From 2ab78755e93a10f6216c860a2012f3592f395603 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:14:58 +0200 Subject: [PATCH 24/54] rtc: tx4939: fixup nvmem name and register size The default word_size and stride of 1 are correct for the tx4939. Also fix the nvmem folder name. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 08dbefc79520e..61c110b2045f8 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -253,9 +253,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) struct resource *res; int irq, ret; struct nvmem_config nvmem_cfg = { - .name = "rv8803_nvram", - .word_size = 4, - .stride = 4, + .name = "tx4939_nvram", .size = TX4939_RTC_REG_RAMSIZE, .reg_read = tx4939_nvram_read, .reg_write = tx4939_nvram_write, From fd13c930fe6a6dce8ae1f551121cfd947fb24dd5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:16:31 +0200 Subject: [PATCH 25/54] rtc: test: make license text and module license match. The license text is specifying GPL v2 only but the MODULE_LICENSE is set to GPL which means GNU Public License v2 or later. When MODULE_LICENSE and boiler plate does not match, go for boiler plate license. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index ade6a82709bee..93f1638fb8c81 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -197,7 +197,7 @@ static void __exit test_exit(void) MODULE_AUTHOR("Alessandro Zummo "); MODULE_DESCRIPTION("RTC test driver/device"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); module_init(test_init); module_exit(test_exit); From c7080e2016074363298e05d5e4d91eaf243a58c2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 03:16:32 +0200 Subject: [PATCH 26/54] rtc: test: Switch to SPDX identifier Replace the license boilerplate by an SPDX identifier Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 93f1638fb8c81..6c5f09c815e8e 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * An RTC test device/driver * Copyright (C) 2005 Tower Technologies * Author: Alessandro Zummo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include From 8ddeb09de163ce4f362c610cd901f9c5ad4f58fd Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 19:52:09 +0200 Subject: [PATCH 27/54] rtc: ds1685: drop RTC_DS1685_PROC_REGS /proc is not the correct ABI to display debugging info. Remove RTC_DS1685_PROC_REGS as the driver hasn't seen any real development since it was included. Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 11 -------- drivers/rtc/rtc-ds1685.c | 61 ---------------------------------------- 2 files changed, 72 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4df9a3ec064bd..a819ef07b7ec2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1008,17 +1008,6 @@ config RTC_DRV_DS17885 endchoice -config RTC_DS1685_PROC_REGS - bool "Display register values in /proc" - depends on RTC_DRV_DS1685_FAMILY && PROC_FS - help - Enable this to display a readout of all of the RTC registers in - /proc/drivers/rtc. Keep in mind that this can potentially lead - to lost interrupts, as reading Control Register C will clear - all pending IRQ flags. - - Unless you are debugging this driver, choose N. - config RTC_DRV_DS1742 tristate "Maxim/Dallas DS1742/1743" depends on HAS_IOMEM diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 6f39f683a98c6..2bad1f50414f0 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -770,33 +770,6 @@ static const char *ds1685_rtc_sqw_freq[16] = { "512Hz", "256Hz", "128Hz", "64Hz", "32Hz", "16Hz", "8Hz", "4Hz", "2Hz" }; -#ifdef CONFIG_RTC_DS1685_PROC_REGS -/** - * ds1685_rtc_print_regs - helper function to print register values. - * @hex: hex byte to convert into binary bits. - * @dest: destination char array. - * - * This is basically a hex->binary function, just with extra spacing between - * the digits. It only works on 1-byte values (8 bits). - */ -static char* -ds1685_rtc_print_regs(u8 hex, char *dest) -{ - u32 i, j; - char *tmp = dest; - - for (i = 0; i < NUM_BITS; i++) { - *tmp++ = ((hex & 0x80) != 0 ? '1' : '0'); - for (j = 0; j < NUM_SPACES; j++) - *tmp++ = ' '; - hex <<= 1; - } - *tmp++ = '\0'; - - return dest; -} -#endif - /** * ds1685_rtc_proc - procfs access function. * @dev: pointer to device structure. @@ -809,9 +782,6 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) struct ds1685_priv *rtc = platform_get_drvdata(pdev); u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8]; char *model; -#ifdef CONFIG_RTC_DS1685_PROC_REGS - char bits[NUM_REGS][(NUM_BITS * NUM_SPACES) + NUM_BITS + 1]; -#endif /* Read all the relevant data from the control registers. */ ds1685_rtc_switch_to_bank1(rtc); @@ -859,28 +829,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) "Periodic IRQ\t: %s\n" "Periodic Rate\t: %s\n" "SQW Freq\t: %s\n" -#ifdef CONFIG_RTC_DS1685_PROC_REGS - "Serial #\t: %8phC\n" - "Register Status\t:\n" - " Ctrl A\t: UIP DV2 DV1 DV0 RS3 RS2 RS1 RS0\n" - "\t\t: %s\n" - " Ctrl B\t: SET PIE AIE UIE SQWE DM 2412 DSE\n" - "\t\t: %s\n" - " Ctrl C\t: IRQF PF AF UF --- --- --- ---\n" - "\t\t: %s\n" - " Ctrl D\t: VRT --- --- --- --- --- --- ---\n" - "\t\t: %s\n" -#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689) - " Ctrl 4A\t: VRT2 INCR BME --- PAB RF WF KF\n" -#else - " Ctrl 4A\t: VRT2 INCR --- --- PAB RF WF KF\n" -#endif - "\t\t: %s\n" - " Ctrl 4B\t: ABE E32k CS RCE PRS RIE WIE KSE\n" - "\t\t: %s\n", -#else "Serial #\t: %8phC\n", -#endif model, ((ctrla & RTC_CTRL_A_DV1) ? "enabled" : "disabled"), ((ctrlb & RTC_CTRL_B_2412) ? "24-hour" : "12-hour"), @@ -894,17 +843,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) ds1685_rtc_pirq_rate[(ctrla & RTC_CTRL_A_RS_MASK)] : "none"), (!((ctrl4b & RTC_CTRL_4B_E32K)) ? ds1685_rtc_sqw_freq[(ctrla & RTC_CTRL_A_RS_MASK)] : "32768Hz"), -#ifdef CONFIG_RTC_DS1685_PROC_REGS - ssn, - ds1685_rtc_print_regs(ctrla, bits[0]), - ds1685_rtc_print_regs(ctrlb, bits[1]), - ds1685_rtc_print_regs(ctrlc, bits[2]), - ds1685_rtc_print_regs(ctrld, bits[3]), - ds1685_rtc_print_regs(ctrl4a, bits[4]), - ds1685_rtc_print_regs(ctrl4b, bits[5])); -#else ssn); -#endif return 0; } #else From 482419e120da6da187be996c6871ed1e8bf02c51 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 19:52:10 +0200 Subject: [PATCH 28/54] rtc: ds1685: use generic nvmem Instead of adding a binary sysfs attribute from the driver, use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1685.c | 92 +++++++++++----------------------------- 1 file changed, 25 insertions(+), 67 deletions(-) diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 2bad1f50414f0..1f85e46b7888c 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -866,30 +866,13 @@ ds1685_rtc_ops = { }; /* ----------------------------------------------------------------------- */ - -/* ----------------------------------------------------------------------- */ -/* SysFS interface */ - -#ifdef CONFIG_SYSFS -/** - * ds1685_rtc_sysfs_nvram_read - reads rtc nvram via sysfs. - * @file: pointer to file structure. - * @kobj: pointer to kobject structure. - * @bin_attr: pointer to bin_attribute structure. - * @buf: pointer to char array to hold the output. - * @pos: current file position pointer. - * @size: size of the data to read. - */ -static ssize_t -ds1685_rtc_sysfs_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t pos, size_t size) +static int ds1685_nvram_read(void *priv, unsigned int pos, void *val, + size_t size) { - struct platform_device *pdev = - to_platform_device(container_of(kobj, struct device, kobj)); - struct ds1685_priv *rtc = platform_get_drvdata(pdev); + struct ds1685_priv *rtc = priv; ssize_t count; unsigned long flags = 0; + u8 *buf = val; spin_lock_irqsave(&rtc->lock, flags); ds1685_rtc_switch_to_bank0(rtc); @@ -943,33 +926,16 @@ ds1685_rtc_sysfs_nvram_read(struct file *filp, struct kobject *kobj, #endif /* !CONFIG_RTC_DRV_DS1689 */ spin_unlock_irqrestore(&rtc->lock, flags); - /* - * XXX: Bug? this appears to cause the function to get executed - * several times in succession. But it's the only way to actually get - * data written out to a file. - */ - return count; + return 0; } -/** - * ds1685_rtc_sysfs_nvram_write - writes rtc nvram via sysfs. - * @file: pointer to file structure. - * @kobj: pointer to kobject structure. - * @bin_attr: pointer to bin_attribute structure. - * @buf: pointer to char array to hold the input. - * @pos: current file position pointer. - * @size: size of the data to write. - */ -static ssize_t -ds1685_rtc_sysfs_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t pos, size_t size) +static int ds1685_nvram_write(void *priv, unsigned int pos, void *val, + size_t size) { - struct platform_device *pdev = - to_platform_device(container_of(kobj, struct device, kobj)); - struct ds1685_priv *rtc = platform_get_drvdata(pdev); + struct ds1685_priv *rtc = priv; ssize_t count; unsigned long flags = 0; + u8 *buf = val; spin_lock_irqsave(&rtc->lock, flags); ds1685_rtc_switch_to_bank0(rtc); @@ -1023,27 +989,13 @@ ds1685_rtc_sysfs_nvram_write(struct file *filp, struct kobject *kobj, #endif /* !CONFIG_RTC_DRV_DS1689 */ spin_unlock_irqrestore(&rtc->lock, flags); - return count; + return 0; } -/** - * struct ds1685_rtc_sysfs_nvram_attr - sysfs attributes for rtc nvram. - * @attr: nvram attributes. - * @read: nvram read function. - * @write: nvram write function. - * @size: nvram total size (bank0 + extended). - */ -static struct bin_attribute -ds1685_rtc_sysfs_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - .read = ds1685_rtc_sysfs_nvram_read, - .write = ds1685_rtc_sysfs_nvram_write, - .size = NVRAM_TOTAL_SZ -}; +/* ----------------------------------------------------------------------- */ +/* SysFS interface */ +#ifdef CONFIG_SYSFS /** * ds1685_rtc_sysfs_battery_show - sysfs file for main battery status. * @dev: pointer to device structure. @@ -1136,11 +1088,6 @@ ds1685_rtc_sysfs_register(struct device *dev) { int ret = 0; - sysfs_bin_attr_init(&ds1685_rtc_sysfs_nvram_attr); - ret = sysfs_create_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr); - if (ret) - return ret; - ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp); if (ret) return ret; @@ -1155,7 +1102,6 @@ ds1685_rtc_sysfs_register(struct device *dev) static int ds1685_rtc_sysfs_unregister(struct device *dev) { - sysfs_remove_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr); sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp); return 0; @@ -1181,6 +1127,12 @@ ds1685_rtc_probe(struct platform_device *pdev) u8 ctrla, ctrlb, hours; unsigned char am_pm; int ret = 0; + struct nvmem_config nvmem_cfg = { + .name = "ds1685_nvram", + .size = NVRAM_TOTAL_SZ, + .reg_read = ds1685_nvram_read, + .reg_write = ds1685_nvram_write, + }; /* Get the platform data. */ pdata = (struct ds1685_rtc_platform_data *) pdev->dev.platform_data; @@ -1444,6 +1396,12 @@ ds1685_rtc_probe(struct platform_device *pdev) return ret; #endif + rtc_dev->nvram_old_abi = true; + nvmem_cfg.priv = rtc; + ret = rtc_nvmem_register(rtc_dev, &nvmem_cfg); + if (ret) + return ret; + return rtc_register_device(rtc_dev); } From cfb74916e2ecf018e3189959edd2a1356b2fd89e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 19 Sep 2018 19:52:11 +0200 Subject: [PATCH 29/54] rtc: ds1685: use rtc_add_group Use rtc_add_group to add the sysfs group in a race free manner. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1685.c | 40 +--------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 1f85e46b7888c..b0723025ac31e 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -995,7 +995,6 @@ static int ds1685_nvram_write(void *priv, unsigned int pos, void *val, /* ----------------------------------------------------------------------- */ /* SysFS interface */ -#ifdef CONFIG_SYSFS /** * ds1685_rtc_sysfs_battery_show - sysfs file for main battery status. * @dev: pointer to device structure. @@ -1079,37 +1078,6 @@ ds1685_rtc_sysfs_misc_grp = { .attrs = ds1685_rtc_sysfs_misc_attrs, }; -/** - * ds1685_rtc_sysfs_register - register sysfs files. - * @dev: pointer to device structure. - */ -static int -ds1685_rtc_sysfs_register(struct device *dev) -{ - int ret = 0; - - ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp); - if (ret) - return ret; - - return 0; -} - -/** - * ds1685_rtc_sysfs_unregister - unregister sysfs files. - * @dev: pointer to device structure. - */ -static int -ds1685_rtc_sysfs_unregister(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp); - - return 0; -} -#endif /* CONFIG_SYSFS */ - - - /* ----------------------------------------------------------------------- */ /* Driver Probe/Removal */ @@ -1390,11 +1358,9 @@ ds1685_rtc_probe(struct platform_device *pdev) /* Setup complete. */ ds1685_rtc_switch_to_bank0(rtc); -#ifdef CONFIG_SYSFS - ret = ds1685_rtc_sysfs_register(&pdev->dev); + ret = rtc_add_group(rtc_dev, &ds1685_rtc_sysfs_misc_grp); if (ret) return ret; -#endif rtc_dev->nvram_old_abi = true; nvmem_cfg.priv = rtc; @@ -1414,10 +1380,6 @@ ds1685_rtc_remove(struct platform_device *pdev) { struct ds1685_priv *rtc = platform_get_drvdata(pdev); -#ifdef CONFIG_SYSFS - ds1685_rtc_sysfs_unregister(&pdev->dev); -#endif - /* Read Ctrl B and clear PIE/AIE/UIE. */ rtc->write(rtc, RTC_CTRL_B, (rtc->read(rtc, RTC_CTRL_B) & From 6a5f2a1f4dcdb31fde467d9ae612505692eb4243 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 20 Sep 2018 16:35:26 +0200 Subject: [PATCH 30/54] rtc: ds1307: use rtc_add_group Register frequency test using rtc_add_group to avoid a possible race condition and simplify the code. This also moves the attribute to its proper location under the rtc device instead of the i2c parent device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 53 +++++++++++----------------------------- 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index edccd0c0da250..982503a168d0d 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1050,11 +1050,11 @@ static int m41txx_rtc_set_offset(struct device *dev, long offset) ctrl_reg); } -static ssize_t frequency_test_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t frequency_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct ds1307 *ds1307 = dev_get_drvdata(dev); + struct ds1307 *ds1307 = dev_get_drvdata(dev->parent); bool freq_test_en; int ret; @@ -1070,11 +1070,11 @@ static ssize_t frequency_test_enable_store(struct device *dev, return count; } -static ssize_t frequency_test_enable_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t frequency_test_show(struct device *dev, + struct device_attribute *attr, + char *buf) { - struct ds1307 *ds1307 = dev_get_drvdata(dev); + struct ds1307 *ds1307 = dev_get_drvdata(dev->parent); unsigned int ctrl_reg; regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); @@ -1083,10 +1083,10 @@ static ssize_t frequency_test_enable_show(struct device *dev, "off\n"); } -static DEVICE_ATTR_RW(frequency_test_enable); +static DEVICE_ATTR_RW(frequency_test); static struct attribute *rtc_freq_test_attrs[] = { - &dev_attr_frequency_test_enable.attr, + &dev_attr_frequency_test.attr, NULL, }; @@ -1094,13 +1094,6 @@ static const struct attribute_group rtc_freq_test_attr_group = { .attrs = rtc_freq_test_attrs, }; -static void rtc_calib_remove_sysfs_group(void *_dev) -{ - struct device *dev = _dev; - - sysfs_remove_group(&dev->kobj, &rtc_freq_test_attr_group); -} - static int ds1307_add_frequency_test(struct ds1307 *ds1307) { int err; @@ -1109,27 +1102,9 @@ static int ds1307_add_frequency_test(struct ds1307 *ds1307) case m41t0: case m41t00: case m41t11: - /* Export sysfs entries */ - err = sysfs_create_group(&(ds1307->dev)->kobj, - &rtc_freq_test_attr_group); - if (err) { - dev_err(ds1307->dev, - "Failed to create sysfs group: %d\n", - err); - return err; - } - - err = devm_add_action_or_reset(ds1307->dev, - rtc_calib_remove_sysfs_group, - ds1307->dev); - if (err) { - dev_err(ds1307->dev, - "Failed to add sysfs cleanup action: %d\n", - err); - sysfs_remove_group(&(ds1307->dev)->kobj, - &rtc_freq_test_attr_group); + err = rtc_add_group(ds1307->rtc, &rtc_freq_test_attr_group); + if (err) return err; - } break; default: break; @@ -1876,11 +1851,11 @@ static int ds1307_probe(struct i2c_client *client, } ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; - err = rtc_register_device(ds1307->rtc); + err = ds1307_add_frequency_test(ds1307); if (err) return err; - err = ds1307_add_frequency_test(ds1307); + err = rtc_register_device(ds1307->rtc); if (err) return err; From 0ae3f24ded773edcc5e40ed94c84fbfabd516e14 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 22 Sep 2018 01:22:34 +0200 Subject: [PATCH 31/54] rtc: lib: correct documentation typo rtc_time64_to_tm has not been called rtc_time_to_tm64 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 4a3c0f3aab149..ef160da842200 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -47,7 +47,7 @@ EXPORT_SYMBOL(rtc_year_days); /* - * rtc_time_to_tm64 - Converts time64_t to rtc_time. + * rtc_time64_to_tm - Converts time64_t to rtc_time. * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. */ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) From 7d61cbb945a753af08e247b5f10bdd5dbb8d6c80 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:25:34 +0200 Subject: [PATCH 32/54] rtc: armada38x: fix possible race condition The IRQ is requested before the struct rtc is allocated and registered, but this struct is used in the IRQ handler. This may lead to a NULL pointer dereference. Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before requesting the IRQ. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-armada38x.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index bde53c8ccee2c..b74338d6dde60 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -514,7 +514,6 @@ MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); static __init int armada38x_rtc_probe(struct platform_device *pdev) { - const struct rtc_class_ops *ops; struct resource *res; struct armada38x_rtc *rtc; const struct of_device_id *match; @@ -551,6 +550,11 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no irq\n"); return rtc->irq; } + + rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq, 0, pdev->name, rtc) < 0) { dev_warn(&pdev->dev, "Interrupt not available.\n"); @@ -560,28 +564,24 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) if (rtc->irq != -1) { device_init_wakeup(&pdev->dev, 1); - ops = &armada38x_rtc_ops; + rtc->rtc_dev->ops = &armada38x_rtc_ops; } else { /* * If there is no interrupt available then we can't * use the alarm */ - ops = &armada38x_rtc_ops_noirq; + rtc->rtc_dev->ops = &armada38x_rtc_ops_noirq; } rtc->data = (struct armada38x_rtc_data *)match->data; - /* Update RTC-MBUS bridge timing parameters */ rtc->data->update_mbus_timing(rtc); - rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, - ops, THIS_MODULE); - if (IS_ERR(rtc->rtc_dev)) { - ret = PTR_ERR(rtc->rtc_dev); + ret = rtc_register_device(rtc->rtc_dev); + if (ret) dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - return ret; - } - return 0; + + return ret; } #ifdef CONFIG_PM_SLEEP From ef2a7176c837183043ecfdc5e995a3275f37ee39 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:25:35 +0200 Subject: [PATCH 33/54] rtc: armada38x: add range The RTC is a 32bit seconds counter. Signed-off-by: Alexandre Belloni Tested-by: Gregory CLEMENT Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-armada38x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index b74338d6dde60..d0278ad0a7f9c 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -577,6 +577,8 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) /* Update RTC-MBUS bridge timing parameters */ rtc->data->update_mbus_timing(rtc); + 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); From f6e3d773e10bc4c7c19083cfdd3e275cfece58de Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:25:36 +0200 Subject: [PATCH 34/54] rtc: armada38x: switch to rtc_time64_to_tm/rtc_tm_to_time64 Call the 64bit versions of rtc_time_to_tm and rtc_tm_to_time now that the range is enforced by the core. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-armada38x.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index d0278ad0a7f9c..9e78f004670b3 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -224,7 +224,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) time = rtc->data->read_rtc_reg(rtc, RTC_TIME); spin_unlock_irqrestore(&rtc->lock, flags); - rtc_time_to_tm(time, tm); + rtc_time64_to_tm(time, tm); return 0; } @@ -249,13 +249,9 @@ static void armada38x_rtc_reset(struct armada38x_rtc *rtc) static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct armada38x_rtc *rtc = dev_get_drvdata(dev); - int ret = 0; unsigned long time, flags; - ret = rtc_tm_to_time(tm, &time); - - if (ret) - goto out; + time = rtc_tm_to_time64(tm); if (!rtc->initialized) armada38x_rtc_reset(rtc); @@ -264,8 +260,7 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_delayed_write(time, rtc, RTC_TIME); spin_unlock_irqrestore(&rtc->lock, flags); -out: - return ret; + return 0; } static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) @@ -284,7 +279,7 @@ static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) spin_unlock_irqrestore(&rtc->lock, flags); alrm->enabled = val ? 1 : 0; - rtc_time_to_tm(time, &alrm->time); + rtc_time64_to_tm(time, &alrm->time); return 0; } @@ -295,12 +290,8 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); unsigned long time, flags; - int ret = 0; - ret = rtc_tm_to_time(&alrm->time, &time); - - if (ret) - goto out; + time = rtc_tm_to_time64(&alrm->time); spin_lock_irqsave(&rtc->lock, flags); @@ -313,8 +304,7 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) spin_unlock_irqrestore(&rtc->lock, flags); -out: - return ret; + return 0; } static int armada38x_rtc_alarm_irq_enable(struct device *dev, From 02a6e1293235ba9b38c7f7428e0993fd972557cf Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 17:05:07 +0200 Subject: [PATCH 35/54] rtc: rs5c348: remove useless label Since commit 8fb1ecb36f7e ("rtc: rtc-rs5c348: use devm_*() functions") the kfree_exit label simply returns ret. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c348.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index f2de8b17e7e36..aeb14fc0175db 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -161,7 +161,7 @@ static int rs5c348_probe(struct spi_device *spi) ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS)); if (ret < 0 || (ret & 0x80)) { dev_err(&spi->dev, "not found.\n"); - goto kfree_exit; + return ret; } dev_info(&spi->dev, "spiclk %u KHz.\n", @@ -170,7 +170,7 @@ static int rs5c348_probe(struct spi_device *spi) /* turn RTC on if it was not on */ ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2)); if (ret < 0) - goto kfree_exit; + return ret; if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) { u8 buf[2]; struct rtc_time tm; @@ -181,33 +181,29 @@ static int rs5c348_probe(struct spi_device *spi) rtc_time_to_tm(0, &tm); /* 1970/1/1 */ ret = rs5c348_rtc_set_time(&spi->dev, &tm); if (ret < 0) - goto kfree_exit; + return ret; buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2); buf[1] = 0; ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0); if (ret < 0) - goto kfree_exit; + return ret; } ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1)); if (ret < 0) - goto kfree_exit; + return ret; if (ret & RS5C348_BIT_24H) pdata->rtc_24h = 1; rtc = devm_rtc_device_register(&spi->dev, rs5c348_driver.driver.name, &rs5c348_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - ret = PTR_ERR(rtc); - goto kfree_exit; - } + if (IS_ERR(rtc)) + return PTR_ERR(rtc); pdata->rtc = rtc; return 0; - kfree_exit: - return ret; } static struct spi_driver rs5c348_driver = { From 2d7be4ed7addcaae8eba6ae8cdee83e2f7d39059 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 17:05:08 +0200 Subject: [PATCH 36/54] rtc: rs5c348: remove forward declaration The name passed to devm_rtc_device_register is now unused. anyway, switch to devm_rtc_allocate_device to avoid forward declaring rs5c348_driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c348.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index aeb14fc0175db..7b9c7dc5b309f 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -143,8 +143,6 @@ static const struct rtc_class_ops rs5c348_rtc_ops = { .set_time = rs5c348_rtc_set_time, }; -static struct spi_driver rs5c348_driver; - static int rs5c348_probe(struct spi_device *spi) { int ret; @@ -195,15 +193,15 @@ static int rs5c348_probe(struct spi_device *spi) if (ret & RS5C348_BIT_24H) pdata->rtc_24h = 1; - rtc = devm_rtc_device_register(&spi->dev, rs5c348_driver.driver.name, - &rs5c348_rtc_ops, THIS_MODULE); - + rtc = devm_rtc_allocate_device(&spi->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; - return 0; + rtc->ops = &rs5c348_rtc_ops; + + return rtc_register_device(rtc); } static struct spi_driver rs5c348_driver = { From 1654a2b06b936c5e123978e6d9523b022a2a5aa1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 17:05:09 +0200 Subject: [PATCH 37/54] rtc: rs5c348: report error when time is invalid Instead of resetting the RTC to an bogus valid time, let userspace know that the time is invalid when XSTP is set. Reset XSTP when setting the time again. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c348.c | 43 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 7b9c7dc5b309f..6582be707bd0f 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -66,6 +66,17 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 txbuf[5+7], *txp; int ret; + ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2)); + if (ret < 0) + return ret; + if (ret & RS5C348_BIT_XSTP) { + txbuf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2); + txbuf[1] = 0; + ret = spi_write_then_read(spi, txbuf, 2, NULL, 0); + if (ret < 0) + return ret; + } + /* Transfer 5 bytes before writing SEC. This gives 31us for carry. */ txp = txbuf; txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ @@ -102,6 +113,16 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 txbuf[5], rxbuf[7]; int ret; + ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2)); + if (ret < 0) + return ret; + if (ret & RS5C348_BIT_VDET) + dev_warn(&spi->dev, "voltage-low detected.\n"); + if (ret & RS5C348_BIT_XSTP) { + dev_warn(&spi->dev, "oscillator-stop detected.\n"); + return -EINVAL; + } + /* Transfer 5 byte befores reading SEC. This gives 31us for carry. */ txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ txbuf[1] = 0; /* dummy */ @@ -165,28 +186,6 @@ static int rs5c348_probe(struct spi_device *spi) dev_info(&spi->dev, "spiclk %u KHz.\n", (spi->max_speed_hz + 500) / 1000); - /* turn RTC on if it was not on */ - ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2)); - if (ret < 0) - return ret; - if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) { - u8 buf[2]; - struct rtc_time tm; - if (ret & RS5C348_BIT_VDET) - dev_warn(&spi->dev, "voltage-low detected.\n"); - if (ret & RS5C348_BIT_XSTP) - dev_warn(&spi->dev, "oscillator-stop detected.\n"); - rtc_time_to_tm(0, &tm); /* 1970/1/1 */ - ret = rs5c348_rtc_set_time(&spi->dev, &tm); - if (ret < 0) - return ret; - buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2); - buf[1] = 0; - ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0); - if (ret < 0) - return ret; - } - ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1)); if (ret < 0) return ret; From b56295dd337a35402663b230ac62260cbe7ee5ac Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:49:00 +0200 Subject: [PATCH 38/54] rtc: ab8500: use rtc_add_group Use rtc_add_group to add the sysfs group in a race free manner. Signed-off-by: Alexandre Belloni Reviewed-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab8500.c | 41 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index e28f4401fd35a..e97015e5c63ee 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -360,15 +360,14 @@ static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR, ab8500_sysfs_show_rtc_calibration, ab8500_sysfs_store_rtc_calibration); -static int ab8500_sysfs_rtc_register(struct device *dev) -{ - return device_create_file(dev, &dev_attr_rtc_calibration); -} +static struct attribute *ab8500_rtc_attrs[] = { + &dev_attr_rtc_calibration.attr, + NULL +}; -static void ab8500_sysfs_rtc_unregister(struct device *dev) -{ - device_remove_file(dev, &dev_attr_rtc_calibration); -} +static const struct attribute_group ab8500_rtc_sysfs_files = { + .attrs = ab8500_rtc_attrs, +}; static irqreturn_t rtc_alarm_handler(int irq, void *data) { @@ -429,14 +428,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, true); - rtc = devm_rtc_device_register(&pdev->dev, "ab8500-rtc", - (struct rtc_class_ops *)platid->driver_data, - THIS_MODULE); - if (IS_ERR(rtc)) { - dev_err(&pdev->dev, "Registration failed\n"); - err = PTR_ERR(rtc); - return err; - } + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + rtc->ops = (struct rtc_class_ops *)platid->driver_data; err = devm_request_threaded_irq(&pdev->dev, irq, NULL, rtc_alarm_handler, IRQF_ONESHOT, @@ -447,22 +443,19 @@ static int ab8500_rtc_probe(struct platform_device *pdev) dev_pm_set_wake_irq(&pdev->dev, irq); platform_set_drvdata(pdev, rtc); - err = ab8500_sysfs_rtc_register(&pdev->dev); - if (err) { - dev_err(&pdev->dev, "sysfs RTC failed to register\n"); - return err; - } - rtc->uie_unsupported = 1; - return 0; + err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files); + if (err) + return err; + + return rtc_register_device(rtc); } static int ab8500_rtc_remove(struct platform_device *pdev) { dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); - ab8500_sysfs_rtc_unregister(&pdev->dev); return 0; } From 38ab97aebe47831e576095e58dac31860152b0fa Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:49:01 +0200 Subject: [PATCH 39/54] rtc: ab8500: let the core handle range Let the core handle offsetting and windowing the RTC range. The RTC has a 24 bit counter for minutes plus a seconds counter. Keep the epoch at the beginning of 2000. Signed-off-by: Alexandre Belloni Acked-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab8500.c | 53 +++------------------------------------- 1 file changed, 4 insertions(+), 49 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index e97015e5c63ee..2e2671b84ab0e 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -46,7 +46,6 @@ #define RTC_STATUS_DATA 0x01 #define COUNTS_PER_SEC (0xF000 / 60) -#define AB8500_RTC_EPOCH 2000 static const u8 ab8500_rtc_time_regs[] = { AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, @@ -59,23 +58,6 @@ static const u8 ab8500_rtc_alarm_regs[] = { AB8500_RTC_ALRM_MIN_LOW_REG }; -/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ -static unsigned long get_elapsed_seconds(int year) -{ - unsigned long secs; - struct rtc_time tm = { - .tm_year = year - 1900, - .tm_mday = 1, - }; - - /* - * This function calculates secs from 1970 and not from - * 1900, even if we supply the offset from year 1900. - */ - rtc_tm_to_time(&tm, &secs); - return secs; -} - static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) { unsigned long timeout = jiffies + HZ; @@ -118,9 +100,6 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) secs = secs / COUNTS_PER_SEC; secs = secs + (mins * 60); - /* Add back the initially subtracted number of seconds */ - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); - rtc_time_to_tm(secs, tm); return 0; } @@ -131,21 +110,8 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; unsigned long no_secs, no_mins, secs = 0; - if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - - /* Get the number of seconds since 1970 */ rtc_tm_to_time(tm, &secs); - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00, since - * we only have a small counter in the RTC. - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); - no_mins = secs / 60; no_secs = secs % 60; @@ -202,9 +168,6 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); secs = mins * 60; - /* Add back the initially subtracted number of seconds */ - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); - rtc_time_to_tm(secs, &alarm->time); return rtc_valid_tm(&alarm->time); @@ -224,12 +187,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) unsigned long mins, secs = 0, cursec = 0; struct rtc_time curtm; - if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - /* Get the number of seconds since 1970 */ rtc_tm_to_time(&alarm->time, &secs); @@ -245,12 +202,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) return -EINVAL; } - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00, since - * we only have a small counter in the RTC. - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); - mins = secs / 60; buf[2] = mins & 0xFF; @@ -445,6 +396,10 @@ static int ab8500_rtc_probe(struct platform_device *pdev) rtc->uie_unsupported = 1; + rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs + rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000; + rtc->set_start_time = true; + err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files); if (err) return err; From 9a90a5bcc73e4805989ad791cdd075a81f1a23ef Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 24 Sep 2018 16:49:02 +0200 Subject: [PATCH 40/54] rtc: ab8500: remove useless check rtc_time_to_tm always rturns a valid tm, there is no need to validate it. Signed-off-by: Alexandre Belloni Acked-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 2e2671b84ab0e..1f0cbd51ba06e 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -170,7 +170,7 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) rtc_time_to_tm(secs, &alarm->time); - return rtc_valid_tm(&alarm->time); + return 0; } static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) From 89e27ce49846a7dedbcaefccbb6cc885c5baae14 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 1 Oct 2018 23:51:35 +0200 Subject: [PATCH 41/54] rtc: vr41xx: switch to rtc_time64_to_tm/rtc_tm_to_time64 Call the 64bit versions of rtc_time_to_tm now that the range is enforced by the core. Also remove the open coded rtc_tm_to_time64. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-vr41xx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 70f013e692b0a..e66d0f63cee22 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -136,8 +136,7 @@ static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time) time64_t epoch_sec, current_sec; epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0); - current_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + current_sec = rtc_tm_to_time64(time); write_elapsed_second(current_sec - epoch_sec); @@ -158,7 +157,7 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) spin_unlock_irq(&rtc_lock); - rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time); + rtc_time64_to_tm((high << 17) | (mid << 1) | (low >> 15), time); return 0; } @@ -166,10 +165,8 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { time64_t alarm_sec; - struct rtc_time *time = &wkalrm->time; - alarm_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + alarm_sec = rtc_tm_to_time64(&wkalrm->time); spin_lock_irq(&rtc_lock); From 959e8b77bf9232a1956e03325837047b110553b2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 2 Oct 2018 00:05:25 +0200 Subject: [PATCH 42/54] rtc: mv: let the core handle invalid alarms Instead of lying to the core when the alarm is invalid, let it handle that by returning the error. Signed-off-by: Alexandre Belloni Tested-by: Gregory CLEMENT (on Armada 375 DB) Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mv.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 4b198b3778d3a..e7f14bd12fe37 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -125,13 +125,9 @@ static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) /* hw counts from year 2000, but tm_year is relative to 1900 */ alm->time.tm_year = bcd2bin(year) + 100; - if (rtc_valid_tm(&alm->time) < 0) { - dev_err(dev, "retrieved alarm date/time is not valid.\n"); - rtc_time_to_tm(0, &alm->time); - } - alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); - return 0; + + return rtc_valid_tm(&alm->time); } static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) From d197a253855d2d8e507a003880aab35c4e2473db Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 2 Oct 2018 02:08:49 +0100 Subject: [PATCH 43/54] rtc: cmos: Fix non-ACPI undefined reference to `hpet_rtc_interrupt' Fix a commit 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") `rtc-cmos' regression causing a link error: drivers/rtc/rtc-cmos.o: In function `cmos_platform_probe': rtc-cmos.c:(.init.text+0x33c): undefined reference to `hpet_rtc_interrupt' rtc-cmos.c:(.init.text+0x3f4): undefined reference to `hpet_rtc_interrupt' with non-ACPI platforms using this driver. The cause is the change of the condition guarding the use of `hpet_rtc_interrupt'. Previously it was a call to `is_hpet_enabled'. That function is static inline and has a hardcoded 0 result for non-ACPI platforms, which imply !HPET_EMULATE_RTC. Consequently the compiler optimized the whole block away including the reference to `hpet_rtc_interrupt', which never made it to the link stage. Now the guarding condition is a call to `use_hpet_alarm', which is not static inline and therefore the compiler may not be able to prove that it actually always returns 0 for non-ACPI platforms. Consequently the build breaks with an unsatisfied reference, because `hpet_rtc_interrupt' is nowhere defined at link time. Fix the problem by marking `use_hpet_alarm' inline. As the `inline' keyword serves as an optimization hint rather than a requirement the compiler is still free to choose whether inlining will be beneficial or not for ACPI platforms. Signed-off-by: Maciej W. Rozycki Fixes: 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") Cc: stable@vger.kernel.org # 4.18+ Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index cd3a2411bc2f5..1c98f845102ca 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -167,7 +167,7 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler) #endif /* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */ -static int use_hpet_alarm(void) +static inline int use_hpet_alarm(void) { return is_hpet_enabled() && !use_acpi_alarm; } From bc51098cdd9573bfdecfd02fc8ed474419d73ea0 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 2 Oct 2018 02:09:05 +0100 Subject: [PATCH 44/54] rtc: cmos: Remove the `use_acpi_alarm' module parameter for !ACPI Fix a problem with commit 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") defining `use_acpi_alarm' module parameter even for non-ACPI platforms, which ignore it. Wrap the definition into #ifdef CONFIG_ACPI and use a static inline wrapper function, hardcoded to return 0 and consequently optimized away for !ACPI, following the existing pattern with HPET handling functions. Signed-off-by: Maciej W. Rozycki Fixes: 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") Cc: stable@vger.kernel.org # 4.18+ Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 1c98f845102ca..df0c5776d49bb 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -50,6 +50,7 @@ /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ #include +#ifdef CONFIG_ACPI /* * Use ACPI SCI to replace HPET interrupt for RTC Alarm event * @@ -61,6 +62,18 @@ static bool use_acpi_alarm; module_param(use_acpi_alarm, bool, 0444); +static inline int cmos_use_acpi_alarm(void) +{ + return use_acpi_alarm; +} +#else /* !CONFIG_ACPI */ + +static inline int cmos_use_acpi_alarm(void) +{ + return 0; +} +#endif + struct cmos_rtc { struct rtc_device *rtc; struct device *dev; @@ -169,7 +182,7 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler) /* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */ static inline int use_hpet_alarm(void) { - return is_hpet_enabled() && !use_acpi_alarm; + return is_hpet_enabled() && !cmos_use_acpi_alarm(); } /*----------------------------------------------------------------*/ @@ -340,7 +353,7 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) if (use_hpet_alarm()) hpet_set_rtc_irq_bit(mask); - if ((mask & RTC_AIE) && use_acpi_alarm) { + if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) { if (cmos->wake_on) cmos->wake_on(cmos->dev); } @@ -358,7 +371,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) if (use_hpet_alarm()) hpet_mask_rtc_irq_bit(mask); - if ((mask & RTC_AIE) && use_acpi_alarm) { + if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) { if (cmos->wake_off) cmos->wake_off(cmos->dev); } @@ -980,7 +993,7 @@ static int cmos_suspend(struct device *dev) } spin_unlock_irq(&rtc_lock); - if ((tmp & RTC_AIE) && !use_acpi_alarm) { + if ((tmp & RTC_AIE) && !cmos_use_acpi_alarm()) { cmos->enabled_wake = 1; if (cmos->wake_on) cmos->wake_on(dev); @@ -1031,7 +1044,7 @@ static void cmos_check_wkalrm(struct device *dev) * ACPI RTC wake event is cleared after resume from STR, * ACK the rtc irq here */ - if (t_now >= cmos->alarm_expires && use_acpi_alarm) { + if (t_now >= cmos->alarm_expires && cmos_use_acpi_alarm()) { cmos_interrupt(0, (void *)cmos->rtc); return; } @@ -1053,7 +1066,7 @@ static int __maybe_unused cmos_resume(struct device *dev) struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char tmp; - if (cmos->enabled_wake && !use_acpi_alarm) { + if (cmos->enabled_wake && !cmos_use_acpi_alarm()) { if (cmos->wake_off) cmos->wake_off(dev); else @@ -1132,7 +1145,7 @@ static u32 rtc_handler(void *context) * Or else, ACPI SCI is enabled during suspend/resume only, * update rtc irq in that case. */ - if (use_acpi_alarm) + if (cmos_use_acpi_alarm()) cmos_interrupt(0, (void *)cmos->rtc); else { /* Fix me: can we use cmos_interrupt() here as well? */ From fe0b5cedc2b73c9b005e1812c0ae5b922a96243a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:12:09 +0200 Subject: [PATCH 45/54] rtc: tegra: Propagate errors from platform_get_irq() Instead of confusingly returning -EBUSY on failure to obtain an interrupt, propagate the real error code. While at it, let the user know why the interrupt could not be acquired. Signed-off-by: Thierry Reding Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tegra.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 8dc48fe7fc356..c9e77a83cd1bc 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -322,9 +322,13 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) if (IS_ERR(info->rtc_base)) return PTR_ERR(info->rtc_base); - info->tegra_rtc_irq = platform_get_irq(pdev, 0); - if (info->tegra_rtc_irq <= 0) - return -EBUSY; + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "failed to get platform IRQ: %d\n", ret); + return ret; + } + + info->tegra_rtc_irq = ret; info->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) From c3e04915b8674a748916db6f7adf92da03b68bef Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 4 Oct 2018 15:07:01 +0200 Subject: [PATCH 46/54] rtc: m41t80: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that in this particular case, I replaced "Fall" with a proper "Fall through" comment. Addresses-Coverity-ID: 1373875 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index ad03e2f12f5d3..a3fb235fea0d1 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -745,7 +745,7 @@ static int wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; wdt_margin = new_margin; wdt_ping(); - /* Fall */ + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(wdt_margin, (int __user *)arg); From 6f5b390b3abe690ac3875a226e96a1528647f948 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 21 Oct 2018 22:00:41 +0200 Subject: [PATCH 47/54] rtc: ds1685: simplify getting .driver_data We should get 'driver_data' from 'struct device' directly. Going via platform_device is an unneeded step back and forth. Signed-off-by: Wolfram Sang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1685.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index b0723025ac31e..2710f2594c42a 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -778,8 +778,7 @@ static const char *ds1685_rtc_sqw_freq[16] = { static int ds1685_rtc_proc(struct device *dev, struct seq_file *seq) { - struct platform_device *pdev = to_platform_device(dev); - struct ds1685_priv *rtc = platform_get_drvdata(pdev); + struct ds1685_priv *rtc = dev_get_drvdata(dev); u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8]; char *model; From 7dceef78f310f5351735060d78a1777c69606016 Mon Sep 17 00:00:00 2001 From: Soeren Moch Date: Mon, 22 Oct 2018 14:38:12 +0200 Subject: [PATCH 48/54] rtc: ds1307: fix ds1339 wakealarm support Commit 51ed73eb998a1c79a2b0e9bed68f75a8a2c93b9b ("rtc: ds1340: Add support for trickle charger.") breaks ds1339 wakealarm support by limiting accessible registers. Fix this. Fixes: 51ed73eb998a ("rtc: ds1340: Add support for trickle charger.") Cc: stable@vger.kernel.org Signed-off-by: Soeren Moch Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 982503a168d0d..74b31dce484fe 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1524,7 +1524,6 @@ static void ds1307_clks_register(struct ds1307 *ds1307) static const struct regmap_config regmap_config = { .reg_bits = 8, .val_bits = 8, - .max_register = 0x9, }; static int ds1307_probe(struct i2c_client *client, From ef0f02fd69a02b50e468a4ddbe33e3d81671e248 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 19 Oct 2018 13:43:45 -0700 Subject: [PATCH 49/54] rtc: s35390a: Change buf's type to u8 in s35390a_init Clang warns: drivers/rtc/rtc-s35390a.c:124:27: warning: implicit conversion from 'int' to 'char' changes value from 192 to -64 [-Wconstant-conversion] buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; ~ ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ 1 warning generated. Update buf to be an unsigned 8-bit integer, which matches the buf member in struct i2c_msg. https://github.com/ClangBuiltLinux/linux/issues/145 Signed-off-by: Nathan Chancellor Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 77feb603cd4c0..3c64dbb08109a 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -108,7 +108,7 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) static int s35390a_init(struct s35390a *s35390a) { - char buf; + u8 buf; int ret; unsigned initcount = 0; From a86d6b23ed9729d47b2818857d8fa5d8e3f8284a Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 18 Oct 2018 16:52:26 +0800 Subject: [PATCH 50/54] rtc: sc27xx: Set wakeup capability before registering rtc device Set wakeup capability before registering rtc device, in case the alarmtimer can find one available rtc device. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index deea5c3726adb..8afba125ad716 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -631,16 +631,18 @@ static int sprd_rtc_probe(struct platform_device *pdev) return ret; } + device_init_wakeup(&pdev->dev, 1); + rtc->rtc->ops = &sprd_rtc_ops; rtc->rtc->range_min = 0; 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; } - device_init_wakeup(&pdev->dev, 1); return 0; } From 7db5adfa63167dac548022c973e00da7f56ffb72 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 18 Oct 2018 16:52:27 +0800 Subject: [PATCH 51/54] rtc: sc27xx: Clear SPG value update interrupt status We should clear the SPG value update interrupt status once the SPG value is updated successfully, in case incorrect status validation for next time. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 8afba125ad716..6ac56538682e8 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -172,7 +172,8 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) return ret; } - return 0; + return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR, + SPRD_RTC_SPG_UPD_EN); } static int sprd_rtc_get_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type, From b2ddc48582efa157635f7ef815c9d4a657e2cabd Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 18 Oct 2018 16:52:28 +0800 Subject: [PATCH 52/54] rtc: sc27xx: Remove interrupts disable and clear in probe() When registering one rtc device, it will check to see if there is an alarm already set in rtc hardware by issuing __rtc_read_alarm(). So we should not disable the RTC interrupts and clear the interrupts status in probe() function. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 6ac56538682e8..4ecabe6c94297 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -129,19 +129,6 @@ static int sprd_rtc_clear_alarm_ints(struct sprd_rtc *rtc) SPRD_RTC_ALM_INT_MASK); } -static int sprd_rtc_disable_ints(struct sprd_rtc *rtc) -{ - int ret; - - ret = regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN, - SPRD_RTC_INT_MASK, 0); - if (ret) - return ret; - - return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR, - SPRD_RTC_INT_MASK); -} - static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) { int ret; @@ -609,13 +596,6 @@ static int sprd_rtc_probe(struct platform_device *pdev) rtc->dev = &pdev->dev; platform_set_drvdata(pdev, rtc); - /* clear all RTC interrupts and disable all RTC interrupts */ - ret = sprd_rtc_disable_ints(rtc); - if (ret) { - dev_err(&pdev->dev, "failed to disable RTC interrupts\n"); - return ret; - } - /* check if RTC time values are valid */ ret = sprd_rtc_check_power_down(rtc); if (ret) { From bf2c532b67fc077051e17de4a1304a83e5ca5b15 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 18 Oct 2018 16:52:29 +0800 Subject: [PATCH 53/54] rtc: sc27xx: Add check to see if need to enable the alarm interrupt The RTC interrupt enable register is not put in always-power-on region supplied by VDDRTC, so we should check if we need enable the alarm interrupt when system booting. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 4ecabe6c94297..72bb002c88ec5 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -563,6 +563,32 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc) return 0; } +static int sprd_rtc_check_alarm_int(struct sprd_rtc *rtc) +{ + u32 val; + int ret; + + ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val); + if (ret) + return ret; + + /* + * The SPRD_RTC_INT_EN register is not put in always-power-on region + * supplied by VDDRTC, so we should check if we need enable the alarm + * interrupt when system booting. + * + * If we have set SPRD_RTC_POWEROFF_ALM_FLAG which is saved in + * always-power-on region, that means we have set one alarm last time, + * so we should enable the alarm interrupt to help RTC core to see if + * there is an alarm already set in RTC hardware. + */ + if (!(val & SPRD_RTC_POWEROFF_ALM_FLAG)) + return 0; + + return regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN, + SPRD_RTC_ALARM_EN, SPRD_RTC_ALARM_EN); +} + static int sprd_rtc_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -596,6 +622,13 @@ static int sprd_rtc_probe(struct platform_device *pdev) rtc->dev = &pdev->dev; platform_set_drvdata(pdev, rtc); + /* check if we need set the alarm interrupt */ + ret = sprd_rtc_check_alarm_int(rtc); + if (ret) { + dev_err(&pdev->dev, "failed to check RTC alarm interrupt\n"); + return ret; + } + /* check if RTC time values are valid */ ret = sprd_rtc_check_power_down(rtc); if (ret) { From 3822d1bb0df18aa28930f19bc46e0704aea1be0f Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 18 Oct 2018 16:52:30 +0800 Subject: [PATCH 54/54] rtc: sc27xx: Always read normal alarm when registering RTC device When registering one RTC device, it will check to see if there is an alarm already set in RTC hardware by reading RTC alarm, at this time we should always read the normal alarm put in always-on region by checking the rtc->registered flag. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 72bb002c88ec5..b4eb3b3c6c2cb 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -415,10 +415,14 @@ static int sprd_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) u32 val; /* - * If aie_timer is enabled, we should get the normal alarm time. + * Before RTC device is registered, it will check to see if there is an + * alarm already set in RTC hardware, and we always read the normal + * alarm at this time. + * + * Or if aie_timer is enabled, we should get the normal alarm time. * Otherwise we should get auxiliary alarm time. */ - if (rtc->rtc && rtc->rtc->aie_timer.enabled == 0) + if (rtc->rtc && rtc->rtc->registered && rtc->rtc->aie_timer.enabled == 0) return sprd_rtc_read_aux_alarm(dev, alrm); ret = sprd_rtc_get_secs(rtc, SPRD_RTC_ALARM, &secs);