From 311ee9c151ad7f273eb698504c4a27ebddc6c6db Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 26 Mar 2018 21:58:01 +0800 Subject: rtc: cmos: allow using ACPI for RTC alarm instead of HPET It's found that the HPET timer prevents the platform from entering Low Power S0 on some new Intel platforms. This means that 1. users can still use RTC wake Alarm for suspend-to-idle, but the system never enters Low Power S0, which is a waste of power. or 2. if users want to put the system into Low Power S0, they can not use RTC as the wakeup source. To fix this, we need to stop using the HPET timer for wake alarm. But disabling CONFIG_HPET_EMULATE_RTC is not an option because HPET emulates PIT at the same time, and this is needed on some of these platforms. Thus, introduce a new mode (use_acpi_alarm) to the rtc_cmos driver, so that, even with CONFIG_HPET_EMULATE_RTC enabled, it's still possible to use ACPI SCI for RTC Alarm, including UIE/AIE/wkalrm, instead of HPET. Only necessary changes are made for the new "use_acpi_alarm" mode, including 1. drop all the calls to HPET emulation code, including the HPET irq handler for rtc interrupt. 2. enabling/disabling ACPI RTC Fixed event upon RTC UIE/AIE request. 3. acknowledge the RTC Alarm in ACPI RTC Fixed event handler. There is no functional change made in this patch if the new mode is not enabled. Note: this "use_acpi_alarm" mode is made based on the assumption that ACPI RTC Fixed event is reliable both at runtime and during system wakeup. And this has been verified on a couple of platforms I have, including a MS Surface Pro 4 (SKL), a Lenovo Yoga 900 (SKL), and a HP 9360 (KBL). Signed-off-by: Zhang Rui Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 111 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 1b3738a11702..d8ce93921d31 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -48,6 +48,17 @@ /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ #include +/* + * Use ACPI SCI to replace HPET interrupt for RTC Alarm event + * + * If cleared, ACPI SCI is only used to wake up the system from suspend + * + * If set, ACPI SCI is used to handle UIE/AIE and system wakeup + */ + +static bool use_acpi_alarm; +module_param(use_acpi_alarm, bool, 0444); + struct cmos_rtc { struct rtc_device *rtc; struct device *dev; @@ -153,6 +164,12 @@ 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) +{ + return is_hpet_enabled() && !use_acpi_alarm; +} + /*----------------------------------------------------------------*/ #ifdef RTC_PORT @@ -298,7 +315,7 @@ static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control) */ rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (is_hpet_enabled()) + if (use_hpet_alarm()) return; rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; @@ -318,7 +335,13 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) rtc_control |= mask; CMOS_WRITE(rtc_control, RTC_CONTROL); - hpet_set_rtc_irq_bit(mask); + if (use_hpet_alarm()) + hpet_set_rtc_irq_bit(mask); + + if ((mask & RTC_AIE) && use_acpi_alarm) { + if (cmos->wake_on) + cmos->wake_on(cmos->dev); + } cmos_checkintr(cmos, rtc_control); } @@ -330,7 +353,13 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) rtc_control = CMOS_READ(RTC_CONTROL); rtc_control &= ~mask; CMOS_WRITE(rtc_control, RTC_CONTROL); - hpet_mask_rtc_irq_bit(mask); + if (use_hpet_alarm()) + hpet_mask_rtc_irq_bit(mask); + + if ((mask & RTC_AIE) && use_acpi_alarm) { + if (cmos->wake_off) + cmos->wake_off(cmos->dev); + } cmos_checkintr(cmos, rtc_control); } @@ -448,10 +477,14 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) CMOS_WRITE(mon, cmos->mon_alrm); } - /* FIXME the HPET alarm glue currently ignores day_alrm - * and mon_alrm ... - */ - hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); + if (use_hpet_alarm()) { + /* + * FIXME the HPET alarm glue currently ignores day_alrm + * and mon_alrm ... + */ + hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, + t->time.tm_sec); + } if (t->enabled) cmos_irq_enable(cmos, RTC_AIE); @@ -508,7 +541,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) "batt_status\t: %s\n", (rtc_control & RTC_PIE) ? "yes" : "no", (rtc_control & RTC_UIE) ? "yes" : "no", - is_hpet_enabled() ? "yes" : "no", + use_hpet_alarm() ? "yes" : "no", // (rtc_control & RTC_SQWE) ? "yes" : "no", (rtc_control & RTC_DM_BINARY) ? "no" : "yes", (rtc_control & RTC_DST_EN) ? "yes" : "no", @@ -614,7 +647,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) */ irqstat = CMOS_READ(RTC_INTR_FLAGS); rtc_control = CMOS_READ(RTC_CONTROL); - if (is_hpet_enabled()) + if (use_hpet_alarm()) irqstat = (unsigned long)irq & 0xF0; /* If we were suspended, RTC_CONTROL may not be accurate since the @@ -633,7 +666,8 @@ static irqreturn_t cmos_interrupt(int irq, void *p) cmos_rtc.suspend_ctrl &= ~RTC_AIE; rtc_control &= ~RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); - hpet_mask_rtc_irq_bit(RTC_AIE); + if (use_hpet_alarm()) + hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); } spin_unlock(&rtc_lock); @@ -762,7 +796,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) * need to do something about other clock frequencies. */ cmos_rtc.rtc->irq_freq = 1024; - hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); + if (use_hpet_alarm()) + hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); } @@ -780,12 +815,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) goto cleanup1; } - hpet_rtc_timer_init(); + if (use_hpet_alarm()) + hpet_rtc_timer_init(); if (is_valid_irq(rtc_irq)) { irq_handler_t rtc_cmos_int_handler; - if (is_hpet_enabled()) { + if (use_hpet_alarm()) { rtc_cmos_int_handler = hpet_rtc_interrupt; retval = hpet_register_irq_handler(cmos_interrupt); if (retval) { @@ -824,7 +860,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) "alarms up to one day", cmos_rtc.century ? ", y3k" : "", nvmem_cfg.size, - is_hpet_enabled() ? ", hpet irqs" : ""); + use_hpet_alarm() ? ", hpet irqs" : ""); return 0; @@ -858,7 +894,8 @@ static void cmos_do_remove(struct device *dev) if (is_valid_irq(cmos->irq)) { free_irq(cmos->irq, cmos->rtc); - hpet_unregister_irq_handler(cmos_interrupt); + if (use_hpet_alarm()) + hpet_unregister_irq_handler(cmos_interrupt); } cmos->rtc = NULL; @@ -935,13 +972,13 @@ static int cmos_suspend(struct device *dev) mask = RTC_IRQMASK; tmp &= ~mask; CMOS_WRITE(tmp, RTC_CONTROL); - hpet_mask_rtc_irq_bit(mask); - + if (use_hpet_alarm()) + hpet_mask_rtc_irq_bit(mask); cmos_checkintr(cmos, tmp); } spin_unlock_irq(&rtc_lock); - if (tmp & RTC_AIE) { + if ((tmp & RTC_AIE) && !use_acpi_alarm) { cmos->enabled_wake = 1; if (cmos->wake_on) cmos->wake_on(dev); @@ -996,7 +1033,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) { + if (cmos->enabled_wake && !use_acpi_alarm) { if (cmos->wake_off) cmos->wake_off(dev); else @@ -1014,16 +1051,17 @@ static int __maybe_unused cmos_resume(struct device *dev) if (tmp & RTC_IRQMASK) { unsigned char mask; - if (device_may_wakeup(dev)) + if (device_may_wakeup(dev) && use_hpet_alarm()) hpet_rtc_timer_init(); do { CMOS_WRITE(tmp, RTC_CONTROL); - hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK); + if (use_hpet_alarm()) + hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK); mask = CMOS_READ(RTC_INTR_FLAGS); mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; - if (!is_hpet_enabled() || !is_intr(mask)) + if (!use_hpet_alarm() || !is_intr(mask)) break; /* force one-shot behavior if HPET blocked @@ -1068,16 +1106,27 @@ static u32 rtc_handler(void *context) unsigned char rtc_intr; unsigned long flags; - spin_lock_irqsave(&rtc_lock, flags); - if (cmos_rtc.suspend_ctrl) - rtc_control = CMOS_READ(RTC_CONTROL); - if (rtc_control & RTC_AIE) { - cmos_rtc.suspend_ctrl &= ~RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - rtc_update_irq(cmos->rtc, 1, rtc_intr); + + /* + * Always update rtc irq when ACPI is used as RTC Alarm. + * Or else, ACPI SCI is enabled during suspend/resume only, + * update rtc irq in that case. + */ + if (use_acpi_alarm) + cmos_interrupt(0, (void *)cmos->rtc); + else { + /* Fix me: can we use cmos_interrupt() here as well? */ + spin_lock_irqsave(&rtc_lock, flags); + if (cmos_rtc.suspend_ctrl) + rtc_control = CMOS_READ(RTC_CONTROL); + if (rtc_control & RTC_AIE) { + cmos_rtc.suspend_ctrl &= ~RTC_AIE; + CMOS_WRITE(rtc_control, RTC_CONTROL); + rtc_intr = CMOS_READ(RTC_INTR_FLAGS); + rtc_update_irq(cmos->rtc, 1, rtc_intr); + } + spin_unlock_irqrestore(&rtc_lock, flags); } - spin_unlock_irqrestore(&rtc_lock, flags); pm_wakeup_hard_event(dev); acpi_clear_event(ACPI_EVENT_RTC); -- cgit v1.2.3 From c6d3a278cc1201a93677737db565c25c58b2cfe0 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 26 Mar 2018 21:58:02 +0800 Subject: rtc: cmos: acknowledge ACPI driven wake alarms upon resume Previously, the RTC alarm is acknowledged either by the cmos rtc irq handler, or by the hpet rtc irq handler. When using ACPI RTC Fixed event as the RTC alarm, the RTC alarm is acknowledged by the ACPI RTC event handler, as addressed in the previous patch. But, when resume from suspend-to-ram (ACPI S3), the ACPI SCI is cleared right after resume, thus the ACPI RTC event handler is not invoked at all, results in the RTC Alarm unacknowledged. Handle this by comparing the current time and the RTC Alarm time in the rtc_cmos driver .resume() callback 1. Assume the wakeup event has already been fired if the RTC Alarm time is earlier than/equal to the current time, and ACK the RTC Alarm. 2. Assume the wakeup event has not been fired if the RTC Alarm time is later than current time, and re-arm it if needed. Signed-off-by: Zhang Rui Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d8ce93921d31..5171bade16f2 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1013,8 +1013,26 @@ static void cmos_check_wkalrm(struct device *dev) { struct cmos_rtc *cmos = dev_get_drvdata(dev); struct rtc_wkalrm current_alarm; + time64_t t_now; time64_t t_current_expires; time64_t t_saved_expires; + struct rtc_time now; + + /* Check if we have RTC Alarm armed */ + if (!(cmos->suspend_ctrl & RTC_AIE)) + return; + + cmos_read_time(dev, &now); + t_now = rtc_tm_to_time64(&now); + + /* + * ACPI RTC wake event is cleared after resume from STR, + * ACK the rtc irq here + */ + if (t_now >= cmos->alarm_expires && use_acpi_alarm) { + cmos_interrupt(0, (void *)cmos->rtc); + return; + } cmos_read_alarm(dev, ¤t_alarm); t_current_expires = rtc_tm_to_time64(¤t_alarm.time); -- cgit v1.2.3 From 36d91a4d401c284ab21213622c85cd855725f10f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 26 Mar 2018 21:58:03 +0800 Subject: rtc: cmos: introduce quirks to enable use_acpi_alarm mode Use ACPI for RTC Alarm only for Intel platforms 1. with Low Power S0 support 2. with HPET RTC emulation enabled 3. no earlier than 2015 Note that, during the test, it is found that this patch 1. works in 4.15-rc kernel 2. hangs the platform after suspend-to-idle for 2 or 3 times, in 4.15.0 3. works again in 4.16-rc3 kernel. 4. works in the latest 4.15.12 stable kernel. Thus although this patch breaks 4.15.0 kernel for some unknown reason, still, it is safe for both upstream and backport. Signed-off-by: Zhang Rui Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5171bade16f2..cd3a2411bc2f 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -43,6 +43,8 @@ #include #ifdef CONFIG_X86 #include +#include +#include #endif /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ @@ -1174,6 +1176,28 @@ static void rtc_wake_off(struct device *dev) acpi_disable_event(ACPI_EVENT_RTC, 0); } +#ifdef CONFIG_X86 +/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */ +static void use_acpi_alarm_quirks(void) +{ + int year; + + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return; + + if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) + return; + + if (!is_hpet_enabled()) + return; + + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2015) + use_acpi_alarm = true; +} +#else +static inline void use_acpi_alarm_quirks(void) { } +#endif + /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find * its device node and pass extra config data. This helps its driver use * capabilities that the now-obsolete mc146818 didn't have, and informs it @@ -1186,6 +1210,8 @@ static void cmos_wake_setup(struct device *dev) if (acpi_disabled) return; + use_acpi_alarm_quirks(); + rtc_wake_setup(dev); acpi_rtc_info.wake_on = rtc_wake_on; acpi_rtc_info.wake_off = rtc_wake_off; -- cgit v1.2.3 From 85368bb9de6366654f442e26fdd571981f205291 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 19 Apr 2018 16:06:14 +0200 Subject: rtc: simplify getting .drvdata We should get drvdata from struct device directly. Going via platform_device is an unneeded step back and forth. Signed-off-by: Wolfram Sang Acked-by: Michal Simek (for zynqmp) Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-bq4802.c | 6 ++---- drivers/rtc/rtc-ds1216.c | 6 ++---- drivers/rtc/rtc-ds1511.c | 9 +++------ drivers/rtc/rtc-ds1553.c | 15 +++++---------- drivers/rtc/rtc-ds1685.c | 21 +++++++-------------- drivers/rtc/rtc-ds1742.c | 6 ++---- drivers/rtc/rtc-lpc32xx.c | 16 ++++++---------- drivers/rtc/rtc-m48t59.c | 41 ++++++++++++++++------------------------- drivers/rtc/rtc-mv.c | 3 +-- drivers/rtc/rtc-mxc.c | 21 +++++++-------------- drivers/rtc/rtc-pcap.c | 15 +++++---------- drivers/rtc/rtc-sh.c | 15 +++++---------- drivers/rtc/rtc-stk17ta8.c | 15 +++++---------- drivers/rtc/rtc-test.c | 3 +-- drivers/rtc/rtc-zynqmp.c | 10 ++++------ 15 files changed, 71 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index bd170cb3361c..d768f6747961 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c @@ -48,8 +48,7 @@ static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) static int bq4802_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct bq4802 *p = platform_get_drvdata(pdev); + struct bq4802 *p = dev_get_drvdata(dev); unsigned long flags; unsigned int century; u8 val; @@ -91,8 +90,7 @@ static int bq4802_read_time(struct device *dev, struct rtc_time *tm) static int bq4802_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct bq4802 *p = platform_get_drvdata(pdev); + struct bq4802 *p = dev_get_drvdata(dev); u8 sec, min, hrs, day, mon, yrs, century, val; unsigned long flags; unsigned int year; diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 5f158715fb4c..50fabe1cd286 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c @@ -76,8 +76,7 @@ static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr) static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct ds1216_priv *priv = platform_get_drvdata(pdev); + struct ds1216_priv *priv = dev_get_drvdata(dev); struct ds1216_regs regs; ds1216_switch_ds_to_clock(priv->ioaddr); @@ -104,8 +103,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm) static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct ds1216_priv *priv = platform_get_drvdata(pdev); + struct ds1216_priv *priv = dev_get_drvdata(dev); struct ds1216_regs regs; ds1216_switch_ds_to_clock(priv->ioaddr); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index a7d5ca428d68..b8b6e51c0461 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -314,8 +314,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) static int ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -334,8 +333,7 @@ ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -373,8 +371,7 @@ ds1511_interrupt(int irq, void *dev_id) static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 2441b9a2b366..34af7a802f43 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -73,8 +73,7 @@ struct rtc_plat_data { static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; u8 century; @@ -98,8 +97,7 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; unsigned int year, month, day, hour, minute, second, week; unsigned int century; @@ -155,8 +153,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -172,8 +169,7 @@ static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -208,8 +204,7 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 1a39829d2b40..f0f8011dce3d 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -267,8 +267,7 @@ ds1685_rtc_get_ssn(struct ds1685_priv *rtc, u8 *ssn) static int ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm) { - 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 ctrlb, century; u8 seconds, minutes, hours, wday, mday, month, years; @@ -317,8 +316,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm) static int ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm) { - 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 ctrlb, seconds, minutes, hours, wday, mday, month, years, century; /* Fetch the time info from rtc_time. */ @@ -394,8 +392,7 @@ ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - 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 seconds, minutes, hours, mday, ctrlb, ctrlc; int ret; @@ -453,8 +450,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - 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 ctrlb, seconds, minutes, hours, mday; int ret; @@ -1119,8 +1115,7 @@ static ssize_t ds1685_rtc_sysfs_battery_show(struct device *dev, struct device_attribute *attr, char *buf) { - 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 ctrld; ctrld = rtc->read(rtc, RTC_CTRL_D); @@ -1140,8 +1135,7 @@ static ssize_t ds1685_rtc_sysfs_auxbatt_show(struct device *dev, struct device_attribute *attr, char *buf) { - 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 ctrl4a; ds1685_rtc_switch_to_bank1(rtc); @@ -1163,8 +1157,7 @@ static ssize_t ds1685_rtc_sysfs_serial_show(struct device *dev, struct device_attribute *attr, char *buf) { - 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 ssn[8]; ds1685_rtc_switch_to_bank1(rtc); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 2d781180e968..5b7f02e89941 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -58,8 +58,7 @@ struct rtc_plat_data { static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr_rtc; u8 century; @@ -83,8 +82,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr_rtc; unsigned int year, month, day, hour, minute, second, week; unsigned int century; diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index 3ba87239aacc..910e600275b9 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -294,11 +294,10 @@ static int lpc32xx_rtc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int lpc32xx_rtc_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); + struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); if (rtc->irq >= 0) { - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(dev)) enable_irq_wake(rtc->irq); else disable_irq_wake(rtc->irq); @@ -309,10 +308,9 @@ static int lpc32xx_rtc_suspend(struct device *dev) static int lpc32xx_rtc_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); + struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); - if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev)) + if (rtc->irq >= 0 && device_may_wakeup(dev)) disable_irq_wake(rtc->irq); return 0; @@ -321,8 +319,7 @@ static int lpc32xx_rtc_resume(struct device *dev) /* Unconditionally disable the alarm */ static int lpc32xx_rtc_freeze(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); + struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); spin_lock_irq(&rtc->lock); @@ -337,8 +334,7 @@ static int lpc32xx_rtc_freeze(struct device *dev) static int lpc32xx_rtc_thaw(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); + struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); if (rtc->alarm_enabled) { spin_lock_irq(&rtc->lock); diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 216fac62c888..1053a406b3aa 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -47,8 +47,7 @@ struct m48t59_private { static void m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); writeb(val, m48t59->ioaddr+ofs); } @@ -56,8 +55,7 @@ m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val) static u8 m48t59_mem_readb(struct device *dev, u32 ofs) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); return readb(m48t59->ioaddr+ofs); } @@ -67,9 +65,8 @@ m48t59_mem_readb(struct device *dev, u32 ofs) */ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); unsigned long flags; u8 val; @@ -110,9 +107,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); unsigned long flags; u8 val = 0; int year = tm->tm_year; @@ -157,9 +153,8 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) */ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); struct rtc_time *tm = &alrm->time; unsigned long flags; u8 val; @@ -204,9 +199,8 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) */ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); struct rtc_time *tm = &alrm->time; u8 mday, hour, min, sec; unsigned long flags; @@ -265,9 +259,8 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) */ static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&m48t59->lock, flags); @@ -282,9 +275,8 @@ static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) { - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); unsigned long flags; u8 val; @@ -303,9 +295,8 @@ static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id) { struct device *dev = (struct device *)dev_id; - struct platform_device *pdev = to_platform_device(dev); - struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct m48t59_private *m48t59 = platform_get_drvdata(pdev); + struct m48t59_plat_data *pdata = dev_get_platdata(dev); + struct m48t59_private *m48t59 = dev_get_drvdata(dev); u8 event; spin_lock(&m48t59->lock); diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index bc52dbb0c0e2..4b198b3778d3 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -176,8 +176,7 @@ static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) static int mv_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; if (pdata->irq < 0) diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index bce427d202ee..822ebe4be3c3 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -109,8 +109,7 @@ static inline int is_imx1_rtc(struct rtc_plat_data *data) */ static time64_t get_alarm_or_time(struct device *dev, int time_alarm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0; @@ -139,8 +138,7 @@ static time64_t get_alarm_or_time(struct device *dev, int time_alarm) static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time) { u32 tod, day, hr, min, sec, temp; - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; day = div_s64_rem(time, 86400, &tod); @@ -176,8 +174,7 @@ static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time) static void rtc_update_alarm(struct device *dev, struct rtc_time *alrm) { time64_t time; - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; time = rtc_tm_to_time64(alrm); @@ -190,8 +187,7 @@ static void rtc_update_alarm(struct device *dev, struct rtc_time *alrm) static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; u32 reg; @@ -266,8 +262,7 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) */ static int mxc_rtc_set_mmss(struct device *dev, time64_t time) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); /* * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only @@ -295,8 +290,7 @@ static int mxc_rtc_set_mmss(struct device *dev, time64_t time) */ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; rtc_time64_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time); @@ -310,8 +304,7 @@ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) */ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); rtc_update_alarm(dev, &alrm->time); diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index c05f524ba9af..f176cb9d0dbc 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c @@ -43,8 +43,7 @@ static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc) static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); + struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev); struct rtc_time *tm = &alrm->time; unsigned long secs; u32 tod; /* time of day, seconds since midnight */ @@ -63,8 +62,7 @@ static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); + struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev); struct rtc_time *tm = &alrm->time; unsigned long secs; u32 tod, days; @@ -82,8 +80,7 @@ static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); + struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev); unsigned long secs; u32 tod, days; @@ -100,8 +97,7 @@ static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) { - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); + struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev); u32 tod, days; tod = secs % SEC_PER_DAY; @@ -115,8 +111,7 @@ static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en) { - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); + struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev); if (en) enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq)); diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 4e8ab370ce63..4f98543d1ea5 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -359,8 +359,7 @@ static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(dev); unsigned int sec128, sec2, yr, yr100, cf_bit; do { @@ -419,8 +418,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(dev); unsigned int tmp; int year; @@ -475,8 +473,7 @@ static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off) static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(dev); struct rtc_time *tm = &wkalrm->time; spin_lock_irq(&rtc->lock); @@ -509,8 +506,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(dev); unsigned int rcr1; struct rtc_time *tm = &wkalrm->time; int mon; @@ -723,8 +719,7 @@ static int __exit sh_rtc_remove(struct platform_device *pdev) static void sh_rtc_set_irq_wake(struct device *dev, int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(dev); irq_set_irq_wake(rtc->periodic_irq, enabled); diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index e70b78d17a98..fccbecbb2c98 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -74,8 +74,7 @@ struct rtc_plat_data { static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; u8 flags; @@ -97,8 +96,7 @@ static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; unsigned int year, month, day, hour, minute, second, week; unsigned int century; @@ -163,8 +161,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -180,8 +177,7 @@ static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; @@ -217,8 +213,7 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) static int stk17ta8_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = dev_get_drvdata(dev); if (pdata->irq <= 0) return -EINVAL; diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 3a2da4c892d6..390f928fd6fc 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -84,8 +84,7 @@ static ssize_t test_irq_store(struct device *dev, const char *buf, size_t count) { int retval; - struct platform_device *plat_dev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(plat_dev); + struct rtc_device *rtc = dev_get_drvdata(dev); retval = count; if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled) diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index fba994dc31eb..c532bd13fbe5 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -278,10 +278,9 @@ static int xlnx_rtc_remove(struct platform_device *pdev) static int __maybe_unused xlnx_rtc_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev); + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(dev)) enable_irq_wake(xrtcdev->alarm_irq); else xlnx_rtc_alarm_irq_enable(dev, 0); @@ -291,10 +290,9 @@ static int __maybe_unused xlnx_rtc_suspend(struct device *dev) static int __maybe_unused xlnx_rtc_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev); + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(dev)) disable_irq_wake(xrtcdev->alarm_irq); else xlnx_rtc_alarm_irq_enable(dev, 1); -- cgit v1.2.3 From 369a30a5f1c9245a214155ee527fa169e7f813ff Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 26 Apr 2018 10:58:44 +0800 Subject: rtc: sprd: Change to use devm_rtc_allocate_device() This is a preparation patch, changing to use devm_rtc_allocate_device() that can allow driver to set 'range_max' and 'range_min' for the RTC device. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 00d87d138984..ac86322c72bc 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -600,6 +600,10 @@ static int sprd_rtc_probe(struct platform_device *pdev) return rtc->irq; } + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc->rtc)) + return PTR_ERR(rtc->rtc); + rtc->dev = &pdev->dev; platform_set_drvdata(pdev, rtc); @@ -626,10 +630,12 @@ static int sprd_rtc_probe(struct platform_device *pdev) return ret; } - rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &sprd_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc)) - return PTR_ERR(rtc->rtc); + rtc->rtc->ops = &sprd_rtc_ops; + ret = rtc_register_device(rtc->rtc); + if (ret) { + dev_err(&pdev->dev, "failed to register rtc device\n"); + return ret; + } device_init_wakeup(&pdev->dev, 1); return 0; -- cgit v1.2.3 From 149aa91cd6d526e7f6eec3490e82eb073c7881f9 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 26 Apr 2018 10:58:45 +0800 Subject: rtc: sprd: Add RTC hardware range The SC27xx RTC can support dates from 1970-01-01 00:00:00 to 2149-06-06 23:59:59. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index ac86322c72bc..6a3876edd8e0 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -631,6 +631,8 @@ static int sprd_rtc_probe(struct platform_device *pdev) } 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"); -- cgit v1.2.3 From 51ed73eb998a1c79a2b0e9bed68f75a8a2c93b9b Mon Sep 17 00:00:00 2001 From: Andrea Greco Date: Fri, 20 Apr 2018 11:34:02 +0200 Subject: rtc: ds1340: Add support for trickle charger. Add support Dallas DS1340 trickle charger function. Signed-off-by: Andrea Greco Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index a13e59edff53..e9ec4160d7f6 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -201,6 +201,7 @@ static const struct chip_desc chips[last_ds_type] = { .century_reg = DS1307_REG_HOUR, .century_enable_bit = DS1340_BIT_CENTURY_EN, .century_bit = DS1340_BIT_CENTURY, + .do_trickle_setup = &do_trickle_setup_ds1339, .trickle_charger_reg = 0x08, }, [ds_1341] = { @@ -1371,6 +1372,7 @@ 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, -- cgit v1.2.3 From 0d1c655380be0962842beeb82772bf37820ebda6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 20 Apr 2018 18:14:24 +0200 Subject: rtc: vr41xx: remove mktime usage This driver uses mktime() and rtc_time_to_tm() to convert between time values. This works fine on 64-bit kernels over the whole supported range, and the vr41xx chip is a 64-bit MIPS implementation, but it is inconsistent because it doesn't do the same thing on 32-bit kernels that overflow in 2106 or 2038. Changing it to use mktime64/rtc_time64_to_tm() should have no visible impact on vr41xx but gets us closer to removing the 32-bit interfaces. Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-vr41xx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 7ce22967fd16..480cffe8d321 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -88,7 +88,7 @@ static unsigned int alarm_enabled; static int aie_irq; static int pie_irq; -static inline unsigned long read_elapsed_second(void) +static inline time64_t read_elapsed_second(void) { unsigned long first_low, first_mid, first_high; @@ -105,10 +105,10 @@ static inline unsigned long read_elapsed_second(void) } while (first_low != second_low || first_mid != second_mid || first_high != second_high); - return (first_high << 17) | (first_mid << 1) | (first_low >> 15); + return ((u64)first_high << 17) | (first_mid << 1) | (first_low >> 15); } -static inline void write_elapsed_second(unsigned long sec) +static inline void write_elapsed_second(time64_t sec) { spin_lock_irq(&rtc_lock); @@ -121,22 +121,22 @@ static inline void write_elapsed_second(unsigned long sec) static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time) { - unsigned long epoch_sec, elapsed_sec; + time64_t epoch_sec, elapsed_sec; - epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); + epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0); elapsed_sec = read_elapsed_second(); - rtc_time_to_tm(epoch_sec + elapsed_sec, time); + rtc_time64_to_tm(epoch_sec + elapsed_sec, time); return 0; } static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time) { - unsigned long epoch_sec, current_sec; + time64_t epoch_sec, current_sec; - epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); - current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, + 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); write_elapsed_second(current_sec - epoch_sec); @@ -165,11 +165,11 @@ 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) { - unsigned long alarm_sec; + time64_t alarm_sec; struct rtc_time *time = &wkalrm->time; - alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + alarm_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); spin_lock_irq(&rtc_lock); -- cgit v1.2.3 From 337fa19cc31541e2574dacbde8def1abe05a8739 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 20 Apr 2018 18:14:25 +0200 Subject: rtc: ls1x: remove mktime usage The loongson1 platform is 32-bit, so storing a time value in 32 bits suffers from limited range. In this case it is likely to be correct until 2106, but it's better to avoid the limitation and just use the time64_t based mktime64() and rtc_time64_to_tm() interfaces. The hardware uses a 32-bit year number, and time64_t can cover that entire range. Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ls1x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 045af1135e48..de86f9fabc11 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -87,16 +87,17 @@ static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm) { - unsigned long v, t; + unsigned long v; + time64_t t; v = readl(SYS_TOYREAD0); t = readl(SYS_TOYREAD1); memset(rtm, 0, sizeof(struct rtc_time)); - t = mktime((t & LS1X_YEAR_MASK), ls1x_get_month(v), + t = mktime64((t & LS1X_YEAR_MASK), ls1x_get_month(v), ls1x_get_day(v), ls1x_get_hour(v), ls1x_get_min(v), ls1x_get_sec(v)); - rtc_time_to_tm(t, rtm); + rtc_time64_to_tm(t, rtm); return 0; } -- cgit v1.2.3 From 7982df86711d06bfb88c74d9da16bf9f8e99cbaf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 20 Apr 2018 18:14:26 +0200 Subject: rtc: tps6586x: remove mktime usage The tps6586x use a 64-bit 'epoch_start' value, but then computes that value using an 'mktime()', which has a smaller range and overflows in 2106 at the latest. As both the hardware and the subsystem interface support wider than 32-bit ranges for rtc times here, let's change all the operations on 'seconds' to time64_t. Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tps6586x.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index d7785ae0a2b4..46a19adf9a96 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -58,7 +58,7 @@ struct tps6586x_rtc { struct rtc_device *rtc; int irq; bool irq_en; - unsigned long long epoch_start; + time64_t epoch_start; }; static inline struct device *to_tps6586x_dev(struct device *dev) @@ -71,7 +71,7 @@ static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long long ticks = 0; - unsigned long seconds; + time64_t seconds; u8 buff[6]; int ret; int i; @@ -98,11 +98,11 @@ static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long long ticks; - unsigned long seconds; + time64_t seconds; u8 buff[5]; int ret; - rtc_tm_to_time(tm, &seconds); + seconds = rtc_tm_to_time64(tm); if (seconds < rtc->epoch_start) { dev_err(dev, "requested time unsupported\n"); return -EINVAL; @@ -157,7 +157,7 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); - unsigned long seconds; + time64_t seconds; unsigned long ticks; unsigned long rtc_current_time; unsigned long long rticks = 0; @@ -166,7 +166,7 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) int ret; int i; - rtc_tm_to_time(&alrm->time, &seconds); + seconds = rtc_tm_to_time64(&alrm->time); if (alrm->enabled && (seconds < rtc->epoch_start)) { dev_err(dev, "can't set alarm to requested time\n"); @@ -213,7 +213,7 @@ static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long ticks; - unsigned long seconds; + time64_t seconds; u8 buff[3]; int ret; @@ -227,7 +227,7 @@ static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) seconds = ticks >> 10; seconds += rtc->epoch_start; - rtc_time_to_tm(seconds, &alrm->time); + rtc_time64_to_tm(seconds, &alrm->time); return 0; } @@ -261,7 +261,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) rtc->irq = platform_get_irq(pdev, 0); /* Set epoch start as 00:00:00:01:01:2009 */ - rtc->epoch_start = mktime(2009, 1, 1, 0, 0, 0); + rtc->epoch_start = mktime64(2009, 1, 1, 0, 0, 0); /* 1 kHz tick mode, enable tick counting */ ret = tps6586x_update(tps_dev, RTC_CTRL, -- cgit v1.2.3 From 248056457287afe742c5a81abd0bdd3ce002750d Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:40 +0200 Subject: rtc: stm32: fix copyright and adopt SPDX identifier Fix copyright by removing "SA" and "for STMicroelectronics", not required. Adopt SPDX identifier. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index f25dabe8fd02..79d9e8673279 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) STMicroelectronics SA 2017 - * Author: Amelie Delaunay for STMicroelectronics. - * License terms: GNU General Public License (GPL), version 2 + * Copyright (C) STMicroelectronics 2017 + * Author: Amelie Delaunay */ #include -- cgit v1.2.3 From d213217d213e0e5648448fc2a5da977a74dc6ad9 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:41 +0200 Subject: rtc: stm32: fix alarm interrupt flags by removing IRQF_TRIGGER_RISING RTC alarm interrupt is active high and already configured by device tree. So remove IRQF_TRIGGER_RISING from driver. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 79d9e8673279..6a060780f797 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -663,8 +663,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) /* Handle RTC alarm interrupts */ ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL, - stm32_rtc_alarm_irq, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + stm32_rtc_alarm_irq, IRQF_ONESHOT, pdev->name, rtc); if (ret) { dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n", -- cgit v1.2.3 From 22cb47c1ea2040c0424073c9d67dd0e644334a7c Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:43 +0200 Subject: rtc: stm32: get DBP register and mask from DT st, syscfg property RTC driver should not be aware of the PWR registers offset and bits position. Furthermore, we can imagine that DBP relative register and bit mask could change depending on the SoC. So this patch introduces 2 parameters, dbp_reg and dbp_mask, allowing to get PWR_CR and PWR_CR_DBP from device tree. And it prepares next RTC version, backup domain write protection is disabled only if needed. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 59 +++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 6a060780f797..de49b5b12951 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -85,23 +85,17 @@ #define RTC_WPR_2ND_KEY 0x53 #define RTC_WPR_WRONG_KEY 0xFF -/* - * RTC registers are protected against parasitic write access. - * PWR_CR_DBP bit must be set to enable write access to RTC registers. - */ -/* STM32_PWR_CR */ -#define PWR_CR 0x00 -/* STM32_PWR_CR bit field */ -#define PWR_CR_DBP BIT(8) - struct stm32_rtc_data { bool has_pclk; + bool need_dbp; }; struct stm32_rtc { struct rtc_device *rtc_dev; void __iomem *base; struct regmap *dbp; + unsigned int dbp_reg; + unsigned int dbp_mask; struct stm32_rtc_data *data; struct clk *pclk; struct clk *rtc_ck; @@ -498,10 +492,12 @@ static const struct rtc_class_ops stm32_rtc_ops = { static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, + .need_dbp = true, }; static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, + .need_dbp = true, }; static const struct of_device_id stm32_rtc_of_match[] = { @@ -576,7 +572,6 @@ static int stm32_rtc_probe(struct platform_device *pdev) { struct stm32_rtc *rtc; struct resource *res; - const struct of_device_id *match; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -588,15 +583,31 @@ static int stm32_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return PTR_ERR(rtc->base); - rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "st,syscfg"); - if (IS_ERR(rtc->dbp)) { - dev_err(&pdev->dev, "no st,syscfg\n"); - return PTR_ERR(rtc->dbp); - } + rtc->data = (struct stm32_rtc_data *) + of_device_get_match_data(&pdev->dev); + + if (rtc->data->need_dbp) { + rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "st,syscfg"); + if (IS_ERR(rtc->dbp)) { + dev_err(&pdev->dev, "no st,syscfg\n"); + return PTR_ERR(rtc->dbp); + } - match = of_match_device(stm32_rtc_of_match, &pdev->dev); - rtc->data = (struct stm32_rtc_data *)match->data; + ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg", + 1, &rtc->dbp_reg); + if (ret) { + dev_err(&pdev->dev, "can't read DBP register offset\n"); + return ret; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg", + 2, &rtc->dbp_mask); + if (ret) { + dev_err(&pdev->dev, "can't read DBP register mask\n"); + return ret; + } + } if (!rtc->data->has_pclk) { rtc->pclk = NULL; @@ -624,7 +635,9 @@ static int stm32_rtc_probe(struct platform_device *pdev) if (ret) goto err; - regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP); + if (rtc->data->need_dbp) + regmap_update_bits(rtc->dbp, rtc->dbp_reg, + rtc->dbp_mask, rtc->dbp_mask); /* * After a system reset, RTC_ISR.INITS flag can be read to check if @@ -684,7 +697,8 @@ err: clk_disable_unprepare(rtc->pclk); clk_disable_unprepare(rtc->rtc_ck); - regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0); + if (rtc->data->need_dbp) + regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); device_init_wakeup(&pdev->dev, false); @@ -707,8 +721,9 @@ static int stm32_rtc_remove(struct platform_device *pdev) if (rtc->data->has_pclk) clk_disable_unprepare(rtc->pclk); - /* Enable backup domain write protection */ - regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0); + /* Enable backup domain write protection if needed */ + if (rtc->data->need_dbp) + regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); device_init_wakeup(&pdev->dev, false); -- cgit v1.2.3 From 6c78a872a673c467c747e2eafc07289d921d3178 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:17:28 +0200 Subject: rtc: at91rm9200: add range The at91rm9200 RTC can support dates from 1900-01-01 00:00:00 to 2099-12-31 23:59:59. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-at91rm9200.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index de81ecedd571..caa71d04e989 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -440,6 +440,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); rtc->ops = &at91_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_1900; + rtc->range_max = RTC_TIMESTAMP_END_2099; ret = rtc_register_device(rtc); if (ret) goto err_clk; -- cgit v1.2.3 From 48b29c7fc2491edabd3d0f1e68f721043e4a079f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:18:56 +0200 Subject: rtc: 88pm80x: stop setting a default time It doesn't make sense to set the RTC to a default value at probe time. Let the core handle invalid date and time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 6cbafefa80a2..76df274f3e1a 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -254,8 +254,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev) struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev); struct pm80x_rtc_info *info; struct device_node *node = pdev->dev.of_node; - struct rtc_time tm; - unsigned long ticks = 0; int ret; if (!pdata && !node) { @@ -302,26 +300,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev) goto out; } - ret = pm80x_rtc_read_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read initial time.\n"); - goto out_rtc; - } - 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 = pm80x_rtc_set_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to set initial time.\n"); - goto out_rtc; - } - } - rtc_tm_to_time(&tm, &ticks); - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc", &pm80x_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { -- cgit v1.2.3 From ba78d51bdf97e67d6ae37075fa34c75068c2938e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:18:57 +0200 Subject: rtc: 88pm80x: remove unused pm80x_rtc_info members pm80x_rtc_info.calib_work and pm80x_rtc_info.vrtc are never used, remove them. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 76df274f3e1a..f60c0d73c2f3 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -52,10 +52,8 @@ struct pm80x_rtc_info { struct regmap *map; struct rtc_device *rtc_dev; struct device *dev; - struct delayed_work calib_work; int irq; - int vrtc; }; static irqreturn_t rtc_update_handler(int irq, void *data) -- cgit v1.2.3 From 661eb89a11c5f39249d8d0d50b4e538ef7bdd9d6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:18:58 +0200 Subject: rtc: 88pm80x: 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-88pm80x.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index f60c0d73c2f3..dae527f8c58e 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -290,6 +290,10 @@ static int pm80x_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 = pm80x_request_irq(chip, info->irq, rtc_update_handler, IRQF_ONESHOT, "rtc", info); if (ret < 0) { @@ -298,10 +302,10 @@ static int pm80x_rtc_probe(struct platform_device *pdev) goto out; } - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc", - &pm80x_rtc_ops, THIS_MODULE); - if (IS_ERR(info->rtc_dev)) { - ret = PTR_ERR(info->rtc_dev); + info->rtc_dev->ops = &pm80x_rtc_ops; + + ret = rtc_register_device(info->rtc_dev); + if (ret) { dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); goto out_rtc; } -- cgit v1.2.3 From 39ba69427a1541c9d599cfbe39366c0c7594340d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:18:59 +0200 Subject: rtc: 88pm80x: let the core handle the RTC range The 88pm80x RTC is storing the time as a 32bit offset from a 32bit counter so it can handle dates from 0 to U32_MAX. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index dae527f8c58e..33b28b6117e9 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -132,12 +132,7 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm) struct pm80x_rtc_info *info = dev_get_drvdata(dev); unsigned char buf[4]; unsigned long ticks, base, data; - if (tm->tm_year > 206) { - dev_dbg(info->dev, - "Set time %d out of range. Please set time between 1970 to 2106.\n", - 1900 + tm->tm_year); - return -EINVAL; - } + rtc_tm_to_time(tm, &ticks); /* load 32-bit read-only counter */ @@ -303,6 +298,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev) } info->rtc_dev->ops = &pm80x_rtc_ops; + info->rtc_dev->range_max = U32_MAX; ret = rtc_register_device(info->rtc_dev); if (ret) { -- cgit v1.2.3 From 02f3712f1f6c878c0fc4657d763272970b1013f5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:19:00 +0200 Subject: rtc: 88pm80x: convert to rtc_tm_to_time64/rtc_time64_to_tm Now that the RTC range is properly checked, convert the driver to rtc_tm_to_time64/rtc_time64_to_tm Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 33b28b6117e9..cab293cb2bf0 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -98,13 +98,13 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, 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); + now_time = rtc_tm_to_time64(now); + next_time = rtc_tm_to_time64(next); if (next_time < now_time) { /* Advance one day */ next_time += 60 * 60 * 24; - rtc_time_to_tm(next_time, next); + rtc_time64_to_tm(next_time, next); } } @@ -123,7 +123,7 @@ static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm) 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, tm); + rtc_time64_to_tm(ticks, tm); return 0; } @@ -133,7 +133,7 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[4]; unsigned long ticks, base, data; - rtc_tm_to_time(tm, &ticks); + ticks = rtc_tm_to_time64(tm); /* load 32-bit read-only counter */ regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); @@ -167,7 +167,7 @@ static int pm80x_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); regmap_read(info->map, PM800_RTC_CONTROL, &ret); alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0; alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0; @@ -195,11 +195,11 @@ static int pm80x_rtc_set_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, &now_tm); + rtc_time64_to_tm(ticks, &now_tm); dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks); 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(&alarm_tm); dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks); data = ticks - base; -- cgit v1.2.3 From 8bde032b280605c21a247557de9ee71e5835cab8 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:20:39 +0200 Subject: rtc: ab-b5ze-s3: fix possible race conditions 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. Also, the probe function is not allowed to fail after the RTC is registered because the following may happen: CPU0: CPU1: sys_load_module() do_init_module() do_one_initcall() cmos_do_probe() rtc_device_register() __register_chrdev() cdev->owner = struct module* open("/dev/rtc0") rtc_device_unregister() module_put() free_module() module_free(mod->module_core) /* struct module *module is now freed */ chrdev_open() spin_lock(cdev_lock) cdev_get() try_module_get() module_is_live() /* dereferences already freed struct module* */ Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before requesting the IRQ and register the RTC as late as possible. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab-b5ze-s3.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index 8dc451932446..f486912577e7 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -925,6 +925,14 @@ static int abb5zes3_probe(struct i2c_client *client, if (ret) goto err; + data->rtc = devm_rtc_allocate_device(dev); + ret = PTR_ERR_OR_ZERO(data->rtc); + if (ret) { + dev_err(dev, "%s: unable to allocate RTC device (%d)\n", + __func__, ret); + goto err; + } + if (client->irq > 0) { ret = devm_request_threaded_irq(dev, client->irq, NULL, _abb5zes3_rtc_interrupt, @@ -942,14 +950,7 @@ static int abb5zes3_probe(struct i2c_client *client, } } - data->rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, - THIS_MODULE); - ret = PTR_ERR_OR_ZERO(data->rtc); - if (ret) { - dev_err(dev, "%s: unable to register RTC device (%d)\n", - __func__, ret); - goto err; - } + data->rtc->ops = &rtc_ops; /* Enable battery low detection interrupt if battery not already low */ if (!data->battery_low && data->irq) { @@ -961,6 +962,8 @@ static int abb5zes3_probe(struct i2c_client *client, } } + ret = rtc_register_device(data->rtc); + err: if (ret && data && data->irq) device_init_wakeup(dev, false); -- cgit v1.2.3 From c402f8ead68ccd05d63f79ab729184498c3467b3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:20:40 +0200 Subject: rtc: ab-b5ze-s3: let the core handle the RTC range The ab-b5ze-s3 RTC is storing the year in an 8bit bcd coded register so it can handle dates from year 2000 to year 2099. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab-b5ze-s3.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index f486912577e7..2233601761ac 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -265,15 +265,6 @@ static int abb5zes3_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN]; int ret; - /* - * Year register is 8-bit wide and bcd-coded, i.e records values - * between 0 and 99. tm_year is an offset from 1900 and we are - * interested in the 2000-2099 range, so any value less than 100 - * is invalid. - */ - if (tm->tm_year < 100) - return -EINVAL; - regs[ABB5ZES3_REG_RTC_SC] = bin2bcd(tm->tm_sec); /* MSB=0 clears OSC */ regs[ABB5ZES3_REG_RTC_MN] = bin2bcd(tm->tm_min); regs[ABB5ZES3_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */ @@ -951,6 +942,8 @@ static int abb5zes3_probe(struct i2c_client *client, } data->rtc->ops = &rtc_ops; + data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + data->rtc->range_max = RTC_TIMESTAMP_END_2099; /* Enable battery low detection interrupt if battery not already low */ if (!data->battery_low && data->irq) { -- cgit v1.2.3 From e6000a438e534ee0afd9e83b67f4e23a26dd1067 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:26:21 +0200 Subject: rtc: tps65910: 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-tps65910.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index d0244d7979fc..a56b526db89a 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -380,6 +380,10 @@ static int tps65910_rtc_probe(struct platform_device *pdev) if (!tps_rtc) return -ENOMEM; + tps_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(tps_rtc->rtc)) + return PTR_ERR(tps_rtc->rtc); + /* Clear pending interrupts */ ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg); if (ret < 0) @@ -421,10 +425,10 @@ static int tps65910_rtc_probe(struct platform_device *pdev) tps_rtc->irq = irq; device_set_wakeup_capable(&pdev->dev, 1); - tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &tps65910_rtc_ops, THIS_MODULE); - if (IS_ERR(tps_rtc->rtc)) { - ret = PTR_ERR(tps_rtc->rtc); + tps_rtc->rtc->ops = &tps65910_rtc_ops; + + ret = rtc_register_device(tps_rtc->rtc); + if (ret) { dev_err(&pdev->dev, "RTC device register: err %d\n", ret); return ret; } -- cgit v1.2.3 From ee366c7a0e2f45bf76f7e4e132c5d1f8964209fa Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:26:22 +0200 Subject: rtc: tps65910: allow platform power up Currently, the IRQs are disabled when the rtc driver is removed (e.g. when shutting down the platform). This means that the RTC will be unable to power up the platform. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tps65910.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index a56b526db89a..819d2d0957b4 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -436,17 +436,6 @@ static int tps65910_rtc_probe(struct platform_device *pdev) return 0; } -/* - * Disable tps65910 RTC interrupts. - * Sets status flag to free. - */ -static int tps65910_rtc_remove(struct platform_device *pdev) -{ - tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int tps65910_rtc_suspend(struct device *dev) { @@ -472,7 +461,6 @@ static SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend, static struct platform_driver tps65910_rtc_driver = { .probe = tps65910_rtc_probe, - .remove = tps65910_rtc_remove, .driver = { .name = "tps65910-rtc", .pm = &tps65910_rtc_pm_ops, -- cgit v1.2.3 From 57ad9e69251177843fd6673eb1d7085e9cf39989 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:26:23 +0200 Subject: rtc: tps65910: add range The tps65910 RTC can support dates from 01/01/2000 to 31/12/2099. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tps65910.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 819d2d0957b4..a9bbd022aeef 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -426,6 +426,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, 1); tps_rtc->rtc->ops = &tps65910_rtc_ops; + tps_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + tps_rtc->rtc->range_max = RTC_TIMESTAMP_END_2099; ret = rtc_register_device(tps_rtc->rtc); if (ret) { -- cgit v1.2.3 From b8157168207db81f7f65a6e54675272c31868af5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:25 +0200 Subject: rtc: rx8581: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 32caadf912ca..c64911a08531 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -286,16 +286,13 @@ static int rx8581_probe(struct i2c_client *client, rx8581->write_block_data = rx8581_write_block_data; } - rx8581->rtc = devm_rtc_device_register(&client->dev, - rx8581_driver.driver.name, &rx8581_rtc_ops, THIS_MODULE); - - if (IS_ERR(rx8581->rtc)) { - dev_err(&client->dev, - "unable to register the class device\n"); + rx8581->rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rx8581->rtc)) return PTR_ERR(rx8581->rtc); - } - return 0; + rx8581->rtc->ops = &rx8581_rtc_ops; + + return rtc_register_device(rx8581->rtc); } static const struct i2c_device_id rx8581_id[] = { -- cgit v1.2.3 From 86c54ef6e607ff190cd3464dfd8eba5b77388ea6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:26 +0200 Subject: rtc: rx8581: add RTC range The rx8581 can support dates from 01/01/2000 to 31/12/2099. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index c64911a08531..c5ffd30ca672 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -291,6 +291,8 @@ static int rx8581_probe(struct i2c_client *client, return PTR_ERR(rx8581->rtc); rx8581->rtc->ops = &rx8581_rtc_ops; + rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099; return rtc_register_device(rx8581->rtc); } -- cgit v1.2.3 From c6e3c297a1948095c248058fd4ba51b1f9d12e7f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:27 +0200 Subject: rtc: rx8581: let the core handle rtc range Let the core handle offsetting and windowing the RTC range. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index c5ffd30ca672..171ee241bd2f 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -153,10 +153,7 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ - tm->tm_year = bcd2bin(date[RX8581_REG_YR]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ - + tm->tm_year = bcd2bin(date[RX8581_REG_YR]) + 100; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", @@ -190,7 +187,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); /* year and century */ - buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100); + buf[RX8581_REG_YR] = bin2bcd(tm->tm_year - 100); buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); /* Stop the clock */ @@ -293,6 +290,8 @@ static int rx8581_probe(struct i2c_client *client, rx8581->rtc->ops = &rx8581_rtc_ops; rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099; + rx8581->rtc->start_secs = 0; + rx8581->rtc->set_start_time = true; return rtc_register_device(rx8581->rtc); } -- cgit v1.2.3 From 2d2b300b3875cb76b67e5aa6ba39b58519942411 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:28 +0200 Subject: rtc: rx8581: remove useless indirection rx8581_get_datetime and rx8581_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 171ee241bd2f..a91fbb86a110 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -93,8 +93,9 @@ static int rx8581_write_block_data(const struct i2c_client *client, u8 command, * In the routines that deal directly with the rx8581 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. */ -static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); unsigned char date[7]; int data, err; struct rx8581 *rx8581 = i2c_get_clientdata(client); @@ -164,8 +165,9 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); int data, err; unsigned char buf[7]; struct rx8581 *rx8581 = i2c_get_clientdata(client); @@ -242,16 +244,6 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return rx8581_get_datetime(to_i2c_client(dev), tm); -} - -static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return rx8581_set_datetime(to_i2c_client(dev), tm); -} - static const struct rtc_class_ops rx8581_rtc_ops = { .read_time = rx8581_rtc_read_time, .set_time = rx8581_rtc_set_time, -- cgit v1.2.3 From ed87c6d86d07dd345b2cd13f9be3794937165e04 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:29 +0200 Subject: rtc: rx8581: remove useless declaration The rx8581_driver forward declaration is useless, remove it. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index a91fbb86a110..0a70f1ac5cc2 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -59,8 +59,6 @@ struct rx8581 { u8 length, const u8 *values); }; -static struct i2c_driver rx8581_driver; - static int rx8581_read_block_data(const struct i2c_client *client, u8 command, u8 length, u8 *values) { @@ -107,7 +105,7 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) */ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); if (data < 0) { - dev_err(&client->dev, "Unable to read device flags\n"); + dev_err(dev, "Unable to read device flags\n"); return -EIO; } @@ -117,7 +115,7 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); if (err != 0) { - dev_err(&client->dev, "Unable to write device flags\n"); + dev_err(dev, "Unable to write device flags\n"); return -EIO; } } @@ -126,24 +124,23 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) err = rx8581->read_block_data(client, RX8581_REG_SC, 7, date); if (err < 0) { - dev_err(&client->dev, "Unable to read date\n"); + dev_err(dev, "Unable to read date\n"); return -EIO; } /* Check flag register */ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); if (data < 0) { - dev_err(&client->dev, "Unable to read device flags\n"); + dev_err(dev, "Unable to read device flags\n"); return -EIO; } } while (data & RX8581_FLAG_UF); if (data & RX8581_FLAG_VLF) - dev_info(&client->dev, + dev_info(dev, "low voltage detected, date/time is not reliable.\n"); - dev_dbg(&client->dev, - "%s: raw data is sec=%02x, min=%02x, hr=%02x, " + dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", __func__, date[0], date[1], date[2], date[3], date[4], date[5], date[6]); @@ -156,7 +153,7 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ tm->tm_year = bcd2bin(date[RX8581_REG_YR]) + 100; - dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, @@ -172,7 +169,7 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[7]; struct rx8581 *rx8581 = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " + dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, @@ -195,49 +192,49 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) /* Stop the clock */ data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); if (data < 0) { - dev_err(&client->dev, "Unable to read control register\n"); + dev_err(dev, "Unable to read control register\n"); return -EIO; } err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, (data | RX8581_CTRL_STOP)); if (err < 0) { - dev_err(&client->dev, "Unable to write control register\n"); + dev_err(dev, "Unable to write control register\n"); return -EIO; } /* write register's data */ err = rx8581->write_block_data(client, RX8581_REG_SC, 7, buf); if (err < 0) { - dev_err(&client->dev, "Unable to write to date registers\n"); + dev_err(dev, "Unable to write to date registers\n"); return -EIO; } /* get VLF and clear it */ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); if (data < 0) { - dev_err(&client->dev, "Unable to read flag register\n"); + dev_err(dev, "Unable to read flag register\n"); return -EIO; } err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, (data & ~(RX8581_FLAG_VLF))); if (err != 0) { - dev_err(&client->dev, "Unable to write flag register\n"); + dev_err(dev, "Unable to write flag register\n"); return -EIO; } /* Restart the clock */ data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); if (data < 0) { - dev_err(&client->dev, "Unable to read control register\n"); + dev_err(dev, "Unable to read control register\n"); return -EIO; } err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, (data & ~(RX8581_CTRL_STOP))); if (err != 0) { - dev_err(&client->dev, "Unable to write control register\n"); + dev_err(dev, "Unable to write control register\n"); return -EIO; } -- cgit v1.2.3 From 6e6111f6c08dcc34c8bc3b3a2a4f944ceeaa78be Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:30 +0200 Subject: rtc: rx8581: error out when time invalid Return an error when the date is unreliable because the battery is low. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 0a70f1ac5cc2..54631a3ab65f 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -109,6 +109,12 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) return -EIO; } + if (data & RX8581_FLAG_VLF) { + dev_warn(dev, + "low voltage detected, date/time is not reliable.\n"); + return -EINVAL; + } + do { /* If update flag set, clear it */ if (data & RX8581_FLAG_UF) { @@ -136,10 +142,6 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) } } while (data & RX8581_FLAG_UF); - if (data & RX8581_FLAG_VLF) - dev_info(dev, - "low voltage detected, date/time is not reliable.\n"); - dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", __func__, -- cgit v1.2.3 From 94389b28ba6c03eecf45105026c1f9978481a706 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:33:31 +0200 Subject: rtc: rx8581: switch to regmap Switch to regmap to simplify handling block read/write. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 155 +++++++++++++---------------------------------- 1 file changed, 42 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 54631a3ab65f..eac882169744 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -51,42 +52,10 @@ #define RX8581_CTRL_RESET 0x01 /* RESET bit */ struct rx8581 { - struct i2c_client *client; + struct regmap *regmap; struct rtc_device *rtc; - s32 (*read_block_data)(const struct i2c_client *client, u8 command, - u8 length, u8 *values); - s32 (*write_block_data)(const struct i2c_client *client, u8 command, - u8 length, const u8 *values); }; -static int rx8581_read_block_data(const struct i2c_client *client, u8 command, - u8 length, u8 *values) -{ - s32 i, data; - - for (i = 0; i < length; i++) { - data = i2c_smbus_read_byte_data(client, command + i); - if (data < 0) - return data; - values[i] = data; - } - return i; -} - -static int rx8581_write_block_data(const struct i2c_client *client, u8 command, - u8 length, const u8 *values) -{ - s32 i, ret; - - for (i = 0; i < length; i++) { - ret = i2c_smbus_write_byte_data(client, command + i, - values[i]); - if (ret < 0) - return ret; - } - return length; -} - /* * In the routines that deal directly with the rx8581 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. @@ -95,7 +64,8 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); unsigned char date[7]; - int data, err; + unsigned int data; + int err; struct rx8581 *rx8581 = i2c_get_clientdata(client); /* First we ensure that the "update flag" is not set, we read the @@ -103,11 +73,9 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) * has been set, we know that the time has changed during the read so * we repeat the whole process again. */ - data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); - if (data < 0) { - dev_err(dev, "Unable to read device flags\n"); - return -EIO; - } + err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + if (err < 0) + return err; if (data & RX8581_FLAG_VLF) { dev_warn(dev, @@ -118,28 +86,22 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) do { /* If update flag set, clear it */ if (data & RX8581_FLAG_UF) { - err = i2c_smbus_write_byte_data(client, - RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); - if (err != 0) { - dev_err(dev, "Unable to write device flags\n"); - return -EIO; - } + err = regmap_write(rx8581->regmap, RX8581_REG_FLAG, + data & ~RX8581_FLAG_UF); + if (err < 0) + return err; } /* Now read time and date */ - err = rx8581->read_block_data(client, RX8581_REG_SC, - 7, date); - if (err < 0) { - dev_err(dev, "Unable to read date\n"); - return -EIO; - } + err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date, + sizeof(date)); + if (err < 0) + return err; /* Check flag register */ - data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); - if (data < 0) { - dev_err(dev, "Unable to read device flags\n"); - return -EIO; - } + err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + if (err < 0) + return err; } while (data & RX8581_FLAG_UF); dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " @@ -167,7 +129,7 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); - int data, err; + int err; unsigned char buf[7]; struct rx8581 *rx8581 = i2c_get_clientdata(client); @@ -192,55 +154,26 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); /* Stop the clock */ - data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); - if (data < 0) { - dev_err(dev, "Unable to read control register\n"); - return -EIO; - } - - err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, - (data | RX8581_CTRL_STOP)); - if (err < 0) { - dev_err(dev, "Unable to write control register\n"); - return -EIO; - } + err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + RX8581_CTRL_STOP, RX8581_CTRL_STOP); + if (err < 0) + return err; /* write register's data */ - err = rx8581->write_block_data(client, RX8581_REG_SC, 7, buf); - if (err < 0) { - dev_err(dev, "Unable to write to date registers\n"); - return -EIO; - } + err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC, + buf, sizeof(buf)); + if (err < 0) + return err; /* get VLF and clear it */ - data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); - if (data < 0) { - dev_err(dev, "Unable to read flag register\n"); - return -EIO; - } - - err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, - (data & ~(RX8581_FLAG_VLF))); - if (err != 0) { - dev_err(dev, "Unable to write flag register\n"); - return -EIO; - } + err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG, + RX8581_FLAG_VLF, 0); + if (err < 0) + return err; /* Restart the clock */ - data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); - if (data < 0) { - dev_err(dev, "Unable to read control register\n"); - return -EIO; - } - - err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, - (data & ~(RX8581_CTRL_STOP))); - if (err != 0) { - dev_err(dev, "Unable to write control register\n"); - return -EIO; - } - - return 0; + return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + RX8581_CTRL_STOP, 0); } static const struct rtc_class_ops rx8581_rtc_ops = { @@ -252,27 +185,23 @@ static int rx8581_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct rx8581 *rx8581; + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xf, + }; dev_dbg(&client->dev, "%s\n", __func__); - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA) - && !i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) - return -EIO; - rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL); if (!rx8581) return -ENOMEM; i2c_set_clientdata(client, rx8581); - rx8581->client = client; - - if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { - rx8581->read_block_data = i2c_smbus_read_i2c_block_data; - rx8581->write_block_data = i2c_smbus_write_i2c_block_data; - } else { - rx8581->read_block_data = rx8581_read_block_data; - rx8581->write_block_data = rx8581_write_block_data; - } + + rx8581->regmap = devm_regmap_init_i2c(client, &config); + if (IS_ERR(rx8581->regmap)) + return PTR_ERR(rx8581->regmap); rx8581->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(rx8581->rtc)) -- cgit v1.2.3 From 9a99247c9c1d1c95c6e8153d013979aac6111c6e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:47:05 +0200 Subject: rtc: vr41xx: fix possible race condition The probe function is not allowed to fail after the RTC is registered because the following may happen: CPU0: CPU1: sys_load_module() do_init_module() do_one_initcall() cmos_do_probe() rtc_device_register() __register_chrdev() cdev->owner = struct module* open("/dev/rtc0") rtc_device_unregister() module_put() free_module() module_free(mod->module_core) /* struct module *module is now freed */ chrdev_open() spin_lock(cdev_lock) cdev_get() try_module_get() module_is_live() /* dereferences already freed struct module* */ Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-vr41xx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 480cffe8d321..2f1212a25f7e 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -292,13 +292,14 @@ static int rtc_probe(struct platform_device *pdev) goto err_rtc1_iounmap; } - rtc = devm_rtc_device_register(&pdev->dev, rtc_name, &vr41xx_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) { retval = PTR_ERR(rtc); goto err_iounmap_all; } + rtc->ops = &vr41xx_rtc_ops; + rtc->max_user_freq = MAX_PERIODIC_RATE; spin_lock_irq(&rtc_lock); @@ -340,6 +341,10 @@ static int rtc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n"); + retval = rtc_register_device(rtc); + if (retval) + goto err_iounmap_all; + return 0; err_iounmap_all: -- cgit v1.2.3 From 30d7891ae903d1e2903033a3df453d7533011076 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:47:06 +0200 Subject: rtc: vr41xx: add range The vr41xx RTC is a 48-bit counter counting at 32.768 kHz, giving a maximum value of 2^(48-15)-1 seconds. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-vr41xx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 2f1212a25f7e..70f013e692b0 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -300,6 +300,8 @@ static int rtc_probe(struct platform_device *pdev) rtc->ops = &vr41xx_rtc_ops; + /* 48-bit counter at 32.768 kHz */ + rtc->range_max = (1ULL << 33) - 1; rtc->max_user_freq = MAX_PERIODIC_RATE; spin_lock_irq(&rtc_lock); -- cgit v1.2.3 From 63d22063073b0ab46d1e06fe633fb5de8f5c58e1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:48:17 +0200 Subject: rtc: tps6586x: fix possible race condition The probe function is not allowed to fail after the RTC is registered because the following may happen: CPU0: CPU1: sys_load_module() do_init_module() do_one_initcall() cmos_do_probe() rtc_device_register() __register_chrdev() cdev->owner = struct module* open("/dev/rtc0") rtc_device_unregister() module_put() free_module() module_free(mod->module_core) /* struct module *module is now freed */ chrdev_open() spin_lock(cdev_lock) cdev_get() try_module_get() module_is_live() /* dereferences already freed struct module* */ Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tps6586x.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index 46a19adf9a96..9b741143f131 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -276,14 +276,15 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, rtc); - rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev), - &tps6586x_rtc_ops, THIS_MODULE); + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); - dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); + dev_err(&pdev->dev, "RTC allocate device: ret %d\n", ret); goto fail_rtc_register; } + rtc->rtc->ops = &tps6586x_rtc_ops; + ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, tps6586x_rtc_irq, IRQF_ONESHOT, @@ -294,6 +295,13 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) goto fail_rtc_register; } disable_irq(rtc->irq); + + ret = rtc_register_device(rtc->rtc); + if (ret) { + dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); + goto fail_rtc_register; + } + return 0; fail_rtc_register: -- cgit v1.2.3 From 180c92c4ae7c76329c990dc55dc3d422e7640527 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:48:18 +0200 Subject: rtc: tps6586x: let the core handle rtc range Let the core handle offsetting and windowing the RTC range. The RTC has a 40-bit counter counting at 1024 Hz. So its maximum value is 2^(40-10) - 1. Also, let the core handle the offset instead of coding it in the callbacks. Keep the default epoch at the beginning of 2009 (this will fail in 2043). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tps6586x.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index 9b741143f131..d6434e514a52 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -58,7 +58,6 @@ struct tps6586x_rtc { struct rtc_device *rtc; int irq; bool irq_en; - time64_t epoch_start; }; static inline struct device *to_tps6586x_dev(struct device *dev) @@ -68,7 +67,6 @@ static inline struct device *to_tps6586x_dev(struct device *dev) static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long long ticks = 0; time64_t seconds; @@ -88,14 +86,13 @@ static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) } seconds = ticks >> 10; - seconds += rtc->epoch_start; - rtc_time_to_tm(seconds, tm); + rtc_time64_to_tm(seconds, tm); + return 0; } static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long long ticks; time64_t seconds; @@ -103,11 +100,6 @@ static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) int ret; seconds = rtc_tm_to_time64(tm); - if (seconds < rtc->epoch_start) { - dev_err(dev, "requested time unsupported\n"); - return -EINVAL; - } - seconds -= rtc->epoch_start; ticks = (unsigned long long)seconds << 10; buff[0] = (ticks >> 32) & 0xff; @@ -155,7 +147,6 @@ static int tps6586x_rtc_alarm_irq_enable(struct device *dev, static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); time64_t seconds; unsigned long ticks; @@ -168,18 +159,12 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) seconds = rtc_tm_to_time64(&alrm->time); - if (alrm->enabled && (seconds < rtc->epoch_start)) { - dev_err(dev, "can't set alarm to requested time\n"); - return -EINVAL; - } - ret = tps6586x_rtc_alarm_irq_enable(dev, alrm->enabled); if (ret < 0) { dev_err(dev, "can't set alarm irq, err %d\n", ret); return ret; } - seconds -= rtc->epoch_start; ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(rbuff), rbuff); if (ret < 0) { @@ -210,7 +195,6 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct tps6586x_rtc *rtc = dev_get_drvdata(dev); struct device *tps_dev = to_tps6586x_dev(dev); unsigned long ticks; time64_t seconds; @@ -225,7 +209,6 @@ static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2]; seconds = ticks >> 10; - seconds += rtc->epoch_start; rtc_time64_to_tm(seconds, &alrm->time); return 0; @@ -260,9 +243,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) rtc->dev = &pdev->dev; rtc->irq = platform_get_irq(pdev, 0); - /* Set epoch start as 00:00:00:01:01:2009 */ - rtc->epoch_start = mktime64(2009, 1, 1, 0, 0, 0); - /* 1 kHz tick mode, enable tick counting */ ret = tps6586x_update(tps_dev, RTC_CTRL, RTC_ENABLE | OSC_SRC_SEL | @@ -284,6 +264,9 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) } rtc->rtc->ops = &tps6586x_rtc_ops; + rtc->rtc->range_max = (1ULL << 30) - 1; /* 30-bit seconds */ + rtc->rtc->start_secs = mktime64(2009, 1, 1, 0, 0, 0); + rtc->rtc->set_start_time = true; ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, tps6586x_rtc_irq, -- cgit v1.2.3 From 52f0e7bc19fb1397aa9d29f87415f94d39bb8b01 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:53:25 +0200 Subject: rtc: ls1x: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ls1x.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index de86f9fabc11..609bd1d013f0 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -173,15 +173,15 @@ static int ls1x_rtc_probe(struct platform_device *pdev) while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) usleep_range(1000, 3000); - rtcdev = devm_rtc_device_register(&pdev->dev, "ls1x-rtc", - &ls1x_rtc_ops , THIS_MODULE); - if (IS_ERR(rtcdev)) { - ret = PTR_ERR(rtcdev); - goto err; - } + rtcdev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtcdev)) + return PTR_ERR(rtcdev); platform_set_drvdata(pdev, rtcdev); - return 0; + rtcdev->ops = &ls1x_rtc_ops; + + return rtc_register_device(rtcdev); + err: return ret; } -- cgit v1.2.3 From 14dc3ec5203ced2000ef157f147944233309c850 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:53:26 +0200 Subject: rtc: ls1x: remove useless label and goto The error handling in ls1x_rtc_probe used to release resources but since it is using devm functions, it only returns a value. Make the code clearer by returning directly instead of using goto. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ls1x.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 609bd1d013f0..8aa3f223621c 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -148,15 +148,13 @@ static int ls1x_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtcdev; unsigned long v; - int ret; v = readl(SYS_COUNTER_CNTRL); if (!(v & RTC_CNTR_OK)) { dev_err(&pdev->dev, "rtc counters not working\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } - ret = -ETIMEDOUT; + /* set to 1 HZ if needed */ if (readl(SYS_TOYTRIM) != 32767) { v = 0x100000; @@ -165,7 +163,7 @@ static int ls1x_rtc_probe(struct platform_device *pdev) if (!v) { dev_err(&pdev->dev, "time out\n"); - goto err; + return -ETIMEDOUT; } writel(32767, SYS_TOYTRIM); } @@ -181,9 +179,6 @@ static int ls1x_rtc_probe(struct platform_device *pdev) rtcdev->ops = &ls1x_rtc_ops; return rtc_register_device(rtcdev); - -err: - return ret; } static struct platform_driver ls1x_rtc_driver = { -- cgit v1.2.3 From d7599245007a653fb5ff96d5ae067cb3204ff7fb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 17 May 2018 22:53:27 +0200 Subject: rtc: ls1x: add range While the year is encoded on 32 bits in SYS_TOYWRITE1i/SYS_TOYREAD1. The Loongson 1c datasheet states that the range is from 0 to 99. The current code exceeds this range and seems to be working, I deduce that the leap year algorithm will fail in 2100. Anyway, alarm registers only encode the year on 14 bits so with alarm support, the range will always be limited to 0 to 16383. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ls1x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 8aa3f223621c..f4c248655edd 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -177,6 +177,8 @@ static int ls1x_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtcdev); rtcdev->ops = &ls1x_rtc_ops; + rtcdev->range_min = RTC_TIMESTAMP_BEGIN_1900; + rtcdev->range_max = RTC_TIMESTAMP_END_2099; return rtc_register_device(rtcdev); } -- cgit v1.2.3 From 5490a1e018a4b447c1fdb49ec274a620e60a4d42 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 19 May 2018 10:01:42 +0200 Subject: rtc: mxc_v2: 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-mxc_v2.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 9e14efb990b2..4cc121a41fe0 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -343,6 +343,12 @@ static int mxc_rtc_probe(struct platform_device *pdev) return ret; } + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(pdata->rtc)) + return PTR_ERR(pdata->rtc); + + pdata->rtc->ops = &mxc_rtc_ops; + clk_disable(pdata->clk); platform_set_drvdata(pdev, pdata); ret = @@ -354,15 +360,11 @@ static int mxc_rtc_probe(struct platform_device *pdev) return ret; } - pdata->rtc = - devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops, - THIS_MODULE); - if (IS_ERR(pdata->rtc)) { + ret = rtc_register_device(pdata->rtc); + if (ret < 0) clk_unprepare(pdata->clk); - return PTR_ERR(pdata->rtc); - } - return 0; + return ret; } static int mxc_rtc_remove(struct platform_device *pdev) -- cgit v1.2.3 From 95fbfa14b431d4d7213b8e0e167563f7a11dd5e7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 19 May 2018 10:04:46 +0200 Subject: rtc: mxc_v2: let the core handle rtc range This RTC is a 32-bit second counter. This also solves an issue where mxc_rtc_set_alarm() can return with the lock taken. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc_v2.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 4cc121a41fe0..24ca74ca632a 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -165,11 +165,6 @@ static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm) time64_t time = rtc_tm_to_time64(tm); int ret; - if (time > U32_MAX) { - dev_err(dev, "RTC exceeded by %llus\n", time - U32_MAX); - return -EINVAL; - } - ret = mxc_rtc_lock(pdata); if (ret) return ret; @@ -248,11 +243,6 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (ret) return ret; - if (time > U32_MAX) { - dev_err(dev, "Hopefully I am out of service by then :-(\n"); - return -EINVAL; - } - writel((u32)time, pdata->ioaddr + SRTC_LPSAR); /* clear alarm interrupt status bit */ @@ -348,6 +338,7 @@ static int mxc_rtc_probe(struct platform_device *pdev) return PTR_ERR(pdata->rtc); pdata->rtc->ops = &mxc_rtc_ops; + pdata->rtc->range_max = U32_MAX; clk_disable(pdata->clk); platform_set_drvdata(pdev, pdata); -- cgit v1.2.3 From 7e83f03fad3e404778fbcfb16f91a09aecf27e04 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 19 May 2018 10:50:03 +0200 Subject: rtc: mxc_v2: use rtc_time64_to_tm in mxc_rtc_read_alarm Use the 64-bit version of rtc_time_to_tm in mxc_rtc_read_alarm Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 24ca74ca632a..c75f26dc8fcc 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -193,7 +193,7 @@ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (ret) return ret; - rtc_time_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time); + rtc_time64_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time); alrm->pending = !!(readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP); return mxc_rtc_unlock(pdata); } -- cgit v1.2.3 From 2abf286a20e338f2e105a2d19dfabec8927faa92 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 20 May 2018 22:27:29 +0200 Subject: rtc: brcmstb-waketimer: switch to rtc_register_device Switch to devm_rtc_allocate_device/rtc_register_device. Signed-off-by: Alexandre Belloni Reviewed-by: Florian Fainelli Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-brcmstb-waketimer.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index bdd6674a1054..ba49d9bcff12 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -229,6 +229,10 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev) if (IS_ERR(timer->base)) return PTR_ERR(timer->base); + timer->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(timer->rtc)) + return PTR_ERR(timer->rtc); + /* * Set wakeup capability before requesting wakeup interrupt, so we can * process boot-time "wakeups" (e.g., from S5 soft-off) @@ -261,11 +265,11 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev) timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot; register_reboot_notifier(&timer->reboot_notifier); - timer->rtc = rtc_device_register("brcmstb-waketmr", dev, - &brcmstb_waketmr_ops, THIS_MODULE); - if (IS_ERR(timer->rtc)) { + timer->rtc->ops = &brcmstb_waketmr_ops; + + ret = rtc_register_device(timer->rtc); + if (ret) { dev_err(dev, "unable to register device\n"); - ret = PTR_ERR(timer->rtc); goto err_notifier; } @@ -288,7 +292,6 @@ static int brcmstb_waketmr_remove(struct platform_device *pdev) struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev); unregister_reboot_notifier(&timer->reboot_notifier); - rtc_device_unregister(timer->rtc); return 0; } -- cgit v1.2.3 From ded676666f90882181fa004a43bcb84294c2a5c8 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 20 May 2018 22:27:30 +0200 Subject: rtc: brcmstb-waketimer: add range Let the core handle the range. Signed-off-by: Alexandre Belloni Reviewed-by: Florian Fainelli Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-brcmstb-waketimer.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index ba49d9bcff12..f4010a75f2be 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -145,9 +145,6 @@ static int brcmstb_waketmr_settime(struct device *dev, sec = rtc_tm_to_time64(tm); - if (sec > U32_MAX || sec < 0) - return -EINVAL; - writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER); return 0; @@ -184,9 +181,6 @@ static int brcmstb_waketmr_setalarm(struct device *dev, else sec = 0; - if (sec > U32_MAX || sec < 0) - return -EINVAL; - brcmstb_waketmr_set_alarm(timer, sec); return 0; @@ -266,6 +260,7 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev) register_reboot_notifier(&timer->reboot_notifier); timer->rtc->ops = &brcmstb_waketmr_ops; + timer->rtc->range_max = U32_MAX; ret = rtc_register_device(timer->rtc); if (ret) { -- cgit v1.2.3 From 48e9a9b203affc57a2bf6a0d0483472dd950a455 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sun, 20 May 2018 17:21:45 +0200 Subject: rtc: ds1742: don't explicitly specify word_size and stride of nvmem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nvmem_register() assumes these values to be 1 if unset, so they don't need to be set explicitly. Signed-off-by: Uwe Kleine-König Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1742.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 5b7f02e89941..5a4c2c5e86fe 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -152,8 +152,6 @@ static int ds1742_rtc_probe(struct platform_device *pdev) int ret = 0; struct nvmem_config nvmem_cfg = { .name = "ds1742_nvram", - .word_size = 1, - .stride = 1, .reg_read = ds1742_nvram_read, .reg_write = ds1742_nvram_write, }; -- cgit v1.2.3 From 046dbb2420cee74b31fd2ce266d3e2629d8c7b8a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sun, 20 May 2018 17:26:40 +0200 Subject: rtc: nvmem: don't use IS_ERR_OR_NULL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nvmem_register() never returns NULL, so IS_ERR is good enough here. Signed-off-by: Uwe Kleine-König Signed-off-by: Alexandre Belloni --- drivers/rtc/nvmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index 17ec4c8d0fad..36ab183c42f1 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -94,7 +94,7 @@ int rtc_nvmem_register(struct rtc_device *rtc, nvmem_config->dev = rtc->dev.parent; nvmem_config->owner = rtc->owner; rtc->nvmem = nvmem_register(nvmem_config); - if (IS_ERR_OR_NULL(rtc->nvmem)) + if (IS_ERR(rtc->nvmem)) return PTR_ERR(rtc->nvmem); /* Register the old ABI */ -- cgit v1.2.3 From 5874c7f16a10acba0db1658f24c3a7206c12ab14 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2018 23:45:58 -0300 Subject: rtc: snvs: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 9af591d5223c..8a75cc3af6e7 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -1,13 +1,6 @@ -/* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2011-2012 Freescale Semiconductor, Inc. #include #include -- cgit v1.2.3 From 75d01b75c2efcf79a3df0d60ebda3b9a7841e848 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2018 23:45:59 -0300 Subject: rtc: mxc: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 822ebe4be3c3..878c6ee82901 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -1,13 +1,6 @@ -/* - * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. #include #include -- cgit v1.2.3 From 819cbde5218689d33e0405ebe71bed07bc21f28e Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:23 +0200 Subject: rtc: stm32: fix misspelling and misalignment issues This patch cleans the following checkpatch complaints: CHECK: 'initalized' may be misspelled - perhaps 'initialized'? #644: FILE: drivers/rtc/rtc-stm32.c:644: + * the calendar has been initalized or not. INITS flag is reset by a CHECK: Alignment should match open parenthesis #669: FILE: drivers/rtc/rtc-stm32.c:669: + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, + &stm32_rtc_ops, THIS_MODULE); Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index de49b5b12951..d41f8047bee4 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -641,7 +641,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) /* * After a system reset, RTC_ISR.INITS flag can be read to check if - * the calendar has been initalized or not. INITS flag is reset by a + * the calendar has been initialized or not. INITS flag is reset by a * power-on reset (no vbat, no power-supply). It is not reset if * rtc_ck parent clock has changed (so RTC prescalers need to be * changed). That's why we cannot rely on this flag to know if RTC @@ -666,7 +666,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) "alarm won't be able to wake up the system"); rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, - &stm32_rtc_ops, THIS_MODULE); + &stm32_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc_dev)) { ret = PTR_ERR(rtc->rtc_dev); dev_err(&pdev->dev, "rtc device registration failed, err=%d\n", -- cgit v1.2.3 From 02b0cc345c2a1b7f1c590796a02d84e49e51ded0 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:24 +0200 Subject: rtc: stm32: rework register management to prepare other version of RTC This patch reworks register/bits management because next version of RTC uses the same way of working but with different register's offset or bits moved in new registers. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 184 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 127 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index d41f8047bee4..8254e38ec7cf 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -16,15 +16,6 @@ #define DRIVER_NAME "stm32_rtc" -/* STM32 RTC registers */ -#define STM32_RTC_TR 0x00 -#define STM32_RTC_DR 0x04 -#define STM32_RTC_CR 0x08 -#define STM32_RTC_ISR 0x0C -#define STM32_RTC_PRER 0x10 -#define STM32_RTC_ALRMAR 0x1C -#define STM32_RTC_WPR 0x24 - /* STM32_RTC_TR bit fields */ #define STM32_RTC_TR_SEC_SHIFT 0 #define STM32_RTC_TR_SEC GENMASK(6, 0) @@ -85,7 +76,26 @@ #define RTC_WPR_2ND_KEY 0x53 #define RTC_WPR_WRONG_KEY 0xFF +struct stm32_rtc; + +struct stm32_rtc_registers { + u8 tr; + u8 dr; + u8 cr; + u8 isr; + u8 prer; + u8 alrmar; + u8 wpr; +}; + +struct stm32_rtc_events { + u32 alra; +}; + struct stm32_rtc_data { + const struct stm32_rtc_registers regs; + const struct stm32_rtc_events events; + void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags); bool has_pclk; bool need_dbp; }; @@ -96,30 +106,35 @@ struct stm32_rtc { struct regmap *dbp; unsigned int dbp_reg; unsigned int dbp_mask; - struct stm32_rtc_data *data; struct clk *pclk; struct clk *rtc_ck; + const struct stm32_rtc_data *data; int irq_alarm; }; static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) { - writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR); - writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + + writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + regs->wpr); + writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + regs->wpr); } static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc) { - writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + + writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr); } static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) { - unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + unsigned int isr = readl_relaxed(rtc->base + regs->isr); if (!(isr & STM32_RTC_ISR_INITF)) { isr |= STM32_RTC_ISR_INIT; - writel_relaxed(isr, rtc->base + STM32_RTC_ISR); + writel_relaxed(isr, rtc->base + regs->isr); /* * It takes around 2 rtc_ck clock cycles to enter in @@ -128,7 +143,7 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) * 1MHz, we poll every 10 us with a timeout of 100ms. */ return readl_relaxed_poll_timeout_atomic( - rtc->base + STM32_RTC_ISR, + rtc->base + regs->isr, isr, (isr & STM32_RTC_ISR_INITF), 10, 100000); } @@ -138,40 +153,50 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc) { - unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + unsigned int isr = readl_relaxed(rtc->base + regs->isr); isr &= ~STM32_RTC_ISR_INIT; - writel_relaxed(isr, rtc->base + STM32_RTC_ISR); + writel_relaxed(isr, rtc->base + regs->isr); } static int stm32_rtc_wait_sync(struct stm32_rtc *rtc) { - unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + unsigned int isr = readl_relaxed(rtc->base + regs->isr); isr &= ~STM32_RTC_ISR_RSF; - writel_relaxed(isr, rtc->base + STM32_RTC_ISR); + writel_relaxed(isr, rtc->base + regs->isr); /* * Wait for RSF to be set to ensure the calendar registers are * synchronised, it takes around 2 rtc_ck clock cycles */ - return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR, + return readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr, isr, (isr & STM32_RTC_ISR_RSF), 10, 100000); } +static void stm32_rtc_clear_event_flags(struct stm32_rtc *rtc, + unsigned int flags) +{ + rtc->data->clear_events(rtc, flags); +} + static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) { struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id; - unsigned int isr, cr; + const struct stm32_rtc_registers *regs = &rtc->data->regs; + const struct stm32_rtc_events *evts = &rtc->data->events; + unsigned int status, cr; mutex_lock(&rtc->rtc_dev->ops_lock); - isr = readl_relaxed(rtc->base + STM32_RTC_ISR); - cr = readl_relaxed(rtc->base + STM32_RTC_CR); + status = readl_relaxed(rtc->base + regs->isr); + cr = readl_relaxed(rtc->base + regs->cr); - if ((isr & STM32_RTC_ISR_ALRAF) && + if ((status & evts->alra) && (cr & STM32_RTC_CR_ALRAIE)) { /* Alarm A flag - Alarm interrupt */ dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n"); @@ -179,9 +204,8 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) /* Pass event to the kernel */ rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); - /* Clear event flag, otherwise new events won't be received */ - writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF, - rtc->base + STM32_RTC_ISR); + /* Clear event flags, otherwise new events won't be received */ + stm32_rtc_clear_event_flags(rtc, evts->alra); } mutex_unlock(&rtc->rtc_dev->ops_lock); @@ -228,11 +252,12 @@ static void bcd2tm(struct rtc_time *tm) static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct stm32_rtc *rtc = dev_get_drvdata(dev); + const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int tr, dr; /* Time and Date in BCD format */ - tr = readl_relaxed(rtc->base + STM32_RTC_TR); - dr = readl_relaxed(rtc->base + STM32_RTC_DR); + tr = readl_relaxed(rtc->base + regs->tr); + dr = readl_relaxed(rtc->base + regs->dr); tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT; tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT; @@ -253,6 +278,7 @@ static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm) static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct stm32_rtc *rtc = dev_get_drvdata(dev); + const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int tr, dr; int ret = 0; @@ -277,8 +303,8 @@ static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm) goto end; } - writel_relaxed(tr, rtc->base + STM32_RTC_TR); - writel_relaxed(dr, rtc->base + STM32_RTC_DR); + writel_relaxed(tr, rtc->base + regs->tr); + writel_relaxed(dr, rtc->base + regs->dr); stm32_rtc_exit_init_mode(rtc); @@ -292,12 +318,14 @@ end: static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct stm32_rtc *rtc = dev_get_drvdata(dev); + const struct stm32_rtc_registers *regs = &rtc->data->regs; + const struct stm32_rtc_events *evts = &rtc->data->events; struct rtc_time *tm = &alrm->time; - unsigned int alrmar, cr, isr; + unsigned int alrmar, cr, status; - alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR); - cr = readl_relaxed(rtc->base + STM32_RTC_CR); - isr = readl_relaxed(rtc->base + STM32_RTC_ISR); + alrmar = readl_relaxed(rtc->base + regs->alrmar); + cr = readl_relaxed(rtc->base + regs->cr); + status = readl_relaxed(rtc->base + regs->isr); if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) { /* @@ -350,7 +378,7 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) bcd2tm(tm); alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0; - alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0; + alrm->pending = (status & evts->alra) ? 1 : 0; return 0; } @@ -358,9 +386,11 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct stm32_rtc *rtc = dev_get_drvdata(dev); - unsigned int isr, cr; + const struct stm32_rtc_registers *regs = &rtc->data->regs; + const struct stm32_rtc_events *evts = &rtc->data->events; + unsigned int cr; - cr = readl_relaxed(rtc->base + STM32_RTC_CR); + cr = readl_relaxed(rtc->base + regs->cr); stm32_rtc_wpr_unlock(rtc); @@ -369,12 +399,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE); else cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE); - writel_relaxed(cr, rtc->base + STM32_RTC_CR); + writel_relaxed(cr, rtc->base + regs->cr); - /* Clear event flag, otherwise new events won't be received */ - isr = readl_relaxed(rtc->base + STM32_RTC_ISR); - isr &= ~STM32_RTC_ISR_ALRAF; - writel_relaxed(isr, rtc->base + STM32_RTC_ISR); + /* Clear event flags, otherwise new events won't be received */ + stm32_rtc_clear_event_flags(rtc, evts->alra); stm32_rtc_wpr_lock(rtc); @@ -383,9 +411,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm) { + const struct stm32_rtc_registers *regs = &rtc->data->regs; int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec; - unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR); - unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR); + unsigned int dr = readl_relaxed(rtc->base + regs->dr); + unsigned int tr = readl_relaxed(rtc->base + regs->tr); cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT; cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT; @@ -419,6 +448,7 @@ static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm) static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct stm32_rtc *rtc = dev_get_drvdata(dev); + const struct stm32_rtc_registers *regs = &rtc->data->regs; struct rtc_time *tm = &alrm->time; unsigned int cr, isr, alrmar; int ret = 0; @@ -450,15 +480,15 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) stm32_rtc_wpr_unlock(rtc); /* Disable Alarm */ - cr = readl_relaxed(rtc->base + STM32_RTC_CR); + cr = readl_relaxed(rtc->base + regs->cr); cr &= ~STM32_RTC_CR_ALRAE; - writel_relaxed(cr, rtc->base + STM32_RTC_CR); + writel_relaxed(cr, rtc->base + regs->cr); /* * Poll Alarm write flag to be sure that Alarm update is allowed: it * takes around 2 rtc_ck clock cycles */ - ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR, + ret = readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr, isr, (isr & STM32_RTC_ISR_ALRAWF), 10, 100000); @@ -469,7 +499,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) } /* Write to Alarm register */ - writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR); + writel_relaxed(alrmar, rtc->base + regs->alrmar); if (alrm->enabled) stm32_rtc_alarm_irq_enable(dev, 1); @@ -490,14 +520,50 @@ static const struct rtc_class_ops stm32_rtc_ops = { .alarm_irq_enable = stm32_rtc_alarm_irq_enable, }; +static void stm32_rtc_clear_events(struct stm32_rtc *rtc, + unsigned int flags) +{ + const struct stm32_rtc_registers *regs = &rtc->data->regs; + + /* Flags are cleared by writing 0 in RTC_ISR */ + writel_relaxed(readl_relaxed(rtc->base + regs->isr) & ~flags, + rtc->base + regs->isr); +} + static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, + .regs = { + .tr = 0x00, + .dr = 0x04, + .cr = 0x08, + .isr = 0x0C, + .prer = 0x10, + .alrmar = 0x1C, + .wpr = 0x24, + }, + .events = { + .alra = STM32_RTC_ISR_ALRAF, + }, + .clear_events = stm32_rtc_clear_events, }; static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, + .regs = { + .tr = 0x00, + .dr = 0x04, + .cr = 0x08, + .isr = 0x0C, + .prer = 0x10, + .alrmar = 0x1C, + .wpr = 0x24, + }, + .events = { + .alra = STM32_RTC_ISR_ALRAF, + }, + .clear_events = stm32_rtc_clear_events, }; static const struct of_device_id stm32_rtc_of_match[] = { @@ -510,6 +576,7 @@ MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); static int stm32_rtc_init(struct platform_device *pdev, struct stm32_rtc *rtc) { + const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr; unsigned int rate; int ret = 0; @@ -550,14 +617,14 @@ static int stm32_rtc_init(struct platform_device *pdev, } prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S; - writel_relaxed(prer, rtc->base + STM32_RTC_PRER); + writel_relaxed(prer, rtc->base + regs->prer); prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A; - writel_relaxed(prer, rtc->base + STM32_RTC_PRER); + writel_relaxed(prer, rtc->base + regs->prer); /* Force 24h time format */ - cr = readl_relaxed(rtc->base + STM32_RTC_CR); + cr = readl_relaxed(rtc->base + regs->cr); cr &= ~STM32_RTC_CR_FMT; - writel_relaxed(cr, rtc->base + STM32_RTC_CR); + writel_relaxed(cr, rtc->base + regs->cr); stm32_rtc_exit_init_mode(rtc); @@ -571,6 +638,7 @@ end: static int stm32_rtc_probe(struct platform_device *pdev) { struct stm32_rtc *rtc; + const struct stm32_rtc_registers *regs; struct resource *res; int ret; @@ -585,6 +653,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) rtc->data = (struct stm32_rtc_data *) of_device_get_match_data(&pdev->dev); + regs = &rtc->data->regs; if (rtc->data->need_dbp) { rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, @@ -688,7 +757,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) * If INITS flag is reset (calendar year field set to 0x00), calendar * must be initialized */ - if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS)) + if (!(readl_relaxed(rtc->base + regs->isr) & STM32_RTC_ISR_INITS)) dev_warn(&pdev->dev, "Date/Time must be initialized\n"); return 0; @@ -708,13 +777,14 @@ err: static int stm32_rtc_remove(struct platform_device *pdev) { struct stm32_rtc *rtc = platform_get_drvdata(pdev); + const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int cr; /* Disable interrupts */ stm32_rtc_wpr_unlock(rtc); - cr = readl_relaxed(rtc->base + STM32_RTC_CR); + cr = readl_relaxed(rtc->base + regs->cr); cr &= ~STM32_RTC_CR_ALRAIE; - writel_relaxed(cr, rtc->base + STM32_RTC_CR); + writel_relaxed(cr, rtc->base + regs->cr); stm32_rtc_wpr_lock(rtc); clk_disable_unprepare(rtc->rtc_ck); -- cgit v1.2.3 From b72252b6580c9c7ad74644642378e2a9a86b2283 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:26 +0200 Subject: rtc: stm32: add stm32mp1 rtc support This patch adds support for stm32mp1 RTC. Some common registers with previous RTC version have a different offset. It is the case for Control Register (CR) and ALaRMA Register (ALRMAR). There are also new registers regarding event flags: now, Alarm event flag is in Status Register (SR) and write 1 in Status Clear Register (SCR) is required to clear the event. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 103 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 8254e38ec7cf..c5908cfea234 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,7 @@ #define STM32_RTC_CR_ALRAE BIT(8) #define STM32_RTC_CR_ALRAIE BIT(12) -/* STM32_RTC_ISR bit fields */ +/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */ #define STM32_RTC_ISR_ALRAWF BIT(0) #define STM32_RTC_ISR_INITS BIT(4) #define STM32_RTC_ISR_RSF BIT(5) @@ -71,21 +72,36 @@ #define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24) #define STM32_RTC_ALRMXR_DATE_MASK BIT(31) +/* STM32_RTC_SR/_SCR bit fields */ +#define STM32_RTC_SR_ALRA BIT(0) + +/* STM32_RTC_VERR bit fields */ +#define STM32_RTC_VERR_MINREV_SHIFT 0 +#define STM32_RTC_VERR_MINREV GENMASK(3, 0) +#define STM32_RTC_VERR_MAJREV_SHIFT 4 +#define STM32_RTC_VERR_MAJREV GENMASK(7, 4) + /* STM32_RTC_WPR key constants */ #define RTC_WPR_1ST_KEY 0xCA #define RTC_WPR_2ND_KEY 0x53 #define RTC_WPR_WRONG_KEY 0xFF +/* Max STM32 RTC register offset is 0x3FC */ +#define UNDEF_REG 0xFFFF + struct stm32_rtc; struct stm32_rtc_registers { - u8 tr; - u8 dr; - u8 cr; - u8 isr; - u8 prer; - u8 alrmar; - u8 wpr; + u16 tr; + u16 dr; + u16 cr; + u16 isr; + u16 prer; + u16 alrmar; + u16 wpr; + u16 sr; + u16 scr; + u16 verr; }; struct stm32_rtc_events { @@ -98,6 +114,7 @@ struct stm32_rtc_data { void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags); bool has_pclk; bool need_dbp; + bool has_wakeirq; }; struct stm32_rtc { @@ -110,6 +127,7 @@ struct stm32_rtc { struct clk *rtc_ck; const struct stm32_rtc_data *data; int irq_alarm; + int wakeirq_alarm; }; static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) @@ -193,7 +211,7 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) mutex_lock(&rtc->rtc_dev->ops_lock); - status = readl_relaxed(rtc->base + regs->isr); + status = readl_relaxed(rtc->base + regs->sr); cr = readl_relaxed(rtc->base + regs->cr); if ((status & evts->alra) && @@ -325,7 +343,7 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrmar = readl_relaxed(rtc->base + regs->alrmar); cr = readl_relaxed(rtc->base + regs->cr); - status = readl_relaxed(rtc->base + regs->isr); + status = readl_relaxed(rtc->base + regs->sr); if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) { /* @@ -533,6 +551,7 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc, static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, + .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -541,6 +560,9 @@ static const struct stm32_rtc_data stm32_rtc_data = { .prer = 0x10, .alrmar = 0x1C, .wpr = 0x24, + .sr = 0x0C, /* set to ISR offset to ease alarm management */ + .scr = UNDEF_REG, + .verr = UNDEF_REG, }, .events = { .alra = STM32_RTC_ISR_ALRAF, @@ -551,6 +573,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, + .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -559,6 +582,9 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .prer = 0x10, .alrmar = 0x1C, .wpr = 0x24, + .sr = 0x0C, /* set to ISR offset to ease alarm management */ + .scr = UNDEF_REG, + .verr = UNDEF_REG, }, .events = { .alra = STM32_RTC_ISR_ALRAF, @@ -566,9 +592,41 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .clear_events = stm32_rtc_clear_events, }; +static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc, + unsigned int flags) +{ + struct stm32_rtc_registers regs = rtc->data->regs; + + /* Flags are cleared by writing 1 in RTC_SCR */ + writel_relaxed(flags, rtc->base + regs.scr); +} + +static const struct stm32_rtc_data stm32mp1_data = { + .has_pclk = true, + .need_dbp = false, + .has_wakeirq = true, + .regs = { + .tr = 0x00, + .dr = 0x04, + .cr = 0x18, + .isr = 0x0C, /* named RTC_ICSR on stm32mp1 */ + .prer = 0x10, + .alrmar = 0x40, + .wpr = 0x24, + .sr = 0x50, + .scr = 0x5C, + .verr = 0x3F4, + }, + .events = { + .alra = STM32_RTC_SR_ALRA, + }, + .clear_events = stm32mp1_rtc_clear_events, +}; + static const struct of_device_id stm32_rtc_of_match[] = { { .compatible = "st,stm32-rtc", .data = &stm32_rtc_data }, { .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data }, + { .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data }, {} }; MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); @@ -727,12 +785,19 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } - platform_set_drvdata(pdev, rtc); - ret = device_init_wakeup(&pdev->dev, true); + if (rtc->data->has_wakeirq) { + rtc->wakeirq_alarm = platform_get_irq(pdev, 1); + if (rtc->wakeirq_alarm <= 0) + ret = rtc->wakeirq_alarm; + else + ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, + rtc->wakeirq_alarm); + } if (ret) - dev_warn(&pdev->dev, - "alarm won't be able to wake up the system"); + dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret); + + platform_set_drvdata(pdev, rtc); rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, &stm32_rtc_ops, THIS_MODULE); @@ -760,6 +825,14 @@ static int stm32_rtc_probe(struct platform_device *pdev) if (!(readl_relaxed(rtc->base + regs->isr) & STM32_RTC_ISR_INITS)) dev_warn(&pdev->dev, "Date/Time must be initialized\n"); + if (regs->verr != UNDEF_REG) { + u32 ver = readl_relaxed(rtc->base + regs->verr); + + dev_info(&pdev->dev, "registered rev:%d.%d\n", + (ver >> STM32_RTC_VERR_MAJREV_SHIFT) & 0xF, + (ver >> STM32_RTC_VERR_MINREV_SHIFT) & 0xF); + } + return 0; err: if (rtc->data->has_pclk) @@ -769,6 +842,7 @@ err: if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); + dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); return ret; @@ -795,6 +869,7 @@ static int stm32_rtc_remove(struct platform_device *pdev) if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); + dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); return 0; -- cgit v1.2.3 From d482510fee9957ffaca3a0357c655628f3e3870b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 20 May 2018 14:33:36 +0200 Subject: rtc: st-lpc: 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: Patrice Chotard Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-st-lpc.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index d5222667f892..2f1ef2c28740 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -212,6 +212,10 @@ static int st_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; + rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + spin_lock_init(&rtc->lock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -253,26 +257,17 @@ static int st_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = rtc_device_register("st-lpc-rtc", &pdev->dev, - &st_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc_dev)) { + rtc->rtc_dev->ops = &st_rtc_ops; + + ret = rtc_register_device(rtc->rtc_dev); + if (ret) { clk_disable_unprepare(rtc->clk); - return PTR_ERR(rtc->rtc_dev); + return ret; } return 0; } -static int st_rtc_remove(struct platform_device *pdev) -{ - struct st_rtc *rtc = platform_get_drvdata(pdev); - - if (likely(rtc->rtc_dev)) - rtc_device_unregister(rtc->rtc_dev); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int st_rtc_suspend(struct device *dev) { @@ -325,7 +320,6 @@ static struct platform_driver st_rtc_platform_driver = { .of_match_table = st_rtc_match, }, .probe = st_rtc_probe, - .remove = st_rtc_remove, }; module_platform_driver(st_rtc_platform_driver); -- cgit v1.2.3 From b64c984ac8c0806e8fee608d4e1d33d2e7f6fb0f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 21 May 2018 22:49:05 +0200 Subject: rtc: st-lpc: add range The RTC has a 64 bit counter. Signed-off-by: Alexandre Belloni Acked-by: Patrice Chotard Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-st-lpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 2f1ef2c28740..bee75ca7ff79 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -258,6 +258,8 @@ static int st_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); rtc->rtc_dev->ops = &st_rtc_ops; + rtc->rtc_dev->range_max = U64_MAX; + do_div(rtc->rtc_dev->range_max, rtc->clkrate); ret = rtc_register_device(rtc->rtc_dev); if (ret) { -- cgit v1.2.3 From 784176820007fac4b3448986f19d69589d00479a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 26 May 2018 03:57:29 +0200 Subject: rtc: test: remove obsolete .set_mmss There is no point in testing .set_mmss versus .set_mmss64 as there are both taking the exact same argument (truncated for set_mmss though). Also, this allows to constify struct rtc_ops. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 390f928fd6fc..a0d1571c4af6 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -13,10 +13,6 @@ #include #include -static int test_mmss64; -module_param(test_mmss64, int, 0644); -MODULE_PARM_DESC(test_mmss64, "Test struct rtc_class_ops.set_mmss64()."); - static struct platform_device *test0 = NULL, *test1 = NULL; static int test_rtc_read_alarm(struct device *dev, @@ -44,12 +40,6 @@ static int test_rtc_set_mmss64(struct device *dev, time64_t secs) return 0; } -static int test_rtc_set_mmss(struct device *dev, unsigned long secs) -{ - dev_info(dev, "%s, secs = %lu\n", __func__, secs); - return 0; -} - static int test_rtc_proc(struct device *dev, struct seq_file *seq) { struct platform_device *plat_dev = to_platform_device(dev); @@ -65,12 +55,12 @@ static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) return 0; } -static struct rtc_class_ops test_rtc_ops = { +static const struct rtc_class_ops test_rtc_ops = { .proc = test_rtc_proc, .read_time = test_rtc_read_time, .read_alarm = test_rtc_read_alarm, .set_alarm = test_rtc_set_alarm, - .set_mmss = test_rtc_set_mmss, + .set_mmss64 = test_rtc_set_mmss64, .alarm_irq_enable = test_rtc_alarm_irq_enable, }; @@ -110,11 +100,6 @@ static int test_probe(struct platform_device *plat_dev) int err; struct rtc_device *rtc; - if (test_mmss64) { - test_rtc_ops.set_mmss64 = test_rtc_set_mmss64; - test_rtc_ops.set_mmss = NULL; - } - rtc = devm_rtc_device_register(&plat_dev->dev, "test", &test_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { -- cgit v1.2.3 From b9ef86084d822ba6aecf59df6abc78e5bec67c9a Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Wed, 23 May 2018 21:58:14 +0200 Subject: rtc: jz4740: Fix a typo in Kconfig Fix typo introduced for RTC_DRV_JZ4740 in commit 586655d278ba ("rtc: jz4740: make the driver buildable as a module again"). Signed-off-by: Mathieu Malaterre Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 59e6dede3db3..a2ba5db36145 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1613,7 +1613,7 @@ config RTC_DRV_JZ4740 If you say yes here you get support for the Ingenic JZ47xx SoCs RTC controllers. - This driver can also be buillt as a module. If so, the module + This driver can also be built as a module. If so, the module will be called rtc-jz4740. config RTC_DRV_LPC24XX -- cgit v1.2.3 From 09018d4bd7994c2c9f775029bc24589bc85f76fa Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Wed, 30 May 2018 23:57:44 +0530 Subject: rtc: sun6i: Fix bit_idx value for clk_register_gate clk-gate core will take bit_idx through clk_register_gate and then do clk_gate_ops by using BIT(bit_idx), but rtc-sun6i is passing bit_idx as BIT(bit_idx) it becomes BIT(BIT(bit_idx) which is wrong and eventually external gate clock is not enabling. This patch fixed by passing bit index and the original change introduced from below commit. "rtc: sun6i: Add support for the external oscillator gate" (sha1: 17ecd246414b3a0fe0cb248c86977a8bda465b7b) Signed-off-by: Michael Trimarchi Fixes: 17ecd246414b ("rtc: sun6i: Add support for the external oscillator gate") Cc: stable@vger.kernel.org Signed-off-by: Jagan Teki Acked-by: Maxime Ripard Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sun6i.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 2e6fb275acc8..2cd5a7b1a2e3 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -74,7 +74,7 @@ #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) #define SUN6I_LOSC_OUT_GATING 0x0060 -#define SUN6I_LOSC_OUT_GATING_EN BIT(0) +#define SUN6I_LOSC_OUT_GATING_EN_OFFSET 0 /* * Get date values @@ -255,7 +255,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) &clkout_name); rtc->ext_losc = clk_register_gate(NULL, clkout_name, rtc->hw.init->name, 0, rtc->base + SUN6I_LOSC_OUT_GATING, - SUN6I_LOSC_OUT_GATING_EN, 0, + SUN6I_LOSC_OUT_GATING_EN_OFFSET, 0, &rtc->lock); if (IS_ERR(rtc->ext_losc)) { pr_crit("Couldn't register the LOSC external gate\n"); -- cgit v1.2.3 From a0defd7cfc2804796144545e00aaf74a486adbe7 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 31 May 2018 17:18:08 +0800 Subject: rtc: sprd: Add new RTC power down check method We should use the new method to check if RTC was powered down, which is more solid. Since we have introduced power control and power status registers, and we just check if the power status is the default value (0x96), if yes that means the RTC has been powered down. Meanwhile We can set the power control register to be one valid value to change the power status to indicate RTC device is valid now. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index 6a3876edd8e0..deea5c3726ad 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -35,6 +35,8 @@ #define SPRD_RTC_DAY_ALM_VALUE 0x4c #define SPRD_RTC_SPG_VALUE 0x50 #define SPRD_RTC_SPG_UPD 0x54 +#define SPRD_RTC_PWR_CTRL 0x58 +#define SPRD_RTC_PWR_STS 0x5c #define SPRD_RTC_SEC_AUXALM_UPD 0x60 #define SPRD_RTC_MIN_AUXALM_UPD 0x64 #define SPRD_RTC_HOUR_AUXALM_UPD 0x68 @@ -86,7 +88,13 @@ /* SPG values definition for SPRD_RTC_SPG_UPD register */ #define SPRD_RTC_POWEROFF_ALM_FLAG BIT(8) -#define SPRD_RTC_POWER_RESET_FLAG BIT(9) + +/* power control/status definition */ +#define SPRD_RTC_POWER_RESET_VALUE 0x96 +#define SPRD_RTC_POWER_STS_CLEAR GENMASK(7, 0) +#define SPRD_RTC_POWER_STS_SHIFT 8 +#define SPRD_RTC_POWER_STS_VALID \ + (~SPRD_RTC_POWER_RESET_VALUE << SPRD_RTC_POWER_STS_SHIFT) /* timeout of synchronizing time and alarm registers (us) */ #define SPRD_RTC_POLL_TIMEOUT 200000 @@ -383,7 +391,6 @@ static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct sprd_rtc *rtc = dev_get_drvdata(dev); time64_t secs = rtc_tm_to_time64(tm); - u32 val; int ret; ret = sprd_rtc_set_secs(rtc, SPRD_RTC_TIME, secs); @@ -391,27 +398,20 @@ static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; if (!rtc->valid) { - /* - * Set SPRD_RTC_POWER_RESET_FLAG to indicate now RTC has valid - * time values. - */ - ret = regmap_update_bits(rtc->regmap, - rtc->base + SPRD_RTC_SPG_UPD, - SPRD_RTC_POWER_RESET_FLAG, - SPRD_RTC_POWER_RESET_FLAG); + /* Clear RTC power status firstly */ + ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL, + SPRD_RTC_POWER_STS_CLEAR); if (ret) return ret; - ret = regmap_read_poll_timeout(rtc->regmap, - rtc->base + SPRD_RTC_INT_RAW_STS, - val, (val & SPRD_RTC_SPG_UPD_EN), - SPRD_RTC_POLL_DELAY_US, - SPRD_RTC_POLL_TIMEOUT); - if (ret) { - dev_err(rtc->dev, "failed to update SPG value:%d\n", - ret); + /* + * Set RTC power status to indicate now RTC has valid time + * values. + */ + ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL, + SPRD_RTC_POWER_STS_VALID); + if (ret) return ret; - } rtc->valid = true; } @@ -562,15 +562,16 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc) u32 val; int ret; - ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val); + ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_PWR_STS, &val); if (ret) return ret; /* - * If the SPRD_RTC_POWER_RESET_FLAG was not set, which means the RTC has - * been powered down, so the RTC time values are invalid. + * If the RTC power status value is SPRD_RTC_POWER_RESET_VALUE, which + * means the RTC has been powered down, so the RTC time values are + * invalid. */ - rtc->valid = (val & SPRD_RTC_POWER_RESET_FLAG) ? true : false; + rtc->valid = val == SPRD_RTC_POWER_RESET_VALUE ? false : true; return 0; } -- cgit v1.2.3 From a2ae8323a8e2c5668ae42493d925da1d68ff0324 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 11:56:42 +0200 Subject: rtc: ds1685: 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. 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-ds1685.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index f0f8011dce3d..e6390475380f 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -2037,6 +2037,22 @@ ds1685_rtc_probe(struct platform_device *pdev) rtc->write(rtc, RTC_EXT_CTRL_4B, (rtc->read(rtc, RTC_EXT_CTRL_4B) | RTC_CTRL_4B_KSE)); + rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); + + rtc_dev->ops = &ds1685_rtc_ops; + + /* Maximum periodic rate is 8192Hz (0.122070ms). */ + rtc_dev->max_user_freq = RTC_MAX_USER_FREQ; + + /* See if the platform doesn't support UIE. */ + if (pdata->uie_unsupported) + rtc_dev->uie_unsupported = 1; + rtc->uie_unsupported = pdata->uie_unsupported; + + rtc->dev = rtc_dev; + /* * Fetch the IRQ and setup the interrupt handler. * @@ -2069,32 +2085,13 @@ ds1685_rtc_probe(struct platform_device *pdev) /* Setup complete. */ ds1685_rtc_switch_to_bank0(rtc); - /* Register the device as an RTC. */ - rtc_dev = rtc_device_register(pdev->name, &pdev->dev, - &ds1685_rtc_ops, THIS_MODULE); - - /* Success? */ - if (IS_ERR(rtc_dev)) - return PTR_ERR(rtc_dev); - - /* Maximum periodic rate is 8192Hz (0.122070ms). */ - rtc_dev->max_user_freq = RTC_MAX_USER_FREQ; - - /* See if the platform doesn't support UIE. */ - if (pdata->uie_unsupported) - rtc_dev->uie_unsupported = 1; - rtc->uie_unsupported = pdata->uie_unsupported; - - rtc->dev = rtc_dev; - #ifdef CONFIG_SYSFS ret = ds1685_rtc_sysfs_register(&pdev->dev); if (ret) - rtc_device_unregister(rtc->dev); + return ret; #endif - /* Done! */ - return ret; + return rtc_register_device(rtc_dev); } /** @@ -2110,8 +2107,6 @@ ds1685_rtc_remove(struct platform_device *pdev) ds1685_rtc_sysfs_unregister(&pdev->dev); #endif - rtc_device_unregister(rtc->dev); - /* Read Ctrl B and clear PIE/AIE/UIE. */ rtc->write(rtc, RTC_CTRL_B, (rtc->read(rtc, RTC_CTRL_B) & -- cgit v1.2.3 From c36b52ed18c2b3d84b26cf8bedca0f6649aeb2b8 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 11:56:43 +0200 Subject: rtc: ds1685: Add range Useful range is 2000-2099 because leap year fails on centuries. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1685.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index e6390475380f..5c0db6c8134c 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -2043,6 +2043,10 @@ ds1685_rtc_probe(struct platform_device *pdev) rtc_dev->ops = &ds1685_rtc_ops; + /* Century bit is useless because leap year fails in 1900 and 2100 */ + rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc_dev->range_max = RTC_TIMESTAMP_END_2099; + /* Maximum periodic rate is 8192Hz (0.122070ms). */ rtc_dev->max_user_freq = RTC_MAX_USER_FREQ; -- cgit v1.2.3 From 9394270ef9ce455b84f896a0060423019834a0e3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 23:09:55 +0200 Subject: rtc: test: remove useless proc info The rtc proc callback is useless for two reasosn: - the test RTC is often not the first RTC so it will never be used - all the info is available in the name file of the RTC sys folder Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index a0d1571c4af6..f0eb8e0c5055 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -40,23 +40,12 @@ static int test_rtc_set_mmss64(struct device *dev, time64_t secs) return 0; } -static int test_rtc_proc(struct device *dev, struct seq_file *seq) -{ - struct platform_device *plat_dev = to_platform_device(dev); - - seq_printf(seq, "test\t\t: yes\n"); - seq_printf(seq, "id\t\t: %d\n", plat_dev->id); - - return 0; -} - static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) { return 0; } static const struct rtc_class_ops test_rtc_ops = { - .proc = test_rtc_proc, .read_time = test_rtc_read_time, .read_alarm = test_rtc_read_alarm, .set_alarm = test_rtc_set_alarm, -- cgit v1.2.3 From 5b257571cd487bf3f5779b2b4b15216cc5eb7bb6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 23:09:56 +0200 Subject: rtc: test: allow registering many devices Use a loop to register RTC devices Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index f0eb8e0c5055..796c45dee661 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -13,7 +13,9 @@ #include #include -static struct platform_device *test0 = NULL, *test1 = NULL; +#define MAX_RTC_TEST 3 + +struct platform_device *pdev[MAX_RTC_TEST]; static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) @@ -122,47 +124,45 @@ static struct platform_driver test_driver = { static int __init test_init(void) { - int err; + int i, err; if ((err = platform_driver_register(&test_driver))) return err; - if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { - err = -ENOMEM; - goto exit_driver_unregister; + err = -ENOMEM; + for (i = 0; i < MAX_RTC_TEST; i++) { + pdev[i] = platform_device_alloc("rtc-test", i); + if (!pdev[i]) + goto exit_free_mem; } - if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { - err = -ENOMEM; - goto exit_put_test0; + for (i = 0; i < MAX_RTC_TEST; i++) { + err = platform_device_add(pdev[i]); + if (err) + goto exit_device_del; } - if ((err = platform_device_add(test0))) - goto exit_put_test1; - - if ((err = platform_device_add(test1))) - goto exit_del_test0; - return 0; -exit_del_test0: - platform_device_del(test0); +exit_device_del: + for (; i > 0; i--) + platform_device_del(pdev[i - 1]); -exit_put_test1: - platform_device_put(test1); +exit_free_mem: + for (i = 0; i < MAX_RTC_TEST; i++) + platform_device_put(pdev[i]); -exit_put_test0: - platform_device_put(test0); - -exit_driver_unregister: platform_driver_unregister(&test_driver); return err; } static void __exit test_exit(void) { - platform_device_unregister(test0); - platform_device_unregister(test1); + int i; + + for (i = 0; i < MAX_RTC_TEST; i++) + platform_device_unregister(pdev[i]); + platform_driver_unregister(&test_driver); } -- cgit v1.2.3 From 4dc2403bed0dbc18d90cc637337eebfc1e939c72 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 23:09:57 +0200 Subject: rtc: test: store time as an offset to system time Store the time as an offset to system time. As the offset is in second, it is currently always synced with system time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 796c45dee661..f50b3321314f 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -15,6 +15,11 @@ #define MAX_RTC_TEST 3 +struct rtc_test_data { + struct rtc_device *rtc; + time64_t offset; +}; + struct platform_device *pdev[MAX_RTC_TEST]; static int test_rtc_read_alarm(struct device *dev, @@ -29,16 +34,21 @@ static int test_rtc_set_alarm(struct device *dev, return 0; } -static int test_rtc_read_time(struct device *dev, - struct rtc_time *tm) +static int test_rtc_read_time(struct device *dev, struct rtc_time *tm) { - rtc_time64_to_tm(ktime_get_real_seconds(), tm); + struct rtc_test_data *rtd = dev_get_drvdata(dev); + + rtc_time64_to_tm(ktime_get_real_seconds() + rtd->offset, tm); + return 0; } static int test_rtc_set_mmss64(struct device *dev, time64_t secs) { - dev_info(dev, "%s, secs = %lld\n", __func__, (long long)secs); + struct rtc_test_data *rtd = dev_get_drvdata(dev); + + rtd->offset = secs - ktime_get_real_seconds(); + return 0; } @@ -88,21 +98,18 @@ static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); static int test_probe(struct platform_device *plat_dev) { - int err; - struct rtc_device *rtc; + struct rtc_test_data *rtd; - rtc = devm_rtc_device_register(&plat_dev->dev, "test", - &test_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - return PTR_ERR(rtc); - } + rtd = devm_kzalloc(&plat_dev->dev, sizeof(*rtd), GFP_KERNEL); + if (!rtd) + return -ENOMEM; - err = device_create_file(&plat_dev->dev, &dev_attr_irq); - if (err) - dev_err(&plat_dev->dev, "Unable to create sysfs entry: %s\n", - dev_attr_irq.attr.name); + platform_set_drvdata(plat_dev, rtd); - platform_set_drvdata(plat_dev, rtc); + rtd->rtc = devm_rtc_device_register(&plat_dev->dev, "test", + &test_rtc_ops, THIS_MODULE); + if (IS_ERR(rtd->rtc)) + return PTR_ERR(rtd->rtc); return 0; } -- cgit v1.2.3 From 8be09029940227d30ae310bb3fe25bc8abbfe140 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 23:09:58 +0200 Subject: rtc: test: emulate alarms using timers Use timers to emulate alarms. Note that multiple alarms may happen if they are set more than 15 days after the current RTC time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index f50b3321314f..3aee7be3a58a 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -18,19 +18,49 @@ struct rtc_test_data { struct rtc_device *rtc; time64_t offset; + struct timer_list alarm; + bool alarm_en; }; struct platform_device *pdev[MAX_RTC_TEST]; -static int test_rtc_read_alarm(struct device *dev, - struct rtc_wkalrm *alrm) +static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct rtc_test_data *rtd = dev_get_drvdata(dev); + time64_t alarm; + + alarm = (rtd->alarm.expires - jiffies) / HZ; + alarm += ktime_get_real_seconds() + rtd->offset; + + rtc_time64_to_tm(alarm, &alrm->time); + alrm->enabled = rtd->alarm_en; + return 0; } -static int test_rtc_set_alarm(struct device *dev, - struct rtc_wkalrm *alrm) +static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct rtc_test_data *rtd = dev_get_drvdata(dev); + ktime_t timeout; + u64 expires; + + timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds(); + timeout -= rtd->offset; + + del_timer(&rtd->alarm); + + expires = jiffies + timeout * HZ; + if (expires > U32_MAX) + expires = U32_MAX; + + pr_err("ABE: %s +%d %s\n", __FILE__, __LINE__, __func__); + rtd->alarm.expires = expires; + + if (alrm->enabled) + add_timer(&rtd->alarm); + + rtd->alarm_en = alrm->enabled; + return 0; } @@ -54,6 +84,14 @@ static int test_rtc_set_mmss64(struct device *dev, time64_t secs) static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) { + struct rtc_test_data *rtd = dev_get_drvdata(dev); + + rtd->alarm_en = enable; + if (enable) + add_timer(&rtd->alarm); + else + del_timer(&rtd->alarm); + return 0; } @@ -65,6 +103,13 @@ static const struct rtc_class_ops test_rtc_ops = { .alarm_irq_enable = test_rtc_alarm_irq_enable, }; +static void test_rtc_alarm_handler(struct timer_list *t) +{ + struct rtc_test_data *rtd = from_timer(rtd, t, alarm); + + rtc_update_irq(rtd->rtc, 1, RTC_AF | RTC_IRQF); +} + static ssize_t test_irq_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -111,6 +156,9 @@ static int test_probe(struct platform_device *plat_dev) if (IS_ERR(rtd->rtc)) return PTR_ERR(rtd->rtc); + timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); + rtd->alarm.expires = 0; + return 0; } -- cgit v1.2.3 From 696fa1d043ecd605166cc97b24c0b7a59dd5a135 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 31 May 2018 23:09:59 +0200 Subject: rtc: test: remove irq sysfs file Now that alarms are emulated, remove the irq sysfs file that could be used to send alarms. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 3aee7be3a58a..70d4ab1d2769 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -110,37 +110,6 @@ static void test_rtc_alarm_handler(struct timer_list *t) rtc_update_irq(rtd->rtc, 1, RTC_AF | RTC_IRQF); } -static ssize_t test_irq_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", 42); -} -static ssize_t test_irq_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int retval; - struct rtc_device *rtc = dev_get_drvdata(dev); - - retval = count; - if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled) - rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF); - else if (strncmp(buf, "alarm", 5) == 0) { - struct rtc_wkalrm alrm; - int err = rtc_read_alarm(rtc, &alrm); - - if (!err && alrm.enabled) - rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); - - } else if (strncmp(buf, "update", 6) == 0 && rtc->uie_rtctimer.enabled) - rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF); - else - retval = -EINVAL; - - return retval; -} -static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); - static int test_probe(struct platform_device *plat_dev) { struct rtc_test_data *rtd; @@ -162,16 +131,8 @@ static int test_probe(struct platform_device *plat_dev) return 0; } -static int test_remove(struct platform_device *plat_dev) -{ - device_remove_file(&plat_dev->dev, &dev_attr_irq); - - return 0; -} - static struct platform_driver test_driver = { .probe = test_probe, - .remove = test_remove, .driver = { .name = "rtc-test", }, -- cgit v1.2.3 From 29615d03ccc0f8f01b45178737600810d8bf971f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 4 Jun 2018 14:05:40 +0200 Subject: rtc: sunxi: 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 Acked-by: Maxime Ripard Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sunxi.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index dadbf8b324ad..21865d3d8fe8 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -445,6 +445,10 @@ static int sunxi_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); chip->dev = &pdev->dev; + chip->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(chip->rtc)) + return PTR_ERR(chip->rtc); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); chip->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(chip->base)) @@ -481,11 +485,12 @@ static int sunxi_rtc_probe(struct platform_device *pdev) writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + SUNXI_ALRM_IRQ_STA); - chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev, - &sunxi_rtc_ops, THIS_MODULE); - if (IS_ERR(chip->rtc)) { + chip->rtc->ops = &sunxi_rtc_ops; + + ret = rtc_register_device(chip->rtc); + if (ret) { dev_err(&pdev->dev, "unable to register device\n"); - return PTR_ERR(chip->rtc); + return ret; } dev_info(&pdev->dev, "RTC enabled\n"); @@ -493,18 +498,8 @@ static int sunxi_rtc_probe(struct platform_device *pdev) return 0; } -static int sunxi_rtc_remove(struct platform_device *pdev) -{ - struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev); - - rtc_device_unregister(chip->rtc); - - return 0; -} - static struct platform_driver sunxi_rtc_driver = { .probe = sunxi_rtc_probe, - .remove = sunxi_rtc_remove, .driver = { .name = "sunxi-rtc", .of_match_table = sunxi_rtc_dt_ids, -- cgit v1.2.3 From 32b41f93dcaf240c4e8241b22dbba6f0dbf4de9d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 5 Jun 2018 16:18:17 +0200 Subject: rtc: mrst: switch to devm functions Switch to devm managed functions to simplify error handling and device removal Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mrst.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index fcb9de5218b2..097a4d4e2aba 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -45,7 +45,6 @@ struct mrst_rtc { struct rtc_device *rtc; struct device *dev; int irq; - struct resource *iomem; u8 enabled_wake; u8 suspend_ctrl; @@ -329,24 +328,22 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, if (!iomem) return -ENODEV; - iomem = request_mem_region(iomem->start, resource_size(iomem), - driver_name); + iomem = devm_request_mem_region(dev, iomem->start, resource_size(iomem), + driver_name); if (!iomem) { dev_dbg(dev, "i/o mem already in use.\n"); return -EBUSY; } mrst_rtc.irq = rtc_irq; - mrst_rtc.iomem = iomem; mrst_rtc.dev = dev; dev_set_drvdata(dev, &mrst_rtc); - mrst_rtc.rtc = rtc_device_register(driver_name, dev, - &mrst_rtc_ops, THIS_MODULE); - if (IS_ERR(mrst_rtc.rtc)) { - retval = PTR_ERR(mrst_rtc.rtc); - goto cleanup0; - } + mrst_rtc.rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(mrst_rtc.rtc)) + return PTR_ERR(mrst_rtc.rtc); + + mrst_rtc.rtc->ops = &mrst_rtc_ops; rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); @@ -359,23 +356,27 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); if (rtc_irq) { - retval = request_irq(rtc_irq, mrst_rtc_irq, - 0, dev_name(&mrst_rtc.rtc->dev), - mrst_rtc.rtc); + retval = devm_request_irq(dev, rtc_irq, mrst_rtc_irq, + 0, dev_name(&mrst_rtc.rtc->dev), + mrst_rtc.rtc); if (retval < 0) { dev_dbg(dev, "IRQ %d is already in use, err %d\n", rtc_irq, retval); - goto cleanup1; + goto cleanup0; } } + + retval = rtc_register_device(mrst_rtc.rtc); + if (retval) { + retval = PTR_ERR(mrst_rtc.rtc); + goto cleanup0; + } + dev_dbg(dev, "initialised\n"); return 0; -cleanup1: - rtc_device_unregister(mrst_rtc.rtc); cleanup0: mrst_rtc.dev = NULL; - release_mem_region(iomem->start, resource_size(iomem)); dev_err(dev, "rtc-mrst: unable to initialise\n"); return retval; } @@ -390,20 +391,10 @@ static void rtc_mrst_do_shutdown(void) static void rtc_mrst_do_remove(struct device *dev) { struct mrst_rtc *mrst = dev_get_drvdata(dev); - struct resource *iomem; rtc_mrst_do_shutdown(); - if (mrst->irq) - free_irq(mrst->irq, mrst->rtc); - - rtc_device_unregister(mrst->rtc); mrst->rtc = NULL; - - iomem = mrst->iomem; - release_mem_region(iomem->start, resource_size(iomem)); - mrst->iomem = NULL; - mrst->dev = NULL; } -- cgit v1.2.3 From e38d161f51982d56637d12eb9ad7e1f057be5202 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 4 Jun 2018 16:15:26 +0200 Subject: rtc: ftrtc010: switch to devm_rtc_allocate_device Switch to devm_rtc_allocate_device/rtc_register_device. This allow or further improvement and simplifies ftrtc010_rtc_remove(). Acked-by: Hans Ulli Kroll Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ftrtc010.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index af8d6beae20c..165d0b62db00 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c @@ -166,14 +166,18 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) if (!rtc->rtc_base) return -ENOMEM; + rtc->rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + + rtc->rtc_dev->ops = &ftrtc010_rtc_ops; + ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) return ret; - rtc->rtc_dev = rtc_device_register(pdev->name, dev, - &ftrtc010_rtc_ops, THIS_MODULE); - return PTR_ERR_OR_ZERO(rtc->rtc_dev); + return rtc_register_device(rtc->rtc_dev); } static int ftrtc010_rtc_remove(struct platform_device *pdev) @@ -184,7 +188,6 @@ static int ftrtc010_rtc_remove(struct platform_device *pdev) clk_disable_unprepare(rtc->extclk); if (!IS_ERR(rtc->pclk)) clk_disable_unprepare(rtc->pclk); - rtc_device_unregister(rtc->rtc_dev); return 0; } -- cgit v1.2.3 From 73318f8b6bf0dbdbff4f21a3fff02d1467479555 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 4 Jun 2018 16:15:27 +0200 Subject: rtc: ftrtc010: handle dates after 2106 Use correct types for offset and time and use rtc_time64_to_tm/rtc_tm_to_time64 to handle dates after 2106 properly. Acked-by: Hans Ulli Kroll Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ftrtc010.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index 165d0b62db00..2cdc78ffeb17 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c @@ -73,8 +73,8 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct ftrtc010_rtc *rtc = dev_get_drvdata(dev); - unsigned int days, hour, min, sec; - unsigned long offset, time; + u32 days, hour, min, sec, offset; + timeu64_t time; sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE); @@ -84,7 +84,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm) time = offset + days * 86400 + hour * 3600 + min * 60 + sec; - rtc_time_to_tm(time, tm); + rtc_time64_to_tm(time, tm); return 0; } @@ -92,13 +92,13 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm) static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct ftrtc010_rtc *rtc = dev_get_drvdata(dev); - unsigned int sec, min, hour, day; - unsigned long offset, time; + u32 sec, min, hour, day, offset; + timeu64_t time; if (tm->tm_year >= 2148) /* EPOCH Year + 179 */ return -EINVAL; - rtc_tm_to_time(tm, &time); + time = rtc_tm_to_time64(tm); sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE); -- cgit v1.2.3 From b8e62b58bc004391c68890ab0313317cff07fb6b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 4 Jun 2018 16:15:28 +0200 Subject: rtc: ftrtc010: let the core handle range The current range handling is highly suspicious. Anyway, let the core handle it. The RTC has a 32 bit counter on top of days + hh:mm:ss registers. Acked-by: Hans Ulli Kroll Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ftrtc010.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index 2cdc78ffeb17..61f798c6101f 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c @@ -95,9 +95,6 @@ static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm) u32 sec, min, hour, day, offset; timeu64_t time; - if (tm->tm_year >= 2148) /* EPOCH Year + 179 */ - return -EINVAL; - time = rtc_tm_to_time64(tm); sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); @@ -120,6 +117,7 @@ static const struct rtc_class_ops ftrtc010_rtc_ops = { static int ftrtc010_rtc_probe(struct platform_device *pdev) { + u32 days, hour, min, sec; struct ftrtc010_rtc *rtc; struct device *dev = &pdev->dev; struct resource *res; @@ -172,6 +170,15 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) rtc->rtc_dev->ops = &ftrtc010_rtc_ops; + sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); + min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE); + hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR); + days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS); + + rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + + min * 60 + sec; + rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min; + ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) -- cgit v1.2.3 From 0b472ad2999c3dea6f9968db7c2ebe150e7eac14 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 5 Jun 2018 23:09:12 +0200 Subject: rtc: test: convert to devm_rtc_allocate_device This allows further improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 70d4ab1d2769..0c30b04326c5 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -120,15 +120,16 @@ static int test_probe(struct platform_device *plat_dev) platform_set_drvdata(plat_dev, rtd); - rtd->rtc = devm_rtc_device_register(&plat_dev->dev, "test", - &test_rtc_ops, THIS_MODULE); + rtd->rtc = devm_rtc_allocate_device(&plat_dev->dev); if (IS_ERR(rtd->rtc)) return PTR_ERR(rtd->rtc); + rtd->rtc->ops = &test_rtc_ops; + timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); rtd->alarm.expires = 0; - return 0; + return rtc_register_device(rtd->rtc); } static struct platform_driver test_driver = { -- cgit v1.2.3 From 1928906d126f647ff025a54df4ed88c05b2afba9 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 5 Jun 2018 23:09:13 +0200 Subject: rtc: test: remove alarm support from the first device To test for issues with RTCs that don't provide an alarm, remove alarm support from the first test RTC device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-test.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 0c30b04326c5..8469256edc2a 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -95,6 +95,12 @@ static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) return 0; } +static const struct rtc_class_ops test_rtc_ops_noalm = { + .read_time = test_rtc_read_time, + .set_mmss64 = test_rtc_set_mmss64, + .alarm_irq_enable = test_rtc_alarm_irq_enable, +}; + static const struct rtc_class_ops test_rtc_ops = { .read_time = test_rtc_read_time, .read_alarm = test_rtc_read_alarm, @@ -124,7 +130,13 @@ static int test_probe(struct platform_device *plat_dev) if (IS_ERR(rtd->rtc)) return PTR_ERR(rtd->rtc); - rtd->rtc->ops = &test_rtc_ops; + switch (plat_dev->id) { + case 0: + rtd->rtc->ops = &test_rtc_ops_noalm; + break; + default: + rtd->rtc->ops = &test_rtc_ops; + } timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); rtd->alarm.expires = 0; -- cgit v1.2.3 From abfdff44bc38e9e2ef7929f633fb8462632299d4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 5 Jun 2018 23:09:14 +0200 Subject: rtc: ensure rtc_set_alarm fails when alarms are not supported When using RTC_ALM_SET or RTC_WKALM_SET with rtc_wkalrm.enabled not set, rtc_timer_enqueue() is not called and rtc_set_alarm() may succeed but the subsequent RTC_AIE_ON ioctl will fail. RTC_ALM_READ would also fail in that case. Ensure rtc_set_alarm() fails when alarms are not supported to avoid letting programs think the alarms are working for a particular RTC when they are not. Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 7cbdc9228dd5..6d4012dd6922 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -441,6 +441,11 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; + if (!rtc->ops) + return -ENODEV; + else if (!rtc->ops->set_alarm) + return -EINVAL; + err = rtc_valid_tm(&alarm->time); if (err != 0) return err; -- cgit v1.2.3 From e6988d23484417b8859d1c56d8378d7d08394c72 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 6 Jun 2018 17:08:53 +0200 Subject: rtc: cros-ec: Make license text and module license match. The license text is specifying "GPLv2" 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: Enric Balletbo i Serra Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cros-ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index bf7ced095c94..f2b87f9159c1 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c @@ -409,5 +409,5 @@ module_platform_driver(cros_ec_rtc_driver); MODULE_DESCRIPTION("RTC driver for Chrome OS ECs"); MODULE_AUTHOR("Stephen Barber "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -- cgit v1.2.3 From 8ee4aee5b504e515a986a1415e45c81efaae8df7 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 6 Jun 2018 17:08:54 +0200 Subject: rtc: cros-ec: Switch to SPDX identifier. Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Enric Balletbo i Serra Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cros-ec.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index f2b87f9159c1..e5444296075e 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c @@ -1,19 +1,8 @@ -/* - * RTC driver for Chrome OS Embedded Controller - * - * Copyright (c) 2017, Google, Inc - * - * Author: Stephen Barber - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ +// SPDX-License-Identifier: GPL-2.0 +// RTC driver for ChromeOS Embedded Controller. +// +// Copyright (C) 2017 Google, Inc. +// Author: Stephen Barber #include #include -- cgit v1.2.3 From e4302aec8a0646828a701443e303eb5ef48b37f5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Jun 2018 11:29:09 +0300 Subject: rtc: pxa: fix probe function This patch is from static analysis and I don't have the hardware to to test it. I think the test is reversed so now the probe function will return success early and the last part of the function is dead code. Fixes: 3cdf4ad9633e ("rtc: pxa: convert to use shared sa1100 functions") Signed-off-by: Dan Carpenter Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pxa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index 47304f5664d8..e1887b86fdc7 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -363,7 +363,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) sa1100_rtc->rtar = pxa_rtc->base + 0x4; sa1100_rtc->rttr = pxa_rtc->base + 0xc; ret = sa1100_rtc_init(pdev, sa1100_rtc); - if (!ret) { + if (ret) { dev_err(dev, "Unable to init SA1100 RTC sub-device\n"); return ret; } -- cgit v1.2.3