diff options
42 files changed, 1191 insertions, 573 deletions
diff --git a/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt b/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt deleted file mode 100644 index 41c7ae18fd7b..000000000000 --- a/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt +++ /dev/null @@ -1,37 +0,0 @@ -JZ4740 and similar SoCs real-time clock driver - -Required properties: - -- compatible: One of: - - "ingenic,jz4740-rtc" - for use with the JZ4740 SoC - - "ingenic,jz4780-rtc" - for use with the JZ4780 SoC -- reg: Address range of rtc register set -- interrupts: IRQ number for the alarm interrupt -- clocks: phandle to the "rtc" clock -- clock-names: must be "rtc" - -Optional properties: -- system-power-controller: To use this component as the - system power controller -- reset-pin-assert-time-ms: Reset pin low-level assertion - time after wakeup (default 60ms; range 0-125ms if RTC clock - at 32 kHz) -- min-wakeup-pin-assert-time-ms: Minimum wakeup pin assertion - time (default 100ms; range 0-2s if RTC clock at 32 kHz) - -Example: - -rtc@10003000 { - compatible = "ingenic,jz4740-rtc"; - reg = <0x10003000 0x40>; - - interrupt-parent = <&intc>; - interrupts = <32>; - - clocks = <&rtc_clock>; - clock-names = "rtc"; - - system-power-controller; - reset-pin-assert-time-ms = <60>; - min-wakeup-pin-assert-time-ms = <100>; -}; diff --git a/Documentation/devicetree/bindings/rtc/ingenic,rtc.yaml b/Documentation/devicetree/bindings/rtc/ingenic,rtc.yaml new file mode 100644 index 000000000000..4206bf8a2469 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/ingenic,rtc.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/ingenic,rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ingenic SoCs Real-Time Clock DT bindings + +maintainers: + - Paul Cercueil <paul@crapouillou.net> + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + oneOf: + - enum: + - ingenic,jz4740-rtc + - ingenic,jz4760-rtc + - items: + - const: ingenic,jz4725b-rtc + - const: ingenic,jz4740-rtc + - items: + - enum: + - ingenic,jz4770-rtc + - ingenic,jz4780-rtc + - const: ingenic,jz4760-rtc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: rtc + + system-power-controller: + description: | + Indicates that the RTC is responsible for powering OFF + the system. + type: boolean + + ingenic,reset-pin-assert-time-ms: + minimum: 0 + maximum: 125 + default: 60 + description: | + Reset pin low-level assertion time after wakeup + (assuming RTC clock at 32 kHz) + + ingenic,min-wakeup-pin-assert-time-ms: + minimum: 0 + maximum: 2000 + default: 100 + description: | + Minimum wakeup pin assertion time + (assuming RTC clock at 32 kHz) + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +examples: + - | + #include <dt-bindings/clock/jz4740-cgu.h> + rtc_dev: rtc@10003000 { + compatible = "ingenic,jz4740-rtc"; + reg = <0x10003000 0x40>; + + interrupt-parent = <&intc>; + interrupts = <15>; + + clocks = <&cgu JZ4740_CLK_RTC>; + clock-names = "rtc"; + }; diff --git a/Documentation/devicetree/bindings/rtc/rtc-mt2712.txt b/Documentation/devicetree/bindings/rtc/rtc-mt2712.txt new file mode 100644 index 000000000000..c33d87e5e753 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-mt2712.txt @@ -0,0 +1,14 @@ +Device-Tree bindings for MediaTek SoC based RTC + +Required properties: +- compatible : Should be "mediatek,mt2712-rtc" : for MT2712 SoC +- reg : Specifies base physical address and size of the registers; +- interrupts : Should contain the interrupt for RTC alarm; + +Example: + +rtc: rtc@10011000 { + compatible = "mediatek,mt2712-rtc"; + reg = <0 0x10011000 0 0x1000>; + interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_LOW>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 6f0e1a53e4c1..9e7896a99355 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2015,7 +2015,9 @@ M: Sean Wang <sean.wang@mediatek.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) S: Maintained +F: Documentation/devicetree/bindings/rtc/rtc-mt2712.txt F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt +F: drivers/rtc/rtc-mt2712.c F: drivers/rtc/rtc-mt6397.c F: drivers/rtc/rtc-mt7622.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8e503881d9d6..f942a3302cdc 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -41,9 +41,6 @@ config RTC_HCTOSYS_DEVICE device should record time in UTC, since the kernel won't do timezone correction. - The driver for this RTC device must be loaded before late_initcall - functions run, so it must usually be statically linked. - This clock should be battery-backed, so that it reads the correct time when the system boots from a power-off state. Otherwise, your system will need an external clock source (like an NTP server). @@ -241,6 +238,7 @@ config RTC_DRV_AS3722 config RTC_DRV_DS1307 tristate "Dallas/Maxim DS1307/37/38/39/40/41, ST M41T00, EPSON RX-8025, ISL12057" select REGMAP_I2C + select WATCHDOG_CORE if WATCHDOG help If you say yes here you get support for various compatible RTC chips (often with battery backup) connected with I2C. This driver @@ -1335,7 +1333,7 @@ config RTC_DRV_IMXDI config RTC_DRV_FSL_FTM_ALARM tristate "Freescale FlexTimer alarm timer" - depends on ARCH_LAYERSCAPE || SOC_LS1021A + depends on ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST help For the FlexTimer in LS1012A, LS1021A, LS1028A, LS1043A, LS1046A, LS1088A, LS208xA, we can use FTM as the wakeup source. @@ -1762,6 +1760,7 @@ config RTC_DRV_MXC_V2 config RTC_DRV_SNVS tristate "Freescale SNVS RTC support" select REGMAP_MMIO + depends on ARCH_MXC || COMPILE_TEST depends on HAS_IOMEM depends on OF help @@ -1807,6 +1806,16 @@ config RTC_DRV_MOXART This driver can also be built as a module. If so, the module will be called rtc-moxart +config RTC_DRV_MT2712 + tristate "MediaTek MT2712 SoC based RTC" + depends on ARCH_MEDIATEK || COMPILE_TEST + help + This enables support for the real time clock built in the MediaTek + SoCs for MT2712. + + This drive can also be built as a module. If so, the module + will be called rtc-mt2712. + config RTC_DRV_MT6397 tristate "MediaTek PMIC based RTC" depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 24c7dfa1bd7d..3b66ee99063f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -6,7 +6,6 @@ ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG obj-$(CONFIG_RTC_LIB) += lib.o -obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o obj-$(CONFIG_RTC_SYSTOHC) += systohc.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o @@ -106,6 +105,7 @@ obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o +obj-$(CONFIG_RTC_DRV_MT2712) += rtc-mt2712.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 9458e6d6686a..7c88d190c51f 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -34,6 +34,50 @@ static void rtc_device_release(struct device *dev) #ifdef CONFIG_RTC_HCTOSYS_DEVICE /* Result of the last RTC to system clock attempt. */ int rtc_hctosys_ret = -ENODEV; + +/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary + * whether it stores the most close value or the value with partial + * seconds truncated. However, it is important that we use it to store + * the truncated value. This is because otherwise it is necessary, + * in an rtc sync function, to read both xtime.tv_sec and + * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read + * of >32bits is not possible. So storing the most close value would + * slow down the sync API. So here we have the truncated value and + * the best guess is to add 0.5s. + */ + +static void rtc_hctosys(struct rtc_device *rtc) +{ + int err; + struct rtc_time tm; + struct timespec64 tv64 = { + .tv_nsec = NSEC_PER_SEC >> 1, + }; + + err = rtc_read_time(rtc, &tm); + if (err) { + dev_err(rtc->dev.parent, + "hctosys: unable to read the hardware clock\n"); + goto err_read; + } + + tv64.tv_sec = rtc_tm_to_time64(&tm); + +#if BITS_PER_LONG == 32 + if (tv64.tv_sec > INT_MAX) { + err = -ERANGE; + goto err_read; + } +#endif + + err = do_settimeofday64(&tv64); + + dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n", + &tm, (long long)tv64.tv_sec); + +err_read: + rtc_hctosys_ret = err; +} #endif #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE) @@ -375,6 +419,11 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) dev_info(rtc->dev.parent, "registered as %s\n", dev_name(&rtc->dev)); +#ifdef CONFIG_RTC_HCTOSYS_DEVICE + if (!strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE)) + rtc_hctosys(rtc); +#endif + return 0; } EXPORT_SYMBOL_GPL(__rtc_register_device); diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c deleted file mode 100644 index a74d0d890600..000000000000 --- a/drivers/rtc/hctosys.c +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * RTC subsystem, initialize system time on startup - * - * Copyright (C) 2005 Tower Technologies - * Author: Alessandro Zummo <a.zummo@towertech.it> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/rtc.h> - -/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary - * whether it stores the most close value or the value with partial - * seconds truncated. However, it is important that we use it to store - * the truncated value. This is because otherwise it is necessary, - * in an rtc sync function, to read both xtime.tv_sec and - * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read - * of >32bits is not possible. So storing the most close value would - * slow down the sync API. So here we have the truncated value and - * the best guess is to add 0.5s. - */ - -static int __init rtc_hctosys(void) -{ - int err = -ENODEV; - struct rtc_time tm; - struct timespec64 tv64 = { - .tv_nsec = NSEC_PER_SEC >> 1, - }; - struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); - - if (!rtc) { - pr_info("unable to open rtc device (%s)\n", - CONFIG_RTC_HCTOSYS_DEVICE); - goto err_open; - } - - err = rtc_read_time(rtc, &tm); - if (err) { - dev_err(rtc->dev.parent, - "hctosys: unable to read the hardware clock\n"); - goto err_read; - } - - tv64.tv_sec = rtc_tm_to_time64(&tm); - -#if BITS_PER_LONG == 32 - if (tv64.tv_sec > INT_MAX) { - err = -ERANGE; - goto err_read; - } -#endif - - err = do_settimeofday64(&tv64); - - dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n", - &tm, (long long)tv64.tv_sec); - -err_read: - rtc_class_close(rtc); - -err_open: - rtc_hctosys_ret = err; - - return err; -} - -late_initcall(rtc_hctosys); diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 4743b16a8d84..cc9b14ef90f1 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -28,7 +28,6 @@ struct pm860x_rtc_info { int irq; int vrtc; - int (*sync)(unsigned int ticks); }; #define REG_VRTC_MEAS1 0x7D @@ -76,33 +75,6 @@ static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) return 0; } -/* - * Calculate the next alarm time given the requested alarm time mask - * and the current time. - */ -static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, - struct rtc_time *alrm) -{ - unsigned long next_time; - unsigned long now_time; - - next->tm_year = now->tm_year; - next->tm_mon = now->tm_mon; - next->tm_mday = now->tm_mday; - next->tm_hour = alrm->tm_hour; - next->tm_min = alrm->tm_min; - next->tm_sec = alrm->tm_sec; - - rtc_tm_to_time(now, &now_time); - rtc_tm_to_time(next, &next_time); - - if (next_time < now_time) { - /* Advance one day */ - next_time += 60 * 60 * 24; - rtc_time_to_tm(next_time, next); - } -} - static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct pm860x_rtc_info *info = dev_get_drvdata(dev); @@ -123,7 +95,7 @@ static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); - rtc_time_to_tm(ticks, tm); + rtc_time64_to_tm(ticks, tm); return 0; } @@ -140,7 +112,7 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) 1900 + tm->tm_year); return -EINVAL; } - rtc_tm_to_time(tm, &ticks); + ticks = rtc_tm_to_time64(tm); /* load 32-bit read-only counter */ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); @@ -155,8 +127,6 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF); pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF); - if (info->sync) - info->sync(ticks); return 0; } @@ -180,7 +150,7 @@ static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); - rtc_time_to_tm(ticks, &alrm->time); + rtc_time64_to_tm(ticks, &alrm->time); ret = pm860x_reg_read(info->i2c, PM8607_RTC1); alrm->enabled = (ret & ALARM_EN) ? 1 : 0; alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0; @@ -190,7 +160,6 @@ static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pm860x_rtc_info *info = dev_get_drvdata(dev); - struct rtc_time now_tm, alarm_tm; unsigned long ticks, base, data; unsigned char buf[8]; int mask; @@ -203,18 +172,7 @@ static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) base = ((unsigned long)buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; - /* load 32-bit read-only counter */ - pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | - (buf[1] << 8) | buf[0]; - ticks = base + data; - dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", - base, data, ticks); - - rtc_time_to_tm(ticks, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); - /* get new ticks for alarm in 24 hours */ - rtc_tm_to_time(&alarm_tm, &ticks); + ticks = rtc_tm_to_time64(&alrm->time); data = ticks - base; buf[0] = data & 0xff; @@ -309,20 +267,15 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev, return 0; } #else -#define pm860x_rtc_dt_init(x, y) (-1) +#define pm860x_rtc_dt_init(x, y) do { } while (0) #endif static int pm860x_rtc_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_rtc_pdata *pdata = NULL; struct pm860x_rtc_info *info; - struct rtc_time tm; - unsigned long ticks = 0; int ret; - pdata = dev_get_platdata(&pdev->dev); - info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_rtc_info), GFP_KERNEL); if (!info) @@ -336,6 +289,10 @@ static int pm860x_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, info); + info->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(info->rtc_dev)) + return PTR_ERR(info->rtc_dev); + ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, rtc_update_handler, IRQF_ONESHOT, "rtc", info); @@ -351,39 +308,14 @@ static int pm860x_rtc_probe(struct platform_device *pdev) pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA); pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA); - ret = pm860x_rtc_read_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read initial time.\n"); - return ret; - } - if ((tm.tm_year < 70) || (tm.tm_year > 138)) { - tm.tm_year = 70; - tm.tm_mon = 0; - tm.tm_mday = 1; - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - ret = pm860x_rtc_set_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to set initial time.\n"); - return ret; - } - } - rtc_tm_to_time(&tm, &ticks); - if (pm860x_rtc_dt_init(pdev, info)) { - if (pdata && pdata->sync) { - pdata->sync(ticks); - info->sync = pdata->sync; - } - } + pm860x_rtc_dt_init(pdev, info); + + info->rtc_dev->ops = &pm860x_rtc_ops; + info->rtc_dev->range_max = U32_MAX; - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm860x-rtc", - &pm860x_rtc_ops, THIS_MODULE); - ret = PTR_ERR(info->rtc_dev); - if (IS_ERR(info->rtc_dev)) { - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + ret = rtc_register_device(info->rtc_dev); + if (ret) return ret; - } /* * enable internal XO instead of internal 3.25MHz clock since it can @@ -393,12 +325,6 @@ static int pm860x_rtc_probe(struct platform_device *pdev) #ifdef VRTC_CALIBRATION /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */ - if (pm860x_rtc_dt_init(pdev, info)) { - if (pdata && pdata->vrtc) - info->vrtc = pdata->vrtc & 0x3; - else - info->vrtc = 1; - } pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC); /* calibrate VRTC */ diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 8492ffed4ca6..3d60f3283f11 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -100,7 +100,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) secs = secs / COUNTS_PER_SEC; secs = secs + (mins * 60); - rtc_time_to_tm(secs, tm); + rtc_time64_to_tm(secs, tm); return 0; } @@ -110,7 +110,7 @@ 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; - rtc_tm_to_time(tm, &secs); + secs = rtc_tm_to_time64(tm); no_mins = secs / 60; @@ -168,7 +168,7 @@ 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; - rtc_time_to_tm(secs, &alarm->time); + rtc_time64_to_tm(secs, &alarm->time); return 0; } @@ -188,7 +188,7 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) struct rtc_time curtm; /* Get the number of seconds since 1970 */ - rtc_tm_to_time(&alarm->time, &secs); + secs = rtc_tm_to_time64(&alarm->time); /* * Check whether alarm is set less than 1min. @@ -196,7 +196,7 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON */ ab8500_rtc_read_time(dev, &curtm); /* Read current time */ - rtc_tm_to_time(&curtm, &cursec); + cursec = rtc_tm_to_time64(&curtm); if ((secs - cursec) < 59) { dev_dbg(dev, "Alarm less than 1 minute not supported\r\n"); return -EINVAL; diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index 7c5530c71285..791bebcb6f47 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c @@ -34,7 +34,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm) t = alchemy_rdsys(AU1000_SYS_TOYREAD); - rtc_time_to_tm(t, tm); + rtc_time64_to_tm(t, tm); return 0; } @@ -43,7 +43,7 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm) { unsigned long t; - rtc_tm_to_time(tm, &t); + t = rtc_tm_to_time64(tm); alchemy_wrsys(t, AU1000_SYS_TOYWRITE); @@ -65,17 +65,13 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtcdev; unsigned long t; - int ret; t = alchemy_rdsys(AU1000_SYS_CNTRCTRL); if (!(t & CNTR_OK)) { dev_err(&pdev->dev, "counters not working; aborting.\n"); - ret = -ENODEV; - goto out_err; + return -ENODEV; } - ret = -ETIMEDOUT; - /* set counter0 tickrate to 1Hz if necessary */ if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) { /* wait until hardware gives access to TRIM register */ @@ -88,7 +84,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) * counters are unusable. */ dev_err(&pdev->dev, "timeout waiting for access\n"); - goto out_err; + return -ETIMEDOUT; } /* set 1Hz TOY tick rate */ @@ -99,19 +95,16 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S) msleep(1); - rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx", - &au1xtoy_rtc_ops, THIS_MODULE); - if (IS_ERR(rtcdev)) { - ret = PTR_ERR(rtcdev); - goto out_err; - } + rtcdev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtcdev)) + return PTR_ERR(rtcdev); - platform_set_drvdata(pdev, rtcdev); + rtcdev->ops = &au1xtoy_rtc_ops; + rtcdev->range_max = U32_MAX; - return 0; + platform_set_drvdata(pdev, rtcdev); -out_err: - return ret; + return rtc_register_device(rtcdev); } static struct platform_driver au1xrtc_driver = { diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index bbbb1f07c91f..4492b770422c 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -542,10 +542,8 @@ static int bd70528_probe(struct platform_device *pdev) irq = platform_get_irq_byname(pdev, irq_name); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get irq\n"); + if (irq < 0) return irq; - } platform_set_drvdata(pdev, bd_rtc); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 82bfe009a50f..bcc96ab7793f 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -649,10 +649,11 @@ static struct cmos_rtc cmos_rtc; static irqreturn_t cmos_interrupt(int irq, void *p) { + unsigned long flags; u8 irqstat; u8 rtc_control; - spin_lock(&rtc_lock); + spin_lock_irqsave(&rtc_lock, flags); /* When the HPET interrupt handler calls us, the interrupt * status is passed as arg1 instead of the irq number. But @@ -686,7 +687,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); } - spin_unlock(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); if (is_intr(irqstat)) { rtc_update_irq(p, 1, irqstat); diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c index 6a3b70fd7e1f..a603f1f21125 100644 --- a/drivers/rtc/rtc-cpcap.c +++ b/drivers/rtc/rtc-cpcap.c @@ -56,14 +56,14 @@ static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap) tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8); time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY); - rtc_time_to_tm(time, rtc); + rtc_time64_to_tm(time, rtc); } static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc) { unsigned long time; - rtc_tm_to_time(rtc, &time); + time = rtc_tm_to_time64(rtc); cpcap->day = time / SECS_PER_DAY; time %= SECS_PER_DAY; @@ -256,12 +256,13 @@ static int cpcap_rtc_probe(struct platform_device *pdev) return -ENODEV; platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc", - &cpcap_rtc_ops, THIS_MODULE); - + rtc->rtc_dev = devm_rtc_allocate_device(dev); if (IS_ERR(rtc->rtc_dev)) return PTR_ERR(rtc->rtc_dev); + rtc->rtc_dev->ops = &cpcap_rtc_ops; + rtc->rtc_dev->range_max = (1 << 14) * SECS_PER_DAY - 1; + err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor); if (err) return err; @@ -298,7 +299,7 @@ static int cpcap_rtc_probe(struct platform_device *pdev) /* ignore error and continue without wakeup support */ } - return 0; + return rtc_register_device(rtc->rtc_dev); } static const struct of_device_id cpcap_rtc_of_match[] = { diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 204eb7cf1aa4..58de10da37b1 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -103,13 +103,11 @@ static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) int ret; uint8_t v[3]; - ret = rtc_tm_to_time(rtc_tm, &alm_time); - if (ret != 0) - return ret; + alm_time = rtc_tm_to_time64(rtc_tm); if (rtc_tm->tm_sec > 0) { alm_time += 60 - rtc_tm->tm_sec; - rtc_time_to_tm(alm_time, rtc_tm); + rtc_time64_to_tm(alm_time, rtc_tm); } BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */ @@ -298,12 +296,18 @@ static int da9052_rtc_probe(struct platform_device *pdev) rtc_err(rtc, "Failed to disable TICKS: %d\n", ret); device_init_wakeup(&pdev->dev, true); - rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &da9052_rtc_ops, THIS_MODULE); - + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) return PTR_ERR(rtc->rtc); + rtc->rtc->ops = &da9052_rtc_ops; + rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->rtc->range_max = RTC_TIMESTAMP_END_2063; + + ret = rtc_register_device(rtc->rtc); + if (ret) + return ret; + ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", da9052_rtc_irq, rtc); if (ret != 0) { diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 390b7351e0fe..73f87a17cdf3 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -227,7 +227,7 @@ davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) return ret; } -static int convertfromdays(u16 days, struct rtc_time *tm) +static void convertfromdays(u16 days, struct rtc_time *tm) { int tmp_days, year, mon; @@ -250,24 +250,17 @@ static int convertfromdays(u16 days, struct rtc_time *tm) break; } } - return 0; } -static int convert2days(u16 *days, struct rtc_time *tm) +static void convert2days(u16 *days, struct rtc_time *tm) { int i; *days = 0; - /* epoch == 1900 */ - if (tm->tm_year < 100 || tm->tm_year > 199) - return -EINVAL; - for (i = 2000; i < 1900 + tm->tm_year; i++) *days += rtc_year_days(1, 12, i); *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); - - return 0; } static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) @@ -300,8 +293,7 @@ static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) days <<= 8; days |= day0; - if (convertfromdays(days, tm) < 0) - return -EINVAL; + convertfromdays(days, tm); return 0; } @@ -313,8 +305,7 @@ static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 rtc_cctrl; unsigned long flags; - if (convert2days(&days, tm) < 0) - return -EINVAL; + convert2days(&days, tm); spin_lock_irqsave(&davinci_rtc_lock, flags); @@ -396,8 +387,7 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) days <<= 8; days |= day0; - if (convertfromdays(days, &alm->time) < 0) - return -EINVAL; + convertfromdays(days, &alm->time); alm->pending = !!(rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & @@ -413,29 +403,7 @@ static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) unsigned long flags; u16 days; - if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0 - && alm->time.tm_year < 0) { - struct rtc_time tm; - unsigned long now, then; - - davinci_rtc_read_time(dev, &tm); - rtc_tm_to_time(&tm, &now); - - alm->time.tm_mday = tm.tm_mday; - alm->time.tm_mon = tm.tm_mon; - alm->time.tm_year = tm.tm_year; - rtc_tm_to_time(&alm->time, &then); - - if (then < now) { - rtc_time_to_tm(now + 24 * 60 * 60, &tm); - alm->time.tm_mday = tm.tm_mday; - alm->time.tm_mon = tm.tm_mon; - alm->time.tm_year = tm.tm_year; - } - } - - if (convert2days(&days, &alm->time) < 0) - return -EINVAL; + convert2days(&days, &alm->time); spin_lock_irqsave(&davinci_rtc_lock, flags); @@ -485,13 +453,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, davinci_rtc); - davinci_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &davinci_rtc_ops, THIS_MODULE); - if (IS_ERR(davinci_rtc->rtc)) { - dev_err(dev, "unable to register RTC device, err %d\n", - ret); + davinci_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(davinci_rtc->rtc)) return PTR_ERR(davinci_rtc->rtc); - } + + davinci_rtc->rtc->ops = &davinci_rtc_ops; + davinci_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + davinci_rtc->rtc->range_max = RTC_TIMESTAMP_BEGIN_2000 + (1 << 16) * 86400ULL - 1; rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); @@ -516,7 +484,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); - return 0; + return rtc_register_device(davinci_rtc->rtc); } static int __exit davinci_rtc_remove(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 4420fbf2f8fe..a3d790889eea 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -325,17 +325,13 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm) u8 buf[1 + DS1305_ALM_LEN]; /* convert desired alarm to time_t */ - status = rtc_tm_to_time(&alm->time, &later); - if (status < 0) - return status; + later = rtc_tm_to_time64(&alm->time); /* Read current time as time_t */ status = ds1305_get_time(dev, &tm); if (status < 0) return status; - status = rtc_tm_to_time(&tm, &now); - if (status < 0) - return status; + now = rtc_tm_to_time64(&tm); /* make sure alarm fires within the next 24 hours */ if (later <= now) @@ -694,6 +690,8 @@ static int ds1305_probe(struct spi_device *spi) return PTR_ERR(ds1305->rtc); ds1305->rtc->ops = &ds1305_ops; + ds1305->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + ds1305->rtc->range_max = RTC_TIMESTAMP_END_2099; ds1305_nvmem_cfg.priv = ds1305; ds1305->rtc->nvram_old_abi = true; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 1f7e8aefc1eb..49702942bb08 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -22,6 +22,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/clk-provider.h> #include <linux/regmap.h> +#include <linux/watchdog.h> /* * We can't determine type by probing, but if we expect pre-Linux code @@ -144,6 +145,15 @@ enum ds_type { # define M41TXX_BIT_CALIB_SIGN BIT(5) # define M41TXX_M_CALIBRATION GENMASK(4, 0) +#define DS1388_REG_WDOG_HUN_SECS 0x08 +#define DS1388_REG_WDOG_SECS 0x09 +#define DS1388_REG_FLAG 0x0b +# define DS1388_BIT_WF BIT(6) +# define DS1388_BIT_OSF BIT(7) +#define DS1388_REG_CONTROL 0x0c +# define DS1388_BIT_RST BIT(0) +# define DS1388_BIT_WDE BIT(1) + /* negative offset step is -2.034ppm */ #define M41TXX_NEG_OFFSET_STEP_PPB 2034 /* positive offset step is +4.068ppm */ @@ -252,6 +262,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) if (tmp & DS1340_BIT_OSF) return -EINVAL; break; + case ds_1388: + ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp); + if (ret) + return ret; + if (tmp & DS1388_BIT_OSF) + return -EINVAL; + break; case mcp794xx: if (!(tmp & MCP794XX_BIT_ST)) return -EINVAL; @@ -845,6 +862,72 @@ static int m41txx_rtc_set_offset(struct device *dev, long offset) ctrl_reg); } +#ifdef CONFIG_WATCHDOG_CORE +static int ds1388_wdt_start(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + int ret; + + ret = regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG, + DS1388_BIT_WF, 0); + if (ret) + return ret; + + ret = regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, 0); + if (ret) + return ret; + + /* + * watchdog timeouts are measured in seconds. So ignore hundredths of + * seconds field. + */ + regs[0] = 0; + regs[1] = bin2bcd(wdt_dev->timeout); + + ret = regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); + if (ret) + return ret; + + return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, + DS1388_BIT_WDE | DS1388_BIT_RST); +} + +static int ds1388_wdt_stop(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + + return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, 0); +} + +static int ds1388_wdt_ping(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + + return regmap_bulk_read(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); +} + +static int ds1388_wdt_set_timeout(struct watchdog_device *wdt_dev, + unsigned int val) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + + wdt_dev->timeout = val; + regs[0] = 0; + regs[1] = bin2bcd(wdt_dev->timeout); + + return regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); +} +#endif + static const struct rtc_class_ops rx8130_rtc_ops = { .read_time = ds1307_get_time, .set_time = ds1307_set_time, @@ -1567,6 +1650,48 @@ static void ds1307_clks_register(struct ds1307 *ds1307) #endif /* CONFIG_COMMON_CLK */ +#ifdef CONFIG_WATCHDOG_CORE +static const struct watchdog_info ds1388_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "DS1388 watchdog", +}; + +static const struct watchdog_ops ds1388_wdt_ops = { + .owner = THIS_MODULE, + .start = ds1388_wdt_start, + .stop = ds1388_wdt_stop, + .ping = ds1388_wdt_ping, + .set_timeout = ds1388_wdt_set_timeout, + +}; + +static void ds1307_wdt_register(struct ds1307 *ds1307) +{ + struct watchdog_device *wdt; + + if (ds1307->type != ds_1388) + return; + + wdt = devm_kzalloc(ds1307->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return; + + wdt->info = &ds1388_wdt_info; + wdt->ops = &ds1388_wdt_ops; + wdt->timeout = 99; + wdt->max_timeout = 99; + wdt->min_timeout = 1; + + watchdog_init_timeout(wdt, 0, ds1307->dev); + watchdog_set_drvdata(wdt, ds1307); + devm_watchdog_register_device(ds1307->dev, wdt); +} +#else +static void ds1307_wdt_register(struct ds1307 *ds1307) +{ +} +#endif /* CONFIG_WATCHDOG_CORE */ + static const struct regmap_config regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -1856,6 +1981,7 @@ static int ds1307_probe(struct i2c_client *client, ds1307_hwmon_register(ds1307); ds1307_clks_register(ds1307); + ds1307_wdt_register(ds1307); return 0; diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 6e9ddcd03992..9c51a12cf70f 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -164,7 +164,7 @@ static int ds1374_read_time(struct device *dev, struct rtc_time *time) ret = ds1374_read_rtc(client, &itime, DS1374_REG_TOD0, 4); if (!ret) - rtc_time_to_tm(itime, time); + rtc_time64_to_tm(itime, time); return ret; } @@ -172,9 +172,8 @@ static int ds1374_read_time(struct device *dev, struct rtc_time *time) static int ds1374_set_time(struct device *dev, struct rtc_time *time) { struct i2c_client *client = to_i2c_client(dev); - unsigned long itime; + unsigned long itime = rtc_tm_to_time64(time); - rtc_tm_to_time(time, &itime); return ds1374_write_rtc(client, itime, DS1374_REG_TOD0, 4); } @@ -212,7 +211,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) if (ret) goto out; - rtc_time_to_tm(now + cur_alarm, &alarm->time); + rtc_time64_to_tm(now + cur_alarm, &alarm->time); alarm->enabled = !!(cr & DS1374_REG_CR_WACE); alarm->pending = !!(sr & DS1374_REG_SR_AF); @@ -237,8 +236,8 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) if (ret < 0) return ret; - rtc_tm_to_time(&alarm->time, &new_alarm); - rtc_tm_to_time(&now, &itime); + new_alarm = rtc_tm_to_time64(&alarm->time); + itime = rtc_tm_to_time64(&now); /* This can happen due to races, in addition to dates that are * truly in the past. To avoid requiring the caller to check for @@ -620,6 +619,10 @@ static int ds1374_probe(struct i2c_client *client, if (!ds1374) return -ENOMEM; + ds1374->rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(ds1374->rtc)) + return PTR_ERR(ds1374->rtc); + ds1374->client = client; i2c_set_clientdata(client, ds1374); @@ -641,12 +644,12 @@ static int ds1374_probe(struct i2c_client *client, device_set_wakeup_capable(&client->dev, 1); } - ds1374->rtc = devm_rtc_device_register(&client->dev, client->name, - &ds1374_rtc_ops, THIS_MODULE); - if (IS_ERR(ds1374->rtc)) { - dev_err(&client->dev, "unable to register the class device\n"); - return PTR_ERR(ds1374->rtc); - } + ds1374->rtc->ops = &ds1374_rtc_ops; + ds1374->rtc->range_max = U32_MAX; + + ret = rtc_register_device(ds1374->rtc); + if (ret) + return ret; #ifdef CONFIG_RTC_DRV_DS1374_WDT save_client = client; diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index 9e6e994cce99..756af62b0486 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -20,6 +20,7 @@ #include <linux/fsl/ftm.h> #include <linux/rtc.h> #include <linux/time.h> +#include <linux/acpi.h> #define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT) @@ -151,6 +152,8 @@ static irqreturn_t ftm_rtc_alarm_interrupt(int irq, void *dev) { struct ftm_rtc *rtc = dev; + rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); + ftm_irq_acknowledge(rtc); ftm_irq_disable(rtc); ftm_clean_alarm(rtc); @@ -242,7 +245,6 @@ static const struct rtc_class_ops ftm_rtc_ops = { static int ftm_rtc_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; int irq; int ret; struct ftm_rtc *rtc; @@ -265,10 +267,10 @@ static int ftm_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->base); } - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "unable to get IRQ from DT, %d\n", irq); - return -EINVAL; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "can't get irq number\n"); + return irq; } ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt, @@ -278,7 +280,9 @@ static int ftm_rtc_probe(struct platform_device *pdev) return ret; } - rtc->big_endian = of_property_read_bool(np, "big-endian"); + rtc->big_endian = + device_property_read_bool(&pdev->dev, "big-endian"); + rtc->alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV; rtc->rtc_dev->ops = &ftm_rtc_ops; @@ -305,11 +309,18 @@ static const struct of_device_id ftm_rtc_match[] = { { }, }; +static const struct acpi_device_id ftm_imx_acpi_ids[] = { + {"NXP0011",}, + { } +}; +MODULE_DEVICE_TABLE(acpi, ftm_imx_acpi_ids); + static struct platform_driver ftm_rtc_driver = { .probe = ftm_rtc_probe, .driver = { .name = "ftm-alarm", .of_match_table = ftm_rtc_match, + .acpi_match_table = ACPI_PTR(ftm_imx_acpi_ids), }, }; diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index cf2c12107f2b..a5f59e6f862e 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -37,7 +37,7 @@ struct imx_sc_msg_timer_rtc_set_alarm { u8 hour; u8 min; u8 sec; -} __packed; +} __packed __aligned(4); static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm) { diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 18023e472cbc..e4c719085c31 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -46,6 +46,7 @@ enum jz4740_rtc_type { ID_JZ4740, + ID_JZ4760, ID_JZ4780, }; @@ -106,7 +107,7 @@ static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, { int ret = 0; - if (rtc->type >= ID_JZ4780) + if (rtc->type >= ID_JZ4760) ret = jz4780_rtc_enable_write(rtc); if (ret == 0) ret = jz4740_rtc_wait_write_ready(rtc); @@ -298,6 +299,7 @@ static void jz4740_rtc_power_off(void) static const struct of_device_id jz4740_rtc_of_match[] = { { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, + { .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 }, { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 }, {}, }; @@ -372,13 +374,14 @@ static int jz4740_rtc_probe(struct platform_device *pdev) if (!pm_power_off) { /* Default: 60ms */ rtc->reset_pin_assert_time = 60; - of_property_read_u32(np, "reset-pin-assert-time-ms", + of_property_read_u32(np, + "ingenic,reset-pin-assert-time-ms", &rtc->reset_pin_assert_time); /* Default: 100ms */ rtc->min_wakeup_pin_assert_time = 100; of_property_read_u32(np, - "min-wakeup-pin-assert-time-ms", + "ingenic,min-wakeup-pin-assert-time-ms", &rtc->min_wakeup_pin_assert_time); dev_for_power_off = &pdev->dev; diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index e8194f1f01a8..92f19bf997b2 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -160,15 +160,10 @@ static int m48t35_probe(struct platform_device *pdev) return -ENOMEM; priv->size = resource_size(res); - /* - * kludge: remove the #ifndef after ioc3 resource - * conflicts are resolved - */ -#ifndef CONFIG_SGI_IP27 if (!devm_request_mem_region(&pdev->dev, res->start, priv->size, pdev->name)) return -EBUSY; -#endif + priv->baseaddr = res->start; priv->reg = devm_ioremap(&pdev->dev, priv->baseaddr, priv->size); if (!priv->reg) diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 15a9d0278778..3040844129ce 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -111,7 +111,7 @@ static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm) */ now = in_be32(®s->actual_time) + in_be32(®s->target_time); - rtc_time_to_tm(now, tm); + rtc_time64_to_tm(now, tm); /* * update second minute hour registers @@ -126,16 +126,14 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); struct mpc5121_rtc_regs __iomem *regs = rtc->regs; - int ret; unsigned long now; /* * The actual_time register is read only so we write the offset * between it and linux time to the target_time register. */ - ret = rtc_tm_to_time(tm, &now); - if (ret == 0) - out_be32(®s->target_time, now - in_be32(®s->actual_time)); + now = rtc_tm_to_time64(tm); + out_be32(®s->target_time, now - in_be32(®s->actual_time)); /* * update second minute hour registers @@ -315,8 +313,8 @@ static int mpc5121_rtc_probe(struct platform_device *op) if (!rtc) return -ENOMEM; - rtc->regs = of_iomap(op->dev.of_node, 0); - if (!rtc->regs) { + rtc->regs = devm_platform_ioremap_resource(op, 0); + if (IS_ERR(rtc->regs)) { dev_err(&op->dev, "%s: couldn't map io space\n", __func__); return -ENOSYS; } @@ -326,8 +324,8 @@ static int mpc5121_rtc_probe(struct platform_device *op) platform_set_drvdata(op, rtc); rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1); - err = request_irq(rtc->irq, mpc5121_rtc_handler, 0, - "mpc5121-rtc", &op->dev); + err = devm_request_irq(&op->dev, rtc->irq, mpc5121_rtc_handler, 0, + "mpc5121-rtc", &op->dev); if (err) { dev_err(&op->dev, "%s: could not request irq: %i\n", __func__, rtc->irq); @@ -335,14 +333,26 @@ static int mpc5121_rtc_probe(struct platform_device *op) } rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0); - err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, - 0, "mpc5121-rtc_upd", &op->dev); + err = devm_request_irq(&op->dev, rtc->irq_periodic, + mpc5121_rtc_handler_upd, 0, "mpc5121-rtc_upd", + &op->dev); if (err) { dev_err(&op->dev, "%s: could not request irq: %i\n", __func__, rtc->irq_periodic); goto out_dispose2; } + rtc->rtc = devm_rtc_allocate_device(&op->dev); + if (IS_ERR(rtc->rtc)) { + err = PTR_ERR(rtc->rtc); + goto out_dispose2; + } + + rtc->rtc->ops = &mpc5200_rtc_ops; + rtc->rtc->uie_unsupported = 1; + rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000; + rtc->rtc->range_max = 65733206399ULL; /* 4052-12-31 23:59:59 */ + if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { u32 ka; ka = in_be32(&rtc->regs->keep_alive); @@ -351,30 +361,26 @@ static int mpc5121_rtc_probe(struct platform_device *op) "mpc5121-rtc: Battery or oscillator failure!\n"); out_be32(&rtc->regs->keep_alive, ka); } - - rtc->rtc = devm_rtc_device_register(&op->dev, "mpc5121-rtc", - &mpc5121_rtc_ops, THIS_MODULE); - } else { - rtc->rtc = devm_rtc_device_register(&op->dev, "mpc5200-rtc", - &mpc5200_rtc_ops, THIS_MODULE); + rtc->rtc->ops = &mpc5121_rtc_ops; + /* + * This is a limitation of the driver that abuses the target + * time register, the actual maximum year for the mpc5121 is + * also 4052. + */ + rtc->rtc->range_min = 0; + rtc->rtc->range_max = U32_MAX; } - if (IS_ERR(rtc->rtc)) { - err = PTR_ERR(rtc->rtc); - goto out_free_irq; - } - rtc->rtc->uie_unsupported = 1; + err = rtc_register_device(rtc->rtc); + if (err) + goto out_dispose2; return 0; -out_free_irq: - free_irq(rtc->irq_periodic, &op->dev); out_dispose2: irq_dispose_mapping(rtc->irq_periodic); - free_irq(rtc->irq, &op->dev); out_dispose: irq_dispose_mapping(rtc->irq); - iounmap(rtc->regs); return err; } @@ -388,9 +394,6 @@ static int mpc5121_rtc_remove(struct platform_device *op) out_8(®s->alm_enable, 0); out_8(®s->int_enable, in_8(®s->int_enable) & ~0x1); - iounmap(rtc->regs); - free_irq(rtc->irq, &op->dev); - free_irq(rtc->irq_periodic, &op->dev); irq_dispose_mapping(rtc->irq); irq_dispose_mapping(rtc->irq_periodic); diff --git a/drivers/rtc/rtc-mt2712.c b/drivers/rtc/rtc-mt2712.c new file mode 100644 index 000000000000..581b8731fb8a --- /dev/null +++ b/drivers/rtc/rtc-mt2712.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ran Bi <ran.bi@mediatek.com> + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + +#define MT2712_BBPU 0x0000 +#define MT2712_BBPU_CLRPKY BIT(4) +#define MT2712_BBPU_RELOAD BIT(5) +#define MT2712_BBPU_CBUSY BIT(6) +#define MT2712_BBPU_KEY (0x43 << 8) + +#define MT2712_IRQ_STA 0x0004 +#define MT2712_IRQ_STA_AL BIT(0) +#define MT2712_IRQ_STA_TC BIT(1) + +#define MT2712_IRQ_EN 0x0008 +#define MT2712_IRQ_EN_AL BIT(0) +#define MT2712_IRQ_EN_TC BIT(1) +#define MT2712_IRQ_EN_ONESHOT BIT(2) + +#define MT2712_CII_EN 0x000c + +#define MT2712_AL_MASK 0x0010 +#define MT2712_AL_MASK_DOW BIT(4) + +#define MT2712_TC_SEC 0x0014 +#define MT2712_TC_MIN 0x0018 +#define MT2712_TC_HOU 0x001c +#define MT2712_TC_DOM 0x0020 +#define MT2712_TC_DOW 0x0024 +#define MT2712_TC_MTH 0x0028 +#define MT2712_TC_YEA 0x002c + +#define MT2712_AL_SEC 0x0030 +#define MT2712_AL_MIN 0x0034 +#define MT2712_AL_HOU 0x0038 +#define MT2712_AL_DOM 0x003c +#define MT2712_AL_DOW 0x0040 +#define MT2712_AL_MTH 0x0044 +#define MT2712_AL_YEA 0x0048 + +#define MT2712_SEC_MASK 0x003f +#define MT2712_MIN_MASK 0x003f +#define MT2712_HOU_MASK 0x001f +#define MT2712_DOM_MASK 0x001f +#define MT2712_DOW_MASK 0x0007 +#define MT2712_MTH_MASK 0x000f +#define MT2712_YEA_MASK 0x007f + +#define MT2712_POWERKEY1 0x004c +#define MT2712_POWERKEY2 0x0050 +#define MT2712_POWERKEY1_KEY 0xa357 +#define MT2712_POWERKEY2_KEY 0x67d2 + +#define MT2712_CON0 0x005c +#define MT2712_CON1 0x0060 + +#define MT2712_PROT 0x0070 +#define MT2712_PROT_UNLOCK1 0x9136 +#define MT2712_PROT_UNLOCK2 0x586a + +#define MT2712_WRTGR 0x0078 + +#define MT2712_RTC_TIMESTAMP_END_2127 4985971199LL + +struct mt2712_rtc { + struct rtc_device *rtc; + void __iomem *base; + int irq; + u8 irq_wake_enabled; + u8 powerlost; +}; + +static inline u32 mt2712_readl(struct mt2712_rtc *mt2712_rtc, u32 reg) +{ + return readl(mt2712_rtc->base + reg); +} + +static inline void mt2712_writel(struct mt2712_rtc *mt2712_rtc, + u32 reg, u32 val) +{ + writel(val, mt2712_rtc->base + reg); +} + +static void mt2712_rtc_write_trigger(struct mt2712_rtc *mt2712_rtc) +{ + unsigned long timeout = jiffies + HZ / 10; + + mt2712_writel(mt2712_rtc, MT2712_WRTGR, 1); + while (1) { + if (!(mt2712_readl(mt2712_rtc, MT2712_BBPU) + & MT2712_BBPU_CBUSY)) + break; + + if (time_after(jiffies, timeout)) { + dev_err(&mt2712_rtc->rtc->dev, + "%s time out!\n", __func__); + break; + } + cpu_relax(); + } +} + +static void mt2712_rtc_writeif_unlock(struct mt2712_rtc *mt2712_rtc) +{ + mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK1); + mt2712_rtc_write_trigger(mt2712_rtc); + mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK2); + mt2712_rtc_write_trigger(mt2712_rtc); +} + +static irqreturn_t rtc_irq_handler_thread(int irq, void *data) +{ + struct mt2712_rtc *mt2712_rtc = data; + u16 irqsta; + + /* Clear interrupt */ + irqsta = mt2712_readl(mt2712_rtc, MT2712_IRQ_STA); + if (irqsta & MT2712_IRQ_STA_AL) { + rtc_update_irq(mt2712_rtc->rtc, 1, RTC_IRQF | RTC_AF); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void __mt2712_rtc_read_time(struct mt2712_rtc *mt2712_rtc, + struct rtc_time *tm, int *sec) +{ + tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) + & MT2712_SEC_MASK; + tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_TC_MIN) + & MT2712_MIN_MASK; + tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_TC_HOU) + & MT2712_HOU_MASK; + tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_TC_DOM) + & MT2712_DOM_MASK; + tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_TC_MTH) - 1) + & MT2712_MTH_MASK; + tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_TC_YEA) + 100) + & MT2712_YEA_MASK; + + *sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) & MT2712_SEC_MASK; +} + +static int mt2712_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + int sec; + + if (mt2712_rtc->powerlost) + return -EINVAL; + + do { + __mt2712_rtc_read_time(mt2712_rtc, tm, &sec); + } while (sec < tm->tm_sec); /* SEC has carried */ + + return 0; +} + +static int mt2712_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + + mt2712_writel(mt2712_rtc, MT2712_TC_SEC, tm->tm_sec & MT2712_SEC_MASK); + mt2712_writel(mt2712_rtc, MT2712_TC_MIN, tm->tm_min & MT2712_MIN_MASK); + mt2712_writel(mt2712_rtc, MT2712_TC_HOU, tm->tm_hour & MT2712_HOU_MASK); + mt2712_writel(mt2712_rtc, MT2712_TC_DOM, tm->tm_mday & MT2712_DOM_MASK); + mt2712_writel(mt2712_rtc, MT2712_TC_MTH, + (tm->tm_mon + 1) & MT2712_MTH_MASK); + mt2712_writel(mt2712_rtc, MT2712_TC_YEA, + (tm->tm_year - 100) & MT2712_YEA_MASK); + + mt2712_rtc_write_trigger(mt2712_rtc); + + if (mt2712_rtc->powerlost) + mt2712_rtc->powerlost = false; + + return 0; +} + +static int mt2712_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + struct rtc_time *tm = &alm->time; + u16 irqen; + + irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN); + alm->enabled = !!(irqen & MT2712_IRQ_EN_AL); + + tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_AL_SEC) & MT2712_SEC_MASK; + tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_AL_MIN) & MT2712_MIN_MASK; + tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_AL_HOU) & MT2712_HOU_MASK; + tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_AL_DOM) & MT2712_DOM_MASK; + tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) - 1) + & MT2712_MTH_MASK; + tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) + 100) + & MT2712_YEA_MASK; + + return 0; +} + +static int mt2712_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + u16 irqen; + + irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN); + if (enabled) + irqen |= MT2712_IRQ_EN_AL; + else + irqen &= ~MT2712_IRQ_EN_AL; + mt2712_writel(mt2712_rtc, MT2712_IRQ_EN, irqen); + mt2712_rtc_write_trigger(mt2712_rtc); + + return 0; +} + +static int mt2712_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + struct rtc_time *tm = &alm->time; + + dev_dbg(&mt2712_rtc->rtc->dev, "set al time: %ptR, alm en: %d\n", + tm, alm->enabled); + + mt2712_writel(mt2712_rtc, MT2712_AL_SEC, + (mt2712_readl(mt2712_rtc, MT2712_AL_SEC) + & ~(MT2712_SEC_MASK)) | (tm->tm_sec & MT2712_SEC_MASK)); + mt2712_writel(mt2712_rtc, MT2712_AL_MIN, + (mt2712_readl(mt2712_rtc, MT2712_AL_MIN) + & ~(MT2712_MIN_MASK)) | (tm->tm_min & MT2712_MIN_MASK)); + mt2712_writel(mt2712_rtc, MT2712_AL_HOU, + (mt2712_readl(mt2712_rtc, MT2712_AL_HOU) + & ~(MT2712_HOU_MASK)) | (tm->tm_hour & MT2712_HOU_MASK)); + mt2712_writel(mt2712_rtc, MT2712_AL_DOM, + (mt2712_readl(mt2712_rtc, MT2712_AL_DOM) + & ~(MT2712_DOM_MASK)) | (tm->tm_mday & MT2712_DOM_MASK)); + mt2712_writel(mt2712_rtc, MT2712_AL_MTH, + (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) + & ~(MT2712_MTH_MASK)) + | ((tm->tm_mon + 1) & MT2712_MTH_MASK)); + mt2712_writel(mt2712_rtc, MT2712_AL_YEA, + (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) + & ~(MT2712_YEA_MASK)) + | ((tm->tm_year - 100) & MT2712_YEA_MASK)); + + /* mask day of week */ + mt2712_writel(mt2712_rtc, MT2712_AL_MASK, MT2712_AL_MASK_DOW); + mt2712_rtc_write_trigger(mt2712_rtc); + + mt2712_rtc_alarm_irq_enable(dev, alm->enabled); + + return 0; +} + +/* Init RTC register */ +static void mt2712_rtc_hw_init(struct mt2712_rtc *mt2712_rtc) +{ + u32 p1, p2; + + mt2712_writel(mt2712_rtc, MT2712_BBPU, + MT2712_BBPU_KEY | MT2712_BBPU_RELOAD); + + mt2712_writel(mt2712_rtc, MT2712_CII_EN, 0); + mt2712_writel(mt2712_rtc, MT2712_AL_MASK, 0); + /* necessary before set MT2712_POWERKEY */ + mt2712_writel(mt2712_rtc, MT2712_CON0, 0x4848); + mt2712_writel(mt2712_rtc, MT2712_CON1, 0x0048); + + mt2712_rtc_write_trigger(mt2712_rtc); + + p1 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY1); + p2 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY2); + if (p1 != MT2712_POWERKEY1_KEY || p2 != MT2712_POWERKEY2_KEY) { + mt2712_rtc->powerlost = true; + dev_dbg(&mt2712_rtc->rtc->dev, + "powerkey not set (lost power)\n"); + } else { + mt2712_rtc->powerlost = false; + } + + /* RTC need POWERKEY1/2 match, then goto normal work mode */ + mt2712_writel(mt2712_rtc, MT2712_POWERKEY1, MT2712_POWERKEY1_KEY); + mt2712_writel(mt2712_rtc, MT2712_POWERKEY2, MT2712_POWERKEY2_KEY); + mt2712_rtc_write_trigger(mt2712_rtc); + + mt2712_rtc_writeif_unlock(mt2712_rtc); +} + +static const struct rtc_class_ops mt2712_rtc_ops = { + .read_time = mt2712_rtc_read_time, + .set_time = mt2712_rtc_set_time, + .read_alarm = mt2712_rtc_read_alarm, + .set_alarm = mt2712_rtc_set_alarm, + .alarm_irq_enable = mt2712_rtc_alarm_irq_enable, +}; + +static int mt2712_rtc_probe(struct platform_device *pdev) +{ + struct resource *res; + struct mt2712_rtc *mt2712_rtc; + int ret; + + mt2712_rtc = devm_kzalloc(&pdev->dev, + sizeof(struct mt2712_rtc), GFP_KERNEL); + if (!mt2712_rtc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mt2712_rtc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mt2712_rtc->base)) + return PTR_ERR(mt2712_rtc->base); + + /* rtc hw init */ + mt2712_rtc_hw_init(mt2712_rtc); + + mt2712_rtc->irq = platform_get_irq(pdev, 0); + if (mt2712_rtc->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return mt2712_rtc->irq; + } + + platform_set_drvdata(pdev, mt2712_rtc); + + mt2712_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(mt2712_rtc->rtc)) + return PTR_ERR(mt2712_rtc->rtc); + + ret = devm_request_threaded_irq(&pdev->dev, mt2712_rtc->irq, NULL, + rtc_irq_handler_thread, + IRQF_ONESHOT | IRQF_TRIGGER_LOW, + dev_name(&mt2712_rtc->rtc->dev), + mt2712_rtc); + if (ret) { + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", + mt2712_rtc->irq, ret); + return ret; + } + + device_init_wakeup(&pdev->dev, true); + + mt2712_rtc->rtc->ops = &mt2712_rtc_ops; + mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127; + + ret = rtc_register_device(mt2712_rtc->rtc); + if (ret) { + dev_err(&pdev->dev, "register rtc device failed\n"); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mt2712_rtc_suspend(struct device *dev) +{ + int wake_status = 0; + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) { + wake_status = enable_irq_wake(mt2712_rtc->irq); + if (!wake_status) + mt2712_rtc->irq_wake_enabled = true; + } + + return 0; +} + +static int mt2712_rtc_resume(struct device *dev) +{ + int wake_status = 0; + struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev) && mt2712_rtc->irq_wake_enabled) { + wake_status = disable_irq_wake(mt2712_rtc->irq); + if (!wake_status) + mt2712_rtc->irq_wake_enabled = false; + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(mt2712_pm_ops, mt2712_rtc_suspend, + mt2712_rtc_resume); +#endif + +static const struct of_device_id mt2712_rtc_of_match[] = { + { .compatible = "mediatek,mt2712-rtc", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, mt2712_rtc_of_match); + +static struct platform_driver mt2712_rtc_driver = { + .driver = { + .name = "mt2712-rtc", + .of_match_table = mt2712_rtc_of_match, +#ifdef CONFIG_PM_SLEEP + .pm = &mt2712_pm_ops, +#endif + }, + .probe = mt2712_rtc_probe, +}; + +module_platform_driver(mt2712_rtc_driver); + +MODULE_DESCRIPTION("MediaTek MT2712 SoC based RTC Driver"); +MODULE_AUTHOR("Ran Bi <ran.bi@mediatek.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 902d57dcd0d4..a8cfbde048f4 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -307,6 +307,14 @@ static const struct rtc_class_ops mxc_rtc_ops = { .alarm_irq_enable = mxc_rtc_alarm_irq_enable, }; +static void mxc_rtc_action(void *p) +{ + struct rtc_plat_data *pdata = p; + + clk_disable_unprepare(pdata->clk_ref); + clk_disable_unprepare(pdata->clk_ipg); +} + static int mxc_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; @@ -366,14 +374,20 @@ static int mxc_rtc_probe(struct platform_device *pdev) pdata->clk_ref = devm_clk_get(&pdev->dev, "ref"); if (IS_ERR(pdata->clk_ref)) { + clk_disable_unprepare(pdata->clk_ipg); dev_err(&pdev->dev, "unable to get ref clock!\n"); - ret = PTR_ERR(pdata->clk_ref); - goto exit_put_clk_ipg; + return PTR_ERR(pdata->clk_ref); } ret = clk_prepare_enable(pdata->clk_ref); + if (ret) { + clk_disable_unprepare(pdata->clk_ipg); + return ret; + } + + ret = devm_add_action_or_reset(&pdev->dev, mxc_rtc_action, pdata); if (ret) - goto exit_put_clk_ipg; + return ret; rate = clk_get_rate(pdata->clk_ref); @@ -385,16 +399,14 @@ static int mxc_rtc_probe(struct platform_device *pdev) reg = RTC_INPUT_CLK_38400HZ; else { dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); - ret = -EINVAL; - goto exit_put_clk_ref; + return -EINVAL; } reg |= RTC_ENABLE_BIT; writew(reg, (pdata->ioaddr + RTC_RTCCTL)); if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { dev_err(&pdev->dev, "hardware module can't be enabled!\n"); - ret = -EIO; - goto exit_put_clk_ref; + return -EIO; } platform_set_drvdata(pdev, pdata); @@ -417,29 +429,10 @@ static int mxc_rtc_probe(struct platform_device *pdev) } ret = rtc_register_device(rtc); - if (ret) - goto exit_put_clk_ref; - - return 0; - -exit_put_clk_ref: - clk_disable_unprepare(pdata->clk_ref); -exit_put_clk_ipg: - clk_disable_unprepare(pdata->clk_ipg); return ret; } -static int mxc_rtc_remove(struct platform_device *pdev) -{ - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - - clk_disable_unprepare(pdata->clk_ref); - clk_disable_unprepare(pdata->clk_ipg); - - return 0; -} - static struct platform_driver mxc_rtc_driver = { .driver = { .name = "mxc_rtc", @@ -447,7 +440,6 @@ static struct platform_driver mxc_rtc_driver = { }, .id_table = imx_rtc_devtype, .probe = mxc_rtc_probe, - .remove = mxc_rtc_remove, }; module_platform_driver(mxc_rtc_driver) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index d4ed20fb3194..c20fc7937dfa 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -9,7 +9,6 @@ * Copyright (C) 2014 Johan Hovold <johan@kernel.org> */ -#include <dt-bindings/gpio/gpio.h> #include <linux/bcd.h> #include <linux/clk.h> #include <linux/delay.h> diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 1db17ba1fc64..7a87f461bec8 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -9,6 +9,7 @@ * Copyright (C) 2019 Micro Crystal AG * Author: Alexandre Belloni <alexandre.belloni@bootlin.com> */ +#include <linux/clk-provider.h> #include <linux/i2c.h> #include <linux/bcd.h> #include <linux/rtc.h> @@ -44,6 +45,10 @@ #define PCF85063_OFFSET_STEP0 4340 #define PCF85063_OFFSET_STEP1 4069 +#define PCF85063_REG_CLKO_F_MASK 0x07 /* frequency mask */ +#define PCF85063_REG_CLKO_F_32768HZ 0x00 +#define PCF85063_REG_CLKO_F_OFF 0x07 + #define PCF85063_REG_RAM 0x03 #define PCF85063_REG_SC 0x04 /* datetime */ @@ -61,6 +66,9 @@ struct pcf85063_config { struct pcf85063 { struct rtc_device *rtc; struct regmap *regmap; +#ifdef CONFIG_COMMON_CLK + struct clk_hw clkout_hw; +#endif }; static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) @@ -357,6 +365,150 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063, PCF85063_REG_CTRL1_CAP_SEL, reg); } +#ifdef CONFIG_COMMON_CLK +/* + * Handling of the clkout + */ + +#define clkout_hw_to_pcf85063(_hw) container_of(_hw, struct pcf85063, clkout_hw) + +static int clkout_rates[] = { + 32768, + 16384, + 8192, + 4096, + 2048, + 1024, + 1, + 0 +}; + +static unsigned long pcf85063_clkout_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw); + unsigned int buf; + int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf); + + if (ret < 0) + return 0; + + buf &= PCF85063_REG_CLKO_F_MASK; + return clkout_rates[buf]; +} + +static long pcf85063_clkout_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) + if (clkout_rates[i] <= rate) + return clkout_rates[i]; + + return 0; +} + +static int pcf85063_clkout_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw); + int i; + + for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) + if (clkout_rates[i] == rate) + return regmap_update_bits(pcf85063->regmap, + PCF85063_REG_CTRL2, + PCF85063_REG_CLKO_F_MASK, i); + + return -EINVAL; +} + +static int pcf85063_clkout_control(struct clk_hw *hw, bool enable) +{ + struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw); + unsigned int buf; + int ret; + + ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &buf); + if (ret < 0) + return ret; + buf &= PCF85063_REG_CLKO_F_MASK; + + if (enable) { + if (buf == PCF85063_REG_CLKO_F_OFF) + buf = PCF85063_REG_CLKO_F_32768HZ; + else + return 0; + } else { + if (buf != PCF85063_REG_CLKO_F_OFF) + buf = PCF85063_REG_CLKO_F_OFF; + else + return 0; + } + + return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, + PCF85063_REG_CLKO_F_MASK, buf); +} + +static int pcf85063_clkout_prepare(struct clk_hw *hw) +{ + return pcf85063_clkout_control(hw, 1); +} + +static void pcf85063_clkout_unprepare(struct clk_hw *hw) +{ + pcf85063_clkout_control(hw, 0); +} + +static int pcf85063_clkout_is_prepared(struct clk_hw *hw) +{ + struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw); + unsigned int buf; + int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf); + + if (ret < 0) + return 0; + + return (buf & PCF85063_REG_CLKO_F_MASK) != PCF85063_REG_CLKO_F_OFF; +} + +static const struct clk_ops pcf85063_clkout_ops = { + .prepare = pcf85063_clkout_prepare, + .unprepare = pcf85063_clkout_unprepare, + .is_prepared = pcf85063_clkout_is_prepared, + .recalc_rate = pcf85063_clkout_recalc_rate, + .round_rate = pcf85063_clkout_round_rate, + .set_rate = pcf85063_clkout_set_rate, +}; + +static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) +{ + struct clk *clk; + struct clk_init_data init; + + init.name = "pcf85063-clkout"; + init.ops = &pcf85063_clkout_ops; + init.flags = 0; + init.parent_names = NULL; + init.num_parents = 0; + pcf85063->clkout_hw.init = &init; + + /* optional override of the clockname */ + of_property_read_string(pcf85063->rtc->dev.of_node, + "clock-output-names", &init.name); + + /* register the clock */ + clk = devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw); + + if (!IS_ERR(clk)) + of_clk_add_provider(pcf85063->rtc->dev.of_node, + of_clk_src_simple_get, clk); + + return clk; +} +#endif + static const struct pcf85063_config pcf85063a_config = { .regmap = { .reg_bits = 8, @@ -457,6 +609,11 @@ static int pcf85063_probe(struct i2c_client *client) nvmem_cfg.priv = pcf85063->regmap; rtc_nvmem_register(pcf85063->rtc, &nvmem_cfg); +#ifdef CONFIG_COMMON_CLK + /* register clk in common clk framework */ + pcf85063_clkout_register_clk(pcf85063); +#endif + return rtc_register_device(pcf85063->rtc); } diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index d4a5f8afafbc..ebe03eba8f5f 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -36,32 +36,24 @@ static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); - rtc_time_to_tm(readl(rtc->base + RTC_MR), &alrm->time); + rtc_time64_to_tm(readl(rtc->base + RTC_MR), &alrm->time); return 0; } static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); - unsigned long time; - int ret; - /* - * At the moment, we can only deal with non-wildcarded alarm times. - */ - ret = rtc_valid_tm(&alrm->time); - if (ret == 0) - ret = rtc_tm_to_time(&alrm->time, &time); - if (ret == 0) - writel(time, rtc->base + RTC_MR); - return ret; + writel(rtc_tm_to_time64(&alrm->time), rtc->base + RTC_MR); + + return 0; } static int pl030_read_time(struct device *dev, struct rtc_time *tm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); - rtc_time_to_tm(readl(rtc->base + RTC_DR), tm); + rtc_time64_to_tm(readl(rtc->base + RTC_DR), tm); return 0; } @@ -77,14 +69,10 @@ static int pl030_read_time(struct device *dev, struct rtc_time *tm) static int pl030_set_time(struct device *dev, struct rtc_time *tm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); - unsigned long time; - int ret; - ret = rtc_tm_to_time(tm, &time); - if (ret == 0) - writel(time + 1, rtc->base + RTC_LR); + writel(rtc_tm_to_time64(tm) + 1, rtc->base + RTC_LR); - return ret; + return 0; } static const struct rtc_class_ops pl030_ops = { @@ -116,6 +104,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) } rtc->rtc->ops = &pl030_ops; + rtc->rtc->range_max = U32_MAX; rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!rtc->base) { ret = -ENOMEM; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 180caebbd355..40d7450a1ce4 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -80,6 +80,8 @@ struct pl031_vendor_data { bool clockwatch; bool st_weekday; unsigned long irqflags; + time64_t range_min; + timeu64_t range_max; }; struct pl031_local { @@ -123,11 +125,9 @@ static int pl031_stv2_tm_to_time(struct device *dev, return -EINVAL; } else if (wday == -1) { /* wday is not provided, calculate it here */ - unsigned long time; struct rtc_time calc_tm; - rtc_tm_to_time(tm, &time); - rtc_time_to_tm(time, &calc_tm); + rtc_time64_to_tm(rtc_tm_to_time64(tm), &calc_tm); wday = calc_tm.tm_wday; } @@ -210,17 +210,13 @@ static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) unsigned long bcd_year; int ret; - /* At the moment, we can only deal with non-wildcarded alarm times. */ - ret = rtc_valid_tm(&alarm->time); + ret = pl031_stv2_tm_to_time(dev, &alarm->time, + &time, &bcd_year); if (ret == 0) { - ret = pl031_stv2_tm_to_time(dev, &alarm->time, - &time, &bcd_year); - if (ret == 0) { - writel(bcd_year, ldata->base + RTC_YMR); - writel(time, ldata->base + RTC_MR); + writel(bcd_year, ldata->base + RTC_YMR); + writel(time, ldata->base + RTC_MR); - pl031_alarm_irq_enable(dev, alarm->enabled); - } + pl031_alarm_irq_enable(dev, alarm->enabled); } return ret; @@ -248,30 +244,25 @@ static int pl031_read_time(struct device *dev, struct rtc_time *tm) { struct pl031_local *ldata = dev_get_drvdata(dev); - rtc_time_to_tm(readl(ldata->base + RTC_DR), tm); + rtc_time64_to_tm(readl(ldata->base + RTC_DR), tm); return 0; } static int pl031_set_time(struct device *dev, struct rtc_time *tm) { - unsigned long time; struct pl031_local *ldata = dev_get_drvdata(dev); - int ret; - ret = rtc_tm_to_time(tm, &time); + writel(rtc_tm_to_time64(tm), ldata->base + RTC_LR); - if (ret == 0) - writel(time, ldata->base + RTC_LR); - - return ret; + return 0; } static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct pl031_local *ldata = dev_get_drvdata(dev); - rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); + rtc_time64_to_tm(readl(ldata->base + RTC_MR), &alarm->time); alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; @@ -282,20 +273,10 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct pl031_local *ldata = dev_get_drvdata(dev); - unsigned long time; - int ret; - /* At the moment, we can only deal with non-wildcarded alarm times. */ - ret = rtc_valid_tm(&alarm->time); - if (ret == 0) { - ret = rtc_tm_to_time(&alarm->time, &time); - if (ret == 0) { - writel(time, ldata->base + RTC_MR); - pl031_alarm_irq_enable(dev, alarm->enabled); - } - } + writel(rtc_tm_to_time64(&alarm->time), ldata->base + RTC_MR); - return ret; + return 0; } static int pl031_remove(struct amba_device *adev) @@ -383,6 +364,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(ldata->rtc); ldata->rtc->ops = ops; + ldata->rtc->range_min = vendor->range_min; + ldata->rtc->range_max = vendor->range_max; ret = rtc_register_device(ldata->rtc); if (ret) @@ -413,6 +396,7 @@ static struct pl031_vendor_data arm_pl031 = { .set_alarm = pl031_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .range_max = U32_MAX, }; /* The First ST derivative */ @@ -426,6 +410,7 @@ static struct pl031_vendor_data stv1_pl031 = { }, .clockwatch = true, .st_weekday = true, + .range_max = U32_MAX, }; /* And the second ST derivative */ @@ -446,6 +431,8 @@ static struct pl031_vendor_data stv2_pl031 = { * remove IRQF_COND_SUSPEND */ .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND, + .range_min = RTC_TIMESTAMP_BEGIN_0000, + .range_max = RTC_TIMESTAMP_END_9999, }; static const struct amba_id pl031_ids[] = { diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 07ea1be3abb9..b45ee2cb2c04 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -84,7 +84,7 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) if (!rtc_dd->allow_set_time) return -EACCES; - rtc_tm_to_time(tm, &secs); + secs = rtc_tm_to_time64(tm); dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); @@ -208,7 +208,7 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) secs = value[0] | (value[1] << 8) | (value[2] << 16) | ((unsigned long)value[3] << 24); - rtc_time_to_tm(secs, tm); + rtc_time64_to_tm(secs, tm); dev_dbg(dev, "secs = %lu, h:m:s == %ptRt, y-m-d = %ptRdr\n", secs, tm, tm); @@ -224,7 +224,7 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; - rtc_tm_to_time(&alarm->time, &secs); + secs = rtc_tm_to_time64(&alarm->time); for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { value[i] = secs & 0xFF; @@ -280,13 +280,7 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) secs = value[0] | (value[1] << 8) | (value[2] << 16) | ((unsigned long)value[3] << 24); - rtc_time_to_tm(secs, &alarm->time); - - rc = rtc_valid_tm(&alarm->time); - if (rc < 0) { - dev_err(dev, "Invalid alarm time read from RTC\n"); - return rc; - } + rtc_time64_to_tm(secs, &alarm->time); dev_dbg(dev, "Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr\n", &alarm->time, &alarm->time); @@ -301,6 +295,7 @@ static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; unsigned int ctrl_reg; + u8 value[NUM_8_BIT_RTC_REGS] = {0}; spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); @@ -319,6 +314,16 @@ static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) goto rtc_rw_fail; } + /* Clear Alarm register */ + if (!enable) { + rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value, + sizeof(value)); + if (rc) { + dev_err(dev, "Clear RTC ALARM register failed\n"); + goto rtc_rw_fail; + } + } + rtc_rw_fail: spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); return rc; @@ -486,13 +491,12 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); /* Register the RTC device */ - rtc_dd->rtc = devm_rtc_device_register(&pdev->dev, "pm8xxx_rtc", - &pm8xxx_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc_dd->rtc)) { - dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", - __func__, PTR_ERR(rtc_dd->rtc)); + rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc_dd->rtc)) return PTR_ERR(rtc_dd->rtc); - } + + rtc_dd->rtc->ops = &pm8xxx_rtc_ops; + rtc_dd->rtc->range_max = U32_MAX; /* Request the alarm IRQ */ rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->rtc_alarm_irq, @@ -504,9 +508,7 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) return rc; } - dev_dbg(&pdev->dev, "Probe success !!\n"); - - return 0; + return rtc_register_device(rtc_dd->rtc); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 89ff713163dd..954b88d2485f 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -85,7 +85,7 @@ static int puv3_rtc_setpie(struct device *dev, int enabled) /* Time read/write */ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { - rtc_time_to_tm(readl(RTC_RCNR), rtc_tm); + rtc_time64_to_tm(readl(RTC_RCNR), rtc_tm); dev_dbg(dev, "read time %ptRr\n", rtc_tm); @@ -94,12 +94,9 @@ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm) { - unsigned long rtc_count = 0; - dev_dbg(dev, "set time %ptRr\n", tm); - rtc_tm_to_time(tm, &rtc_count); - writel(rtc_count, RTC_RCNR); + writel(rtc_tm_to_time64(tm), RTC_RCNR); return 0; } @@ -108,7 +105,7 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *alm_tm = &alrm->time; - rtc_time_to_tm(readl(RTC_RTAR), alm_tm); + rtc_time64_to_tm(readl(RTC_RTAR), alm_tm); alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE; @@ -120,12 +117,10 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; - unsigned long rtcalarm_count = 0; dev_dbg(dev, "set alarm: %d, %ptRr\n", alrm->enabled, tm); - rtc_tm_to_time(tm, &rtcalarm_count); - writel(rtcalarm_count, RTC_RTAR); + writel(rtc_tm_to_time64(tm), RTC_RTAR); puv3_rtc_setaie(dev, alrm->enabled); @@ -234,6 +229,7 @@ static int puv3_rtc_probe(struct platform_device *pdev) /* register RTC and exit */ rtc->ops = &puv3_rtcops; + rtc->range_max = U32_MAX; ret = rtc_register_device(rtc); if (ret) goto err_nortc; diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index d37893f6eaee..9ccc97cf5e09 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -111,20 +111,17 @@ static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct sa1100_rtc *info = dev_get_drvdata(dev); - rtc_time_to_tm(readl_relaxed(info->rcnr), tm); + rtc_time64_to_tm(readl_relaxed(info->rcnr), tm); return 0; } static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct sa1100_rtc *info = dev_get_drvdata(dev); - unsigned long time; - int ret; - ret = rtc_tm_to_time(tm, &time); - if (ret == 0) - writel_relaxed(time, info->rcnr); - return ret; + writel_relaxed(rtc_tm_to_time64(tm), info->rcnr); + + return 0; } static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) @@ -141,24 +138,18 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct sa1100_rtc *info = dev_get_drvdata(dev); - unsigned long time; - int ret; spin_lock_irq(&info->lock); - ret = rtc_tm_to_time(&alrm->time, &time); - if (ret != 0) - goto out; writel_relaxed(readl_relaxed(info->rtsr) & (RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr); - writel_relaxed(time, info->rtar); + writel_relaxed(rtc_tm_to_time64(&alrm->time), info->rtar); if (alrm->enabled) writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr); else writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr); -out: spin_unlock_irq(&info->lock); - return ret; + return 0; } static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) @@ -182,7 +173,6 @@ static const struct rtc_class_ops sa1100_rtc_ops = { int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info) { - struct rtc_device *rtc; int ret; spin_lock_init(&info->lock); @@ -211,15 +201,15 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info) writel_relaxed(0, info->rcnr); } - rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops, - THIS_MODULE); - if (IS_ERR(rtc)) { + info->rtc->ops = &sa1100_rtc_ops; + info->rtc->max_user_freq = RTC_FREQ; + info->rtc->range_max = U32_MAX; + + ret = rtc_register_device(info->rtc); + if (ret) { clk_disable_unprepare(info->clk); - return PTR_ERR(rtc); + return ret; } - info->rtc = rtc; - - rtc->max_user_freq = RTC_FREQ; /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt(). @@ -267,6 +257,10 @@ static int sa1100_rtc_probe(struct platform_device *pdev) info->irq_1hz = irq_1hz; info->irq_alarm = irq_alarm; + info->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(info->rtc)) + return PTR_ERR(info->rtc); + ret = devm_request_irq(&pdev->dev, irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", &pdev->dev); if (ret) { diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index feb1f8e52c00..9167b48014a1 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -504,8 +504,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) if (unlikely(!rtc->res)) return -EBUSY; - rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, - rtc->regsize); + rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, rtc->regsize); if (unlikely(!rtc->regbase)) return -EINVAL; diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c index a2c9c55667cd..abf19435dbad 100644 --- a/drivers/rtc/rtc-sirfsoc.c +++ b/drivers/rtc/rtc-sirfsoc.c @@ -90,13 +90,13 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, */ /* if alarm is in next overflow cycle */ if (rtc_count > rtc_alarm) - rtc_time_to_tm((rtcdrv->overflow_rtc + 1) - << (BITS_PER_LONG - RTC_SHIFT) - | rtc_alarm >> RTC_SHIFT, &(alrm->time)); + rtc_time64_to_tm((rtcdrv->overflow_rtc + 1) + << (BITS_PER_LONG - RTC_SHIFT) + | rtc_alarm >> RTC_SHIFT, &alrm->time); else - rtc_time_to_tm(rtcdrv->overflow_rtc - << (BITS_PER_LONG - RTC_SHIFT) - | rtc_alarm >> RTC_SHIFT, &(alrm->time)); + rtc_time64_to_tm(rtcdrv->overflow_rtc + << (BITS_PER_LONG - RTC_SHIFT) + | rtc_alarm >> RTC_SHIFT, &alrm->time); if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E) alrm->enabled = 1; @@ -113,7 +113,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, rtcdrv = dev_get_drvdata(dev); if (alrm->enabled) { - rtc_tm_to_time(&(alrm->time), &rtc_alarm); + rtc_alarm = rtc_tm_to_time64(&alrm->time); spin_lock_irq(&rtcdrv->lock); @@ -181,8 +181,8 @@ static int sirfsoc_rtc_read_time(struct device *dev, cpu_relax(); } while (tmp_rtc != sirfsoc_rtc_readl(rtcdrv, RTC_CN)); - rtc_time_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) | - tmp_rtc >> RTC_SHIFT, tm); + rtc_time64_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) + | tmp_rtc >> RTC_SHIFT, tm); return 0; } @@ -193,7 +193,7 @@ static int sirfsoc_rtc_set_time(struct device *dev, struct sirfsoc_rtc_drv *rtcdrv; rtcdrv = dev_get_drvdata(dev); - rtc_tm_to_time(tm, &rtc_time); + rtc_time = rtc_tm_to_time64(tm); rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT); @@ -341,28 +341,22 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) rtcdrv->overflow_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE); - rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &sirfsoc_rtc_ops, THIS_MODULE); - if (IS_ERR(rtcdrv->rtc)) { - err = PTR_ERR(rtcdrv->rtc); - dev_err(&pdev->dev, "can't register RTC device\n"); - return err; - } + rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtcdrv->rtc)) + return PTR_ERR(rtcdrv->rtc); + + rtcdrv->rtc->ops = &sirfsoc_rtc_ops; + rtcdrv->rtc->range_max = (1ULL << 60) - 1; rtcdrv->irq = platform_get_irq(pdev, 0); - err = devm_request_irq( - &pdev->dev, - rtcdrv->irq, - sirfsoc_rtc_irq_handler, - IRQF_SHARED, - pdev->name, - rtcdrv); + err = devm_request_irq(&pdev->dev, rtcdrv->irq, sirfsoc_rtc_irq_handler, + IRQF_SHARED, pdev->name, rtcdrv); if (err) { dev_err(&pdev->dev, "Unable to register for the SiRF SOC RTC IRQ\n"); return err; } - return 0; + return rtc_register_device(rtcdrv->rtc); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 757f4daa7181..35ee08aa7584 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -7,7 +7,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_wakeirq.h> #include <linux/rtc.h> @@ -264,6 +263,12 @@ static const struct regmap_config snvs_rtc_config = { .reg_stride = 4, }; +static void snvs_rtc_action(void *data) +{ + if (data) + clk_disable_unprepare(data); +} + static int snvs_rtc_probe(struct platform_device *pdev) { struct snvs_rtc_data *data; @@ -314,6 +319,10 @@ static int snvs_rtc_probe(struct platform_device *pdev) } } + ret = devm_add_action_or_reset(&pdev->dev, snvs_rtc_action, data->clk); + if (ret) + return ret; + platform_set_drvdata(pdev, data); /* Initialize glitch detect */ @@ -326,7 +335,7 @@ static int snvs_rtc_probe(struct platform_device *pdev) ret = snvs_rtc_enable(data, true); if (ret) { dev_err(&pdev->dev, "failed to enable rtc %d\n", ret); - goto error_rtc_device_register; + return ret; } device_init_wakeup(&pdev->dev, true); @@ -339,24 +348,13 @@ static int snvs_rtc_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to request irq %d: %d\n", data->irq, ret); - goto error_rtc_device_register; + return ret; } data->rtc->ops = &snvs_rtc_ops; data->rtc->range_max = U32_MAX; - ret = rtc_register_device(data->rtc); - if (ret) { - dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); - goto error_rtc_device_register; - } - - return 0; -error_rtc_device_register: - if (data->clk) - clk_disable_unprepare(data->clk); - - return ret; + return rtc_register_device(data->rtc); } static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev) diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c index a7d49329d626..37a26279e107 100644 --- a/drivers/rtc/rtc-starfire.c +++ b/drivers/rtc/rtc-starfire.c @@ -27,7 +27,7 @@ static u32 starfire_get_time(void) static int starfire_read_time(struct device *dev, struct rtc_time *tm) { - rtc_time_to_tm(starfire_get_time(), tm); + rtc_time64_to_tm(starfire_get_time(), tm); return 0; } @@ -39,14 +39,16 @@ static int __init starfire_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; - rtc = devm_rtc_device_register(&pdev->dev, "starfire", - &starfire_rtc_ops, THIS_MODULE); + rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + rtc->ops = &starfire_rtc_ops; + rtc->range_max = U32_MAX; + platform_set_drvdata(pdev, rtc); - return 0; + return rtc_register_device(rtc); } static struct platform_driver starfire_rtc_driver = { diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 852f5f3b3592..e2b8b150bcb4 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -108,7 +108,6 @@ * driver, even though it is somewhat limited. */ #define SUN6I_YEAR_MIN 1970 -#define SUN6I_YEAR_MAX 2033 #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) /* @@ -250,19 +249,17 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, writel(reg, rtc->base + SUN6I_LOSC_CTRL); } - /* Switch to the external, more precise, oscillator */ - reg |= SUN6I_LOSC_CTRL_EXT_OSC; - if (rtc->data->has_losc_en) - reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; + /* Switch to the external, more precise, oscillator, if present */ + if (of_get_property(node, "clocks", NULL)) { + reg |= SUN6I_LOSC_CTRL_EXT_OSC; + if (rtc->data->has_losc_en) + reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; + } writel(reg, rtc->base + SUN6I_LOSC_CTRL); /* Yes, I know, this is ugly. */ sun6i_rtc = rtc; - /* Deal with old DTs */ - if (!of_get_property(node, "clocks", NULL)) - goto err; - /* Only read IOSC name from device tree if it is exported */ if (rtc->data->export_iosc) of_property_read_string_index(node, "clock-output-names", 2, @@ -279,11 +276,13 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, } parents[0] = clk_hw_get_name(rtc->int_osc); + /* If there is no external oscillator, this will be NULL and ... */ parents[1] = of_clk_get_parent_name(node, 0); rtc->hw.init = &init; init.parent_names = parents; + /* ... number of clock parents will be 1. */ init.num_parents = of_clk_get_parent_count(node) + 1; of_property_read_string_index(node, "clock-output-names", 0, &init.name); @@ -499,7 +498,7 @@ static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); - rtc_time_to_tm(chip->alarm, &wkalrm->time); + rtc_time64_to_tm(chip->alarm, &wkalrm->time); return 0; } @@ -520,8 +519,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) return -EINVAL; } - rtc_tm_to_time(alrm_tm, &time_set); - rtc_tm_to_time(&tm_now, &time_now); + time_set = rtc_tm_to_time64(alrm_tm); + time_now = rtc_tm_to_time64(&tm_now); if (time_set <= time_now) { dev_err(dev, "Date to set in the past\n"); return -EINVAL; @@ -569,14 +568,6 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); u32 date = 0; u32 time = 0; - int year; - - year = rtc_tm->tm_year + 1900; - if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) { - dev_err(dev, "rtc only supports year in range %d - %d\n", - SUN6I_YEAR_MIN, SUN6I_YEAR_MAX); - return -EINVAL; - } rtc_tm->tm_year -= SUN6I_YEAR_OFF; rtc_tm->tm_mon += 1; @@ -585,7 +576,7 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); - if (is_leap_year(year)) + if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) date |= SUN6I_LEAP_SET_VALUE(1); time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | @@ -726,12 +717,16 @@ static int sun6i_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i", - &sun6i_rtc_ops, THIS_MODULE); - if (IS_ERR(chip->rtc)) { - dev_err(&pdev->dev, "unable to register device\n"); + chip->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(chip->rtc)) return PTR_ERR(chip->rtc); - } + + chip->rtc->ops = &sun6i_rtc_ops; + chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */ + + ret = rtc_register_device(chip->rtc); + if (ret) + return ret; dev_info(&pdev->dev, "RTC enabled\n"); diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 5786866c09e9..4b1077e2f826 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -38,6 +38,8 @@ #define RTC_CALIB_DEF 0x198233 #define RTC_CALIB_MASK 0x1FFFFF +#define RTC_ALRM_MASK BIT(1) +#define RTC_MSEC 1000 struct xlnx_rtc_dev { struct rtc_device *rtc; @@ -123,11 +125,28 @@ static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled) { struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + unsigned int status; + ulong timeout; + + timeout = jiffies + msecs_to_jiffies(RTC_MSEC); + + if (enabled) { + while (1) { + status = readl(xrtcdev->reg_base + RTC_INT_STS); + if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK)) + break; + + if (time_after_eq(jiffies, timeout)) { + dev_err(dev, "Time out occur, while clearing alarm status bit\n"); + return -ETIMEDOUT; + } + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); + } - if (enabled) writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN); - else + } else { writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); + } return 0; } @@ -183,8 +202,8 @@ static irqreturn_t xlnx_rtc_interrupt(int irq, void *id) if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) return IRQ_NONE; - /* Clear RTC_INT_ALRM interrupt only */ - writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); + /* Disable RTC_INT_ALRM interrupt only */ + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); if (status & RTC_INT_ALRM) rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF); diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c index b7ca7d79fb28..950fac0d41ff 100644 --- a/drivers/rtc/sysfs.c +++ b/drivers/rtc/sysfs.c @@ -279,7 +279,7 @@ static bool rtc_does_wakealarm(struct rtc_device *rtc) static umode_t rtc_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct rtc_device *rtc = to_rtc_device(dev); umode_t mode = attr->mode; diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 23990bd29040..bba3db3f7efa 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -34,18 +34,6 @@ static inline time64_t rtc_tm_sub(struct rtc_time *lhs, struct rtc_time *rhs) return rtc_tm_to_time64(lhs) - rtc_tm_to_time64(rhs); } -static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) -{ - rtc_time64_to_tm(time, tm); -} - -static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) -{ - *time = rtc_tm_to_time64(tm); - - return 0; -} - #include <linux/device.h> #include <linux/seq_file.h> #include <linux/cdev.h> diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h index 095af360326a..83bba58d47f4 100644 --- a/include/uapi/linux/rtc.h +++ b/include/uapi/linux/rtc.h @@ -12,6 +12,9 @@ #ifndef _UAPI_LINUX_RTC_H_ #define _UAPI_LINUX_RTC_H_ +#include <linux/const.h> +#include <linux/ioctl.h> + /* * The struct used to pass data via the following ioctl. Similar to the * struct tm in <time.h>, but it needs to be here so that the kernel @@ -92,10 +95,10 @@ struct rtc_pll_info { #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ -#define RTC_VL_DATA_INVALID BIT(0) /* Voltage too low, RTC data is invalid */ -#define RTC_VL_BACKUP_LOW BIT(1) /* Backup voltage is low */ -#define RTC_VL_BACKUP_EMPTY BIT(2) /* Backup empty or not present */ -#define RTC_VL_ACCURACY_LOW BIT(3) /* Voltage is low, RTC accuracy is reduced */ +#define RTC_VL_DATA_INVALID _BITUL(0) /* Voltage too low, RTC data is invalid */ +#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */ +#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */ +#define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */ #define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */ #define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */ |