From 29a1f599c0cc37004f92ba455d1ccda3db0b6a94 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 14 Dec 2017 13:31:43 +0800 Subject: [PATCH 001/128] rtc: Add tracepoints for RTC system It will be more helpful to add some tracepoints to track RTC actions when debugging RTC driver. Below sample is that we set/read the RTC time, then set 2 alarms, so we can see the trace logs: set/read RTC time: kworker/0:1-67 [000] 21.814245: rtc_set_time: UTC (1510301580) (0) kworker/0:1-67 [000] 21.814312: rtc_read_time: UTC (1510301580) (0) set the first alarm timer: kworker/0:1-67 [000] 21.829238: rtc_timer_enqueue: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0 kworker/0:1-67 [000] 22.018279: rtc_set_alarm: UTC (1510301700) (0) set the second alarm timer: kworker/0:1-67 [000] 22.230284: rtc_timer_enqueue: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0 the first alarm timer was expired: kworker/0:1-67 [000] 145.155584: rtc_timer_dequeue: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0 kworker/0:1-67 [000] 145.155593: rtc_timer_fired: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0 kworker/0:1-67 [000] 145.172504: rtc_set_alarm: UTC (1510301820) (0) the second alarm timer was expired: kworker/0:1-67 [000] 269.102353: rtc_timer_dequeue: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0 kworker/0:1-67 [000] 269.102360: rtc_timer_fired: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0 disable alarm irq: kworker/0:1-67 [000] 269.102469: rtc_alarm_irq_enable: disable RTC alarm IRQ (0) Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 30 ++++++ include/trace/events/rtc.h | 206 +++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 include/trace/events/rtc.h diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 672b192f8153..7e253be19ba7 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -17,6 +17,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); @@ -53,6 +56,8 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) err = __rtc_read_time(rtc, tm); mutex_unlock(&rtc->ops_lock); + + trace_rtc_read_time(rtc_tm_to_time64(tm), err); return err; } EXPORT_SYMBOL_GPL(rtc_read_time); @@ -87,6 +92,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) mutex_unlock(&rtc->ops_lock); /* A timer might have just expired */ schedule_work(&rtc->irqwork); + + trace_rtc_set_time(rtc_tm_to_time64(tm), err); return err; } EXPORT_SYMBOL_GPL(rtc_set_time); @@ -119,6 +126,8 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al } mutex_unlock(&rtc->ops_lock); + + trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err); return err; } @@ -316,6 +325,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } mutex_unlock(&rtc->ops_lock); + trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err); return err; } EXPORT_SYMBOL_GPL(rtc_read_alarm); @@ -352,6 +362,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) else err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err); return err; } @@ -406,6 +417,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) rtc->aie_timer.enabled = 1; timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); + trace_rtc_timer_enqueue(&rtc->aie_timer); } mutex_unlock(&rtc->ops_lock); return err; @@ -435,6 +447,8 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); mutex_unlock(&rtc->ops_lock); + + trace_rtc_alarm_irq_enable(enabled, err); return err; } EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); @@ -709,6 +723,8 @@ retry: rtc->pie_enabled = enabled; } spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + + trace_rtc_irq_set_state(enabled, err); return err; } EXPORT_SYMBOL_GPL(rtc_irq_set_state); @@ -745,6 +761,8 @@ retry: } } spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + + trace_rtc_irq_set_freq(freq, err); return err; } EXPORT_SYMBOL_GPL(rtc_irq_set_freq); @@ -779,6 +797,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) } timerqueue_add(&rtc->timerqueue, &timer->node); + trace_rtc_timer_enqueue(timer); if (!next || ktime_before(timer->node.expires, next->expires)) { struct rtc_wkalrm alarm; int err; @@ -790,6 +809,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) schedule_work(&rtc->irqwork); } else if (err) { timerqueue_del(&rtc->timerqueue, &timer->node); + trace_rtc_timer_dequeue(timer); timer->enabled = 0; return err; } @@ -803,6 +823,7 @@ static void rtc_alarm_disable(struct rtc_device *rtc) return; rtc->ops->alarm_irq_enable(rtc->dev.parent, false); + trace_rtc_alarm_irq_enable(0, 0); } /** @@ -821,6 +842,7 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) { struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); timerqueue_del(&rtc->timerqueue, &timer->node); + trace_rtc_timer_dequeue(timer); timer->enabled = 0; if (next == &timer->node) { struct rtc_wkalrm alarm; @@ -871,16 +893,19 @@ again: /* expire timer */ timer = container_of(next, struct rtc_timer, node); timerqueue_del(&rtc->timerqueue, &timer->node); + trace_rtc_timer_dequeue(timer); timer->enabled = 0; if (timer->task.func) timer->task.func(timer->task.private_data); + trace_rtc_timer_fired(timer); /* Re-add/fwd periodic timers */ if (ktime_to_ns(timer->period)) { timer->node.expires = ktime_add(timer->node.expires, timer->period); timer->enabled = 1; timerqueue_add(&rtc->timerqueue, &timer->node); + trace_rtc_timer_enqueue(timer); } } @@ -902,6 +927,7 @@ reprogram: timer = container_of(next, struct rtc_timer, node); timerqueue_del(&rtc->timerqueue, &timer->node); + trace_rtc_timer_dequeue(timer); timer->enabled = 0; dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err); goto again; @@ -992,6 +1018,8 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset) mutex_lock(&rtc->ops_lock); ret = rtc->ops->read_offset(rtc->dev.parent, offset); mutex_unlock(&rtc->ops_lock); + + trace_rtc_read_offset(*offset, ret); return ret; } @@ -1025,5 +1053,7 @@ int rtc_set_offset(struct rtc_device *rtc, long offset) mutex_lock(&rtc->ops_lock); ret = rtc->ops->set_offset(rtc->dev.parent, offset); mutex_unlock(&rtc->ops_lock); + + trace_rtc_set_offset(offset, ret); return ret; } diff --git a/include/trace/events/rtc.h b/include/trace/events/rtc.h new file mode 100644 index 000000000000..621333f1c890 --- /dev/null +++ b/include/trace/events/rtc.h @@ -0,0 +1,206 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM rtc + +#if !defined(_TRACE_RTC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_RTC_H + +#include +#include + +DECLARE_EVENT_CLASS(rtc_time_alarm_class, + + TP_PROTO(time64_t secs, int err), + + TP_ARGS(secs, err), + + TP_STRUCT__entry( + __field(time64_t, secs) + __field(int, err) + ), + + TP_fast_assign( + __entry->secs = secs; + __entry->err = err; + ), + + TP_printk("UTC (%lld) (%d)", + __entry->secs, __entry->err + ) +); + +DEFINE_EVENT(rtc_time_alarm_class, rtc_set_time, + + TP_PROTO(time64_t secs, int err), + + TP_ARGS(secs, err) +); + +DEFINE_EVENT(rtc_time_alarm_class, rtc_read_time, + + TP_PROTO(time64_t secs, int err), + + TP_ARGS(secs, err) +); + +DEFINE_EVENT(rtc_time_alarm_class, rtc_set_alarm, + + TP_PROTO(time64_t secs, int err), + + TP_ARGS(secs, err) +); + +DEFINE_EVENT(rtc_time_alarm_class, rtc_read_alarm, + + TP_PROTO(time64_t secs, int err), + + TP_ARGS(secs, err) +); + +TRACE_EVENT(rtc_irq_set_freq, + + TP_PROTO(int freq, int err), + + TP_ARGS(freq, err), + + TP_STRUCT__entry( + __field(int, freq) + __field(int, err) + ), + + TP_fast_assign( + __entry->freq = freq; + __entry->err = err; + ), + + TP_printk("set RTC periodic IRQ frequency:%u (%d)", + __entry->freq, __entry->err + ) +); + +TRACE_EVENT(rtc_irq_set_state, + + TP_PROTO(int enabled, int err), + + TP_ARGS(enabled, err), + + TP_STRUCT__entry( + __field(int, enabled) + __field(int, err) + ), + + TP_fast_assign( + __entry->enabled = enabled; + __entry->err = err; + ), + + TP_printk("%s RTC 2^N Hz periodic IRQs (%d)", + __entry->enabled ? "enable" : "disable", + __entry->err + ) +); + +TRACE_EVENT(rtc_alarm_irq_enable, + + TP_PROTO(unsigned int enabled, int err), + + TP_ARGS(enabled, err), + + TP_STRUCT__entry( + __field(unsigned int, enabled) + __field(int, err) + ), + + TP_fast_assign( + __entry->enabled = enabled; + __entry->err = err; + ), + + TP_printk("%s RTC alarm IRQ (%d)", + __entry->enabled ? "enable" : "disable", + __entry->err + ) +); + +DECLARE_EVENT_CLASS(rtc_offset_class, + + TP_PROTO(long offset, int err), + + TP_ARGS(offset, err), + + TP_STRUCT__entry( + __field(long, offset) + __field(int, err) + ), + + TP_fast_assign( + __entry->offset = offset; + __entry->err = err; + ), + + TP_printk("RTC offset: %ld (%d)", + __entry->offset, __entry->err + ) +); + +DEFINE_EVENT(rtc_offset_class, rtc_set_offset, + + TP_PROTO(long offset, int err), + + TP_ARGS(offset, err) +); + +DEFINE_EVENT(rtc_offset_class, rtc_read_offset, + + TP_PROTO(long offset, int err), + + TP_ARGS(offset, err) +); + +DECLARE_EVENT_CLASS(rtc_timer_class, + + TP_PROTO(struct rtc_timer *timer), + + TP_ARGS(timer), + + TP_STRUCT__entry( + __field(struct rtc_timer *, timer) + __field(ktime_t, expires) + __field(ktime_t, period) + ), + + TP_fast_assign( + __entry->timer = timer; + __entry->expires = timer->node.expires; + __entry->period = timer->period; + ), + + TP_printk("RTC timer:(%p) expires:%lld period:%lld", + __entry->timer, __entry->expires, __entry->period + ) +); + +DEFINE_EVENT(rtc_timer_class, rtc_timer_enqueue, + + TP_PROTO(struct rtc_timer *timer), + + TP_ARGS(timer) +); + +DEFINE_EVENT(rtc_timer_class, rtc_timer_dequeue, + + TP_PROTO(struct rtc_timer *timer), + + TP_ARGS(timer) +); + +DEFINE_EVENT(rtc_timer_class, rtc_timer_fired, + + TP_PROTO(struct rtc_timer *timer), + + TP_ARGS(timer) +); + +#endif /* _TRACE_RTC_H */ + +/* This part must be outside protection */ +#include From 36d46cdb43efea74043e29e2a62b13e9aca31452 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 25 Dec 2017 19:10:37 +0800 Subject: [PATCH 002/128] rtc: Fix overflow when converting time64_t to rtc_time If we convert one large time values to rtc_time, in the original formula 'days * 86400' can be overflowed in 'unsigned int' type to make the formula get one incorrect remain seconds value. Thus we can use div_s64_rem() function to avoid this situation. Signed-off-by: Baolin Wang Acked-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-lib.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 1ae7da5cfc60..ad5bb21908e5 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -52,13 +52,11 @@ EXPORT_SYMBOL(rtc_year_days); */ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) { - unsigned int month, year; - unsigned long secs; + unsigned int month, year, secs; int days; /* time must be positive */ - days = div_s64(time, 86400); - secs = time - (unsigned int) days * 86400; + days = div_s64_rem(time, 86400, &secs); /* day of the week, 1970-01-01 was a Thursday */ tm->tm_wday = (days + 4) % 7; From 82d632b85eb89f97051530f556cb49ee1c04bde7 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 16 Jan 2018 14:45:21 +0000 Subject: [PATCH 003/128] rtc: goldfish: Add missing MODULE_LICENSE Fix the following warning in MIPS allmodconfig by adding a MODULE_LICENSE() at the end of rtc-goldfish.c, based on the file header comment which says GNU General Public License version 2: WARNING: modpost: missing MODULE_LICENSE() in drivers/rtc/rtc-goldfish.o Fixes: f22d9cdcb5eb ("rtc: goldfish: Add RTC driver for Android emulator") Signed-off-by: James Hogan Cc: Miodrag Dinic Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: linux-rtc@vger.kernel.org Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-goldfish.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c index d67769265185..a1c44d0c8557 100644 --- a/drivers/rtc/rtc-goldfish.c +++ b/drivers/rtc/rtc-goldfish.c @@ -235,3 +235,5 @@ static struct platform_driver goldfish_rtc = { }; module_platform_driver(goldfish_rtc); + +MODULE_LICENSE("GPL v2"); From 5134d2fd9fe1278ecb309421275d88b6c80ebddd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Jan 2018 10:17:27 +0000 Subject: [PATCH 004/128] rtc: ds1302: remove redundant initializations of pointer bp Pointe bp is being initialized and this value is never read, it is being updated to the same value later just before it is going to be used. Remove the initialization as it is never read and keep the setting of bp closer to the use of bp. Cleans up clang warnings: drivers/rtc/rtc-ds1302.c:115:7: warning: Value stored to 'bp' during its initialization is never read drivers/rtc/rtc-ds1302.c:46:7: warning: Value stored to 'bp' during its initialization is never read Signed-off-by: Colin Ian King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1302.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 0ec4be62322b..43bcb17c922e 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -43,7 +43,7 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *time) { struct spi_device *spi = dev_get_drvdata(dev); u8 buf[1 + RTC_CLCK_LEN]; - u8 *bp = buf; + u8 *bp; int status; /* Enable writing */ @@ -112,7 +112,7 @@ static int ds1302_probe(struct spi_device *spi) struct rtc_device *rtc; u8 addr; u8 buf[4]; - u8 *bp = buf; + u8 *bp; int status; /* Sanity check board setup data. This may be hooked up From 7b21db9184a21b3ba479030dcfecaf3f2fa94b1f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:15 +0100 Subject: [PATCH 005/128] rtc: documentation: correct nvmem date and version The nvmem interface appaeared in linux 4.13 Signed-off-by: Alexandre Belloni --- Documentation/ABI/testing/sysfs-class-rtc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-rtc b/Documentation/ABI/testing/sysfs-class-rtc index cf60412882f0..65270d95873c 100644 --- a/Documentation/ABI/testing/sysfs-class-rtc +++ b/Documentation/ABI/testing/sysfs-class-rtc @@ -58,8 +58,8 @@ Description: (RO) RTC-provided time in 24-hour notation (hh:mm:ss) What: /sys/class/rtc/rtcX/*/nvmem -Date: February 2016 -KernelVersion: 4.6 +Date: July 2017 +KernelVersion: 4.13 Contact: linux-rtc@vger.kernel.org Description: (RW) The non volatile storage exported as a raw file, as From 4cce9d3988ae33eb53742d9648ecc59046196e6f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:16 +0100 Subject: [PATCH 006/128] rtc: nvmem: pass nvmem_config to rtc_nvmem_register() To be able to remove nvmem_config from struct rtc_device, pass it as a parameter to rtc_nvmem_register. Signed-off-by: Alexandre Belloni --- drivers/rtc/class.c | 2 +- drivers/rtc/nvmem.c | 17 +++++++++-------- drivers/rtc/rtc-core.h | 6 ++++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 722d683e0b0f..47c4aeed5106 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -453,7 +453,7 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) rtc_proc_add_device(rtc); - rtc_nvmem_register(rtc); + rtc_nvmem_register(rtc, rtc->nvmem_config); rtc->registered = true; dev_info(rtc->dev.parent, "registered as %s\n", diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index 8567b4ed9ac6..0a3522bcdd25 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -46,7 +46,7 @@ rtc_nvram_write(struct file *filp, struct kobject *kobj, return nvmem_device_write(rtc->nvmem, off, count, buf); } -static int rtc_nvram_register(struct rtc_device *rtc) +static int rtc_nvram_register(struct rtc_device *rtc, size_t size) { int err; @@ -64,7 +64,7 @@ static int rtc_nvram_register(struct rtc_device *rtc) rtc->nvram->read = rtc_nvram_read; rtc->nvram->write = rtc_nvram_write; - rtc->nvram->size = rtc->nvmem_config->size; + rtc->nvram->size = size; err = sysfs_create_bin_file(&rtc->dev.parent->kobj, rtc->nvram); @@ -84,20 +84,21 @@ static void rtc_nvram_unregister(struct rtc_device *rtc) /* * New ABI, uses nvmem */ -void rtc_nvmem_register(struct rtc_device *rtc) +void rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config) { - if (!rtc->nvmem_config) + if (!nvmem_config) return; - rtc->nvmem_config->dev = &rtc->dev; - rtc->nvmem_config->owner = rtc->owner; - rtc->nvmem = nvmem_register(rtc->nvmem_config); + nvmem_config->dev = &rtc->dev; + nvmem_config->owner = rtc->owner; + rtc->nvmem = nvmem_register(nvmem_config); if (IS_ERR_OR_NULL(rtc->nvmem)) return; /* Register the old ABI */ if (rtc->nvram_old_abi) - rtc_nvram_register(rtc); + rtc_nvram_register(rtc, nvmem_config->size); } void rtc_nvmem_unregister(struct rtc_device *rtc) diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h index 513b9bedd2c8..5f60e3b11cde 100644 --- a/drivers/rtc/rtc-core.h +++ b/drivers/rtc/rtc-core.h @@ -48,9 +48,11 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) #endif #ifdef CONFIG_RTC_NVMEM -void rtc_nvmem_register(struct rtc_device *rtc); +void rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config); void rtc_nvmem_unregister(struct rtc_device *rtc); #else -static inline void rtc_nvmem_register(struct rtc_device *rtc) {} +static inline void rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config) {} static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} #endif From 2cc8212198820487ec3fdcc7b98133701fc9dfc3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:17 +0100 Subject: [PATCH 007/128] rtc: nvmem: return error values In case of error, make rtc_nvmem_register() able to return an error value to its caller. Signed-off-by: Alexandre Belloni --- drivers/rtc/nvmem.c | 10 ++++++---- drivers/rtc/rtc-core.h | 11 +++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index 0a3522bcdd25..293df6db7c42 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -84,21 +84,23 @@ static void rtc_nvram_unregister(struct rtc_device *rtc) /* * New ABI, uses nvmem */ -void rtc_nvmem_register(struct rtc_device *rtc, - struct nvmem_config *nvmem_config) +int rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config) { if (!nvmem_config) - return; + return -ENODEV; nvmem_config->dev = &rtc->dev; nvmem_config->owner = rtc->owner; rtc->nvmem = nvmem_register(nvmem_config); if (IS_ERR_OR_NULL(rtc->nvmem)) - return; + return PTR_ERR(rtc->nvmem); /* Register the old ABI */ if (rtc->nvram_old_abi) rtc_nvram_register(rtc, nvmem_config->size); + + return 0; } void rtc_nvmem_unregister(struct rtc_device *rtc) diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h index 5f60e3b11cde..05a67837fd76 100644 --- a/drivers/rtc/rtc-core.h +++ b/drivers/rtc/rtc-core.h @@ -48,11 +48,14 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) #endif #ifdef CONFIG_RTC_NVMEM -void rtc_nvmem_register(struct rtc_device *rtc, - struct nvmem_config *nvmem_config); +int rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config); void rtc_nvmem_unregister(struct rtc_device *rtc); #else -static inline void rtc_nvmem_register(struct rtc_device *rtc, - struct nvmem_config *nvmem_config) {} +static inline int rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config) +{ + return -ENODEV; +} static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} #endif From ab3ea36eda76069ba52e9b6aef5a9370b0b462bf Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:18 +0100 Subject: [PATCH 008/128] rtc: nvmem: disallow registering nvmem more than once Make rtc_nvmem_register return -EBUSY when an nvmem is already registered for that RTC. Signed-off-by: Alexandre Belloni --- drivers/rtc/nvmem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index 293df6db7c42..fd1c39a5ade5 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -87,6 +87,9 @@ static void rtc_nvram_unregister(struct rtc_device *rtc) int rtc_nvmem_register(struct rtc_device *rtc, struct nvmem_config *nvmem_config) { + if (!IS_ERR_OR_NULL(rtc->nvmem)) + return -EBUSY; + if (!nvmem_config) return -ENODEV; From ac75779b72fd52741d7446ad27cf6d58c006c643 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 28 Feb 2018 21:58:02 +0100 Subject: [PATCH 009/128] rtc: nvmem: allow registering the nvmem device before the rtc Switch the parent of the nvmem device to the parent of the rtc device so it can be registered before the RTC. This is a small change in the ABI as the nvmem moves out of the /sys/class/rtc/rtcX folder to be under the parent device folder (that is where the previous nvram files where registered). However, it is still available under its correct location, /sys/bus/nvmem/devices which is the one that should be used by userspace applications. The other benefit is that the nvmem device can stay registered even if the rtc registration fails. Or it is possible to not register the rtc if the nvmem registration failed. Finally, it makes a lot of sense for devices that actually have different i2c or spi addresses for the RTC and the EEPROM. That is basically how it would end up when using MFD or even completely separate devices. Signed-off-by: Alexandre Belloni --- Documentation/ABI/testing/sysfs-class-rtc | 8 -------- drivers/rtc/class.c | 5 +++-- drivers/rtc/nvmem.c | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-rtc b/Documentation/ABI/testing/sysfs-class-rtc index 65270d95873c..792a38300336 100644 --- a/Documentation/ABI/testing/sysfs-class-rtc +++ b/Documentation/ABI/testing/sysfs-class-rtc @@ -57,14 +57,6 @@ Contact: linux-rtc@vger.kernel.org Description: (RO) RTC-provided time in 24-hour notation (hh:mm:ss) -What: /sys/class/rtc/rtcX/*/nvmem -Date: July 2017 -KernelVersion: 4.13 -Contact: linux-rtc@vger.kernel.org -Description: - (RW) The non volatile storage exported as a raw file, as - described in Documentation/nvmem/nvmem.txt - What: /sys/class/rtc/rtcX/offset Date: February 2016 KernelVersion: 4.6 diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 47c4aeed5106..0cab397f6e37 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -293,8 +293,6 @@ EXPORT_SYMBOL_GPL(rtc_device_register); */ void rtc_device_unregister(struct rtc_device *rtc) { - rtc_nvmem_unregister(rtc); - mutex_lock(&rtc->ops_lock); /* * Remove innards of this RTC, then disable it, before @@ -312,6 +310,7 @@ static void devm_rtc_device_release(struct device *dev, void *res) { struct rtc_device *rtc = *(struct rtc_device **)res; + rtc_nvmem_unregister(rtc); rtc_device_unregister(rtc); } @@ -382,6 +381,8 @@ static void devm_rtc_release_device(struct device *dev, void *res) { struct rtc_device *rtc = *(struct rtc_device **)res; + rtc_nvmem_unregister(rtc); + if (rtc->registered) rtc_device_unregister(rtc); else diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index fd1c39a5ade5..eb8c622cfcf4 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -93,7 +93,7 @@ int rtc_nvmem_register(struct rtc_device *rtc, if (!nvmem_config) return -ENODEV; - nvmem_config->dev = &rtc->dev; + nvmem_config->dev = rtc->dev.parent; nvmem_config->owner = rtc->owner; rtc->nvmem = nvmem_register(nvmem_config); if (IS_ERR_OR_NULL(rtc->nvmem)) From fd5cd21d995e67f87b3eb4adf938be85fe83ef4b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:19 +0100 Subject: [PATCH 010/128] rtc: export rtc_nvmem_register() to drivers Export rtc_nvmem_register() so it can be called from drivers instead of only the core. Signed-off-by: Alexandre Belloni --- drivers/rtc/nvmem.c | 3 +-- drivers/rtc/rtc-core.h | 13 ------------- include/linux/rtc.h | 13 +++++++++++++ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c index eb8c622cfcf4..17ec4c8d0fad 100644 --- a/drivers/rtc/nvmem.c +++ b/drivers/rtc/nvmem.c @@ -14,8 +14,6 @@ #include #include -#include "rtc-core.h" - /* * Deprecated ABI compatibility, this should be removed at some point */ @@ -105,6 +103,7 @@ int rtc_nvmem_register(struct rtc_device *rtc, return 0; } +EXPORT_SYMBOL_GPL(rtc_nvmem_register); void rtc_nvmem_unregister(struct rtc_device *rtc) { diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h index 05a67837fd76..0abf98983e13 100644 --- a/drivers/rtc/rtc-core.h +++ b/drivers/rtc/rtc-core.h @@ -46,16 +46,3 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) return NULL; } #endif - -#ifdef CONFIG_RTC_NVMEM -int rtc_nvmem_register(struct rtc_device *rtc, - struct nvmem_config *nvmem_config); -void rtc_nvmem_unregister(struct rtc_device *rtc); -#else -static inline int rtc_nvmem_register(struct rtc_device *rtc, - struct nvmem_config *nvmem_config) -{ - return -ENODEV; -} -static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} -#endif diff --git a/include/linux/rtc.h b/include/linux/rtc.h index fc6c90b57be0..fbc92fff7c2e 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -271,4 +271,17 @@ extern int rtc_hctosys_ret; #define rtc_hctosys_ret -ENODEV #endif +#ifdef CONFIG_RTC_NVMEM +int rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config); +void rtc_nvmem_unregister(struct rtc_device *rtc); +#else +static inline int rtc_nvmem_register(struct rtc_device *rtc, + struct nvmem_config *nvmem_config) +{ + return -ENODEV; +} +static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} +#endif + #endif /* _LINUX_RTC_H_ */ From 6910614f1e2806f43d0237a3566f83bfbee33440 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:20 +0100 Subject: [PATCH 011/128] rtc: ds1305: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index d8df2e9e14ad..affa90da26f1 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -703,15 +703,15 @@ static int ds1305_probe(struct spi_device *spi) ds1305->rtc->ops = &ds1305_ops; ds1305_nvmem_cfg.priv = ds1305; - ds1305->rtc->nvmem_config = &ds1305_nvmem_cfg; ds1305->rtc->nvram_old_abi = true; - status = rtc_register_device(ds1305->rtc); if (status) { dev_dbg(&spi->dev, "register rtc --> %d\n", status); return status; } + rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg); + /* Maybe set up alarm IRQ; be ready to handle it triggering right * away. NOTE that we don't share this. The signal is active low, * and we can't ack it before a SPI message delay. We temporarily From eed9d7a335d67f8d61286fb3bbacce9c61c6dc52 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:21 +0100 Subject: [PATCH 012/128] rtc: ds1305: put ds1305_nvmem_cfg on the stack This makes to code safer on system using two similar RTCs. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index affa90da26f1..3d2400a39da9 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -544,15 +544,6 @@ static int ds1305_nvram_write(void *priv, unsigned int off, void *buf, return spi_sync(spi, &m); } -static struct nvmem_config ds1305_nvmem_cfg = { - .name = "ds1305_nvram", - .word_size = 1, - .stride = 1, - .size = DS1305_NVRAM_LEN, - .reg_read = ds1305_nvram_read, - .reg_write = ds1305_nvram_write, -}; - /*----------------------------------------------------------------------*/ /* @@ -566,6 +557,14 @@ static int ds1305_probe(struct spi_device *spi) u8 addr, value; struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev); bool write_ctrl = false; + struct nvmem_config ds1305_nvmem_cfg = { + .name = "ds1305_nvram", + .word_size = 1, + .stride = 1, + .size = DS1305_NVRAM_LEN, + .reg_read = ds1305_nvram_read, + .reg_write = ds1305_nvram_write, + }; /* Sanity check board setup data. This may be hooked up * in 3wire mode, but we don't care. Note that unless From e9fb7682fa22b16175b6cabcc481ec53ba696c43 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:22 +0100 Subject: [PATCH 013/128] rtc: ds1307: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 923dde912f60..c146411a2099 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1696,6 +1696,11 @@ read_rtc: } } + ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; + err = rtc_register_device(ds1307->rtc); + if (err) + return err; + if (chip->nvram_size) { ds1307->nvmem_cfg.name = "ds1307_nvram"; ds1307->nvmem_cfg.word_size = 1; @@ -1705,15 +1710,10 @@ read_rtc: ds1307->nvmem_cfg.reg_write = ds1307_nvram_write; ds1307->nvmem_cfg.priv = ds1307; - ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg; ds1307->rtc->nvram_old_abi = true; + rtc_nvmem_register(ds1307->rtc, &ds1307->nvmem_cfg); } - ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; - err = rtc_register_device(ds1307->rtc); - if (err) - return err; - ds1307_hwmon_register(ds1307); ds1307_clks_register(ds1307); From 409baf1785db703583a5f0b51c0d0b114e14f4fb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:23 +0100 Subject: [PATCH 014/128] rtc: ds1307: put struct nvmem_config on the stack Avoid allocating memory for struct nvmem_config as it is only necessary at the nvmem registration. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index c146411a2099..4021d478b9f3 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -114,7 +114,6 @@ enum ds_type { # define RX8025_BIT_XST 0x20 struct ds1307 { - struct nvmem_config nvmem_cfg; enum ds_type type; unsigned long flags; #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ @@ -1702,16 +1701,18 @@ read_rtc: return err; if (chip->nvram_size) { - ds1307->nvmem_cfg.name = "ds1307_nvram"; - ds1307->nvmem_cfg.word_size = 1; - ds1307->nvmem_cfg.stride = 1; - ds1307->nvmem_cfg.size = chip->nvram_size; - ds1307->nvmem_cfg.reg_read = ds1307_nvram_read; - ds1307->nvmem_cfg.reg_write = ds1307_nvram_write; - ds1307->nvmem_cfg.priv = ds1307; + struct nvmem_config nvmem_cfg = { + .name = "ds1307_nvram", + .word_size = 1, + .stride = 1, + .size = chip->nvram_size, + .reg_read = ds1307_nvram_read, + .reg_write = ds1307_nvram_write, + .priv = ds1307, + }; ds1307->rtc->nvram_old_abi = true; - rtc_nvmem_register(ds1307->rtc, &ds1307->nvmem_cfg); + rtc_nvmem_register(ds1307->rtc, &nvmem_cfg); } ds1307_hwmon_register(ds1307); From 16fef391428e95b08e2c6ef9770f0d1185de770e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:24 +0100 Subject: [PATCH 015/128] rtc: ds1511: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 1e95312a6f2e..b1e51a4c2908 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -479,13 +479,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev) pdata->rtc->ops = &ds1511_rtc_ops; ds1511_nvmem_cfg.priv = &pdev->dev; - pdata->rtc->nvmem_config = &ds1511_nvmem_cfg; pdata->rtc->nvram_old_abi = true; ret = rtc_register_device(pdata->rtc); if (ret) return ret; + rtc_nvmem_register(pdata->rtc, &ds1511_nvmem_cfg); + /* * if the platform has an interrupt in mind for this device, * then by all means, set it From 71e19c5e25792db5f46d525eb5743186b148326d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:25 +0100 Subject: [PATCH 016/128] rtc: ds1511: put ds1511_nvmem_cfg on the stack Move ds1511_nvmem_cfg to the stack of ds1511_rtc_probe. This results in a very small code size reduction and make it safer on systems with two similar RTCs: text data bss dec hex filename 2128 164 4 2296 8f8 drivers/rtc/rtc-ds1511.o.before 2175 100 4 2279 8e7 drivers/rtc/rtc-ds1511.o.after Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index b1e51a4c2908..5f55214db9f8 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -422,20 +422,20 @@ static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf, return 0; } -static struct nvmem_config ds1511_nvmem_cfg = { - .name = "ds1511_nvram", - .word_size = 1, - .stride = 1, - .size = DS1511_RAM_MAX, - .reg_read = ds1511_nvram_read, - .reg_write = ds1511_nvram_write, -}; - static int ds1511_rtc_probe(struct platform_device *pdev) { struct resource *res; struct rtc_plat_data *pdata; int ret = 0; + struct nvmem_config ds1511_nvmem_cfg = { + .name = "ds1511_nvram", + .word_size = 1, + .stride = 1, + .size = DS1511_RAM_MAX, + .reg_read = ds1511_nvram_read, + .reg_write = ds1511_nvram_write, + .priv = &pdev->dev, + }; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -478,7 +478,6 @@ static int ds1511_rtc_probe(struct platform_device *pdev) pdata->rtc->ops = &ds1511_rtc_ops; - ds1511_nvmem_cfg.priv = &pdev->dev; pdata->rtc->nvram_old_abi = true; ret = rtc_register_device(pdata->rtc); From 3c1bb61fad370d7c440b8f81df76cbb4d52a9b6f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:26 +0100 Subject: [PATCH 017/128] rtc: m48t86: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t86.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index d9aea9b6d9cd..3a48a7eb3e9c 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -266,13 +266,14 @@ static int m48t86_rtc_probe(struct platform_device *pdev) info->rtc->ops = &m48t86_rtc_ops; m48t86_nvmem_cfg.priv = &pdev->dev; - info->rtc->nvmem_config = &m48t86_nvmem_cfg; info->rtc->nvram_old_abi = true; err = rtc_register_device(info->rtc); if (err) return err; + rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg); + /* read battery status */ reg = m48t86_readb(&pdev->dev, M48T86_D); dev_info(&pdev->dev, "battery %s\n", From e3f51c0d29164b2e4cf3c72c962f3a4891412e9b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:27 +0100 Subject: [PATCH 018/128] rtc: m48t86: put m48t86_nvmem_cfg on the stack Move m48t86_nvmem_cfg to the stack of m48t86_rtc_probe. This results in a very small code size reduction and make it safer on systems with two similar RTCs: text data bss dec hex filename 1733 164 0 1897 769 drivers/rtc/rtc-m48t86.o.before 1793 100 0 1893 765 drivers/rtc/rtc-m48t86.o.after Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t86.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 3a48a7eb3e9c..8d17be1e6650 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -218,21 +218,21 @@ static bool m48t86_verify_chip(struct platform_device *pdev) return false; } -static struct nvmem_config m48t86_nvmem_cfg = { - .name = "m48t86_nvram", - .word_size = 1, - .stride = 1, - .size = M48T86_NVRAM_LEN, - .reg_read = m48t86_nvram_read, - .reg_write = m48t86_nvram_write, -}; - static int m48t86_rtc_probe(struct platform_device *pdev) { struct m48t86_rtc_info *info; struct resource *res; unsigned char reg; int err; + struct nvmem_config m48t86_nvmem_cfg = { + .name = "m48t86_nvram", + .word_size = 1, + .stride = 1, + .size = M48T86_NVRAM_LEN, + .reg_read = m48t86_nvram_read, + .reg_write = m48t86_nvram_write, + .priv = &pdev->dev, + }; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -264,8 +264,6 @@ static int m48t86_rtc_probe(struct platform_device *pdev) return PTR_ERR(info->rtc); info->rtc->ops = &m48t86_rtc_ops; - - m48t86_nvmem_cfg.priv = &pdev->dev; info->rtc->nvram_old_abi = true; err = rtc_register_device(info->rtc); From ce603842c282a68191022aa3361ae18fc50a7f82 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:28 +0100 Subject: [PATCH 019/128] rtc: omap: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 09ef802d6e54..e53cb27f4118 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -850,7 +850,6 @@ static int omap_rtc_probe(struct platform_device *pdev) rtc->rtc->ops = &omap_rtc_ops; omap_rtc_nvmem_config.priv = rtc; - rtc->rtc->nvmem_config = &omap_rtc_nvmem_config; /* handle periodic and alarm irqs */ ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, @@ -886,6 +885,8 @@ static int omap_rtc_probe(struct platform_device *pdev) if (ret) goto err; + rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config); + return 0; err: From 24849d177c63e3f9b2bd92eb5c17c7ee0da4d798 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:29 +0100 Subject: [PATCH 020/128] rtc: pcf85363: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index ea04e9f0930b..a1fe833d2431 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -164,6 +164,7 @@ static int pcf85363_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct pcf85363 *pcf85363; + int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; @@ -193,10 +194,13 @@ static int pcf85363_probe(struct i2c_client *client, pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read; pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write; pcf85363->nvmem_cfg.priv = pcf85363; - pcf85363->rtc->nvmem_config = &pcf85363->nvmem_cfg; pcf85363->rtc->ops = &rtc_ops; - return rtc_register_device(pcf85363->rtc); + ret = rtc_register_device(pcf85363->rtc); + + rtc_nvmem_register(pcf85363->rtc, &pcf85363->nvmem_cfg); + + return ret; } static const struct of_device_id dev_ids[] = { From 0e7a412fa24c021cba7feebbc82878a44f58b33a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:30 +0100 Subject: [PATCH 021/128] rtc: pcf85363: put struct nvmem_config on the stack Avoid allocating memory for struct nvmem_config. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index a1fe833d2431..64573cccf7fe 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -80,7 +80,6 @@ static struct i2c_driver pcf85363_driver; struct pcf85363 { struct device *dev; struct rtc_device *rtc; - struct nvmem_config nvmem_cfg; struct regmap *regmap; }; @@ -164,6 +163,14 @@ static int pcf85363_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct pcf85363 *pcf85363; + struct nvmem_config nvmem_cfg = { + .name = "pcf85363-", + .word_size = 1, + .stride = 1, + .size = NVRAM_SIZE, + .reg_read = pcf85363_nvram_read, + .reg_write = pcf85363_nvram_write, + }; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) @@ -187,18 +194,12 @@ static int pcf85363_probe(struct i2c_client *client, if (IS_ERR(pcf85363->rtc)) return PTR_ERR(pcf85363->rtc); - pcf85363->nvmem_cfg.name = "pcf85363-"; - pcf85363->nvmem_cfg.word_size = 1; - pcf85363->nvmem_cfg.stride = 1; - pcf85363->nvmem_cfg.size = NVRAM_SIZE; - pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read; - pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write; - pcf85363->nvmem_cfg.priv = pcf85363; pcf85363->rtc->ops = &rtc_ops; ret = rtc_register_device(pcf85363->rtc); - rtc_nvmem_register(pcf85363->rtc, &pcf85363->nvmem_cfg); + nvmem_cfg.priv = pcf85363; + rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg); return ret; } From 88d3aadea0c72bc9bfaec2504b331134056e9bce Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:31 +0100 Subject: [PATCH 022/128] rtc: rv8803: call rtc_nvmem_register() Call rtc_nvmem_register instead of letting the core do it and stop using the nvmem_config member of struct rtc_device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index aae2576741a6..c10132d8cf2e 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -591,12 +591,13 @@ static int rv8803_probe(struct i2c_client *client, rv8803->nvmem_cfg.priv = client; rv8803->rtc->ops = &rv8803_rtc_ops; - rv8803->rtc->nvmem_config = &rv8803->nvmem_cfg; rv8803->rtc->nvram_old_abi = true; err = rtc_register_device(rv8803->rtc); if (err) return err; + rtc_nvmem_register(rv8803->rtc, &rv8803->nvmem_cfg); + err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); if (err) return err; From c07fd9dea2fab9f4b1f246b766e124606cef187f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:32 +0100 Subject: [PATCH 023/128] rtc: rv8803: put struct nvmem_config on the stack Avoid allocating memory for struct nvmem_config. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index c10132d8cf2e..6fb5041f750b 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -68,7 +68,6 @@ struct rv8803_data { struct mutex flags_lock; u8 ctrl; enum rv8803_type type; - struct nvmem_config nvmem_cfg; }; static int rv8803_read_reg(const struct i2c_client *client, u8 reg) @@ -528,6 +527,15 @@ static int rv8803_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct rv8803_data *rv8803; int err, flags; + struct nvmem_config nvmem_cfg = { + .name = "rv8803_nvram", + .word_size = 1, + .stride = 1, + .size = 1, + .reg_read = rv8803_nvram_read, + .reg_write = rv8803_nvram_write, + .priv = client, + }; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { @@ -582,21 +590,13 @@ static int rv8803_probe(struct i2c_client *client, } } - rv8803->nvmem_cfg.name = "rv8803_nvram", - rv8803->nvmem_cfg.word_size = 1, - rv8803->nvmem_cfg.stride = 1, - rv8803->nvmem_cfg.size = 1, - rv8803->nvmem_cfg.reg_read = rv8803_nvram_read, - rv8803->nvmem_cfg.reg_write = rv8803_nvram_write, - rv8803->nvmem_cfg.priv = client; - rv8803->rtc->ops = &rv8803_rtc_ops; rv8803->rtc->nvram_old_abi = true; err = rtc_register_device(rv8803->rtc); if (err) return err; - rtc_nvmem_register(rv8803->rtc, &rv8803->nvmem_cfg); + rtc_nvmem_register(rv8803->rtc, &nvmem_cfg); err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); if (err) From ce1ae8eb83bee42c5a0dbcc01346e41c6e85da43 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:33 +0100 Subject: [PATCH 024/128] rtc: rv8803: fix possible race condition The probe function is not allowed to fail after registering the RTC. Call rtc_register_device() at the end. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 6fb5041f750b..29fc3d210392 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -590,14 +590,6 @@ static int rv8803_probe(struct i2c_client *client, } } - rv8803->rtc->ops = &rv8803_rtc_ops; - rv8803->rtc->nvram_old_abi = true; - err = rtc_register_device(rv8803->rtc); - if (err) - return err; - - rtc_nvmem_register(rv8803->rtc, &nvmem_cfg); - err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); if (err) return err; @@ -608,6 +600,14 @@ static int rv8803_probe(struct i2c_client *client, return err; } + rv8803->rtc->ops = &rv8803_rtc_ops; + rv8803->rtc->nvram_old_abi = true; + err = rtc_register_device(rv8803->rtc); + if (err) + return err; + + rtc_nvmem_register(rv8803->rtc, &nvmem_cfg); + rv8803->rtc->max_user_freq = 1; return 0; From 0391df74a608e4e65c29ddf80e704edfa8f8ef25 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:34 +0100 Subject: [PATCH 025/128] rtc: remove nvmem_config Because nvmem_config is only used and copied at nvmem registration, remove it from struct rtc_device. All the rtc drivers using nvmem are now calling rtc_nvmem_register directly. Signed-off-by: Alexandre Belloni --- drivers/rtc/class.c | 2 -- include/linux/rtc.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 0cab397f6e37..5a5ab4fa14f9 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -454,8 +454,6 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) rtc_proc_add_device(rtc); - rtc_nvmem_register(rtc, rtc->nvmem_config); - rtc->registered = true; dev_info(rtc->dev.parent, "registered as %s\n", dev_name(&rtc->dev)); diff --git a/include/linux/rtc.h b/include/linux/rtc.h index fbc92fff7c2e..37b041f72f8d 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -145,7 +145,6 @@ struct rtc_device { bool registered; - struct nvmem_config *nvmem_config; struct nvmem_device *nvmem; /* Old ABI support */ bool nvram_old_abi; From b5086150a685dcf8a3a2943eb7677a5fc4186782 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:35 +0100 Subject: [PATCH 026/128] rtc: ds1343: simplify regmap initialization Avoid using memset as gcc can properly initialize structures. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1343.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 895fbeeb47fe..b5102cdd7f61 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -599,15 +599,11 @@ static const struct rtc_class_ops ds1343_rtc_ops = { static int ds1343_probe(struct spi_device *spi) { struct ds1343_priv *priv; - struct regmap_config config; + struct regmap_config config = { .reg_bits = 8, .val_bits = 8, + .write_flag_mask = 0x80, }; unsigned int data; int res; - memset(&config, 0, sizeof(config)); - config.reg_bits = 8; - config.val_bits = 8; - config.write_flag_mask = 0x80; - priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL); if (!priv) return -ENOMEM; From 1536f6dc9d3b9d265c0333970e3a52874144b10f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:36 +0100 Subject: [PATCH 027/128] rtc: ds1343: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1343.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index b5102cdd7f61..a5a5a363c6e1 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -642,12 +642,15 @@ static int ds1343_probe(struct spi_device *spi) data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0); regmap_write(priv->map, DS1343_STATUS_REG, data); - priv->rtc = devm_rtc_device_register(&spi->dev, "ds1343", - &ds1343_rtc_ops, THIS_MODULE); - if (IS_ERR(priv->rtc)) { - dev_err(&spi->dev, "unable to register rtc ds1343\n"); + priv->rtc = devm_rtc_allocate_device(&spi->dev); + if (IS_ERR(priv->rtc)) return PTR_ERR(priv->rtc); - } + + priv->rtc->ops = &ds1343_rtc_ops; + + res = rtc_register_device(priv->rtc); + if (res) + return res; priv->irq = spi->irq; From ab392864039e7319d0be4f4fb4bbe20a8f8b544f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:37 +0100 Subject: [PATCH 028/128] rtc: ds1343: remove undocumented and useless sysfs files A documented ABI already exists to get information about the alarm. It is the only one that is used. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1343.c | 96 +--------------------------------------- 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index a5a5a363c6e1..67cae0dd8154 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -199,74 +199,6 @@ static struct bin_attribute nvram_attr = { .size = DS1343_NVRAM_LEN, }; -static ssize_t ds1343_show_alarmstatus(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ds1343_priv *priv = dev_get_drvdata(dev); - int alarmstatus, data; - - regmap_read(priv->map, DS1343_CONTROL_REG, &data); - - alarmstatus = !!(data & DS1343_A0IE); - - if (alarmstatus) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); -} - -static DEVICE_ATTR(alarm_status, S_IRUGO, ds1343_show_alarmstatus, NULL); - -static ssize_t ds1343_show_alarmmode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ds1343_priv *priv = dev_get_drvdata(dev); - int alarm_mode, data; - char *alarm_str; - - regmap_read(priv->map, DS1343_ALM0_SEC_REG, &data); - alarm_mode = (data & 0x80) >> 4; - - regmap_read(priv->map, DS1343_ALM0_MIN_REG, &data); - alarm_mode |= (data & 0x80) >> 5; - - regmap_read(priv->map, DS1343_ALM0_HOUR_REG, &data); - alarm_mode |= (data & 0x80) >> 6; - - regmap_read(priv->map, DS1343_ALM0_DAY_REG, &data); - alarm_mode |= (data & 0x80) >> 7; - - switch (alarm_mode) { - case 15: - alarm_str = "each second"; - break; - - case 7: - alarm_str = "seconds match"; - break; - - case 3: - alarm_str = "minutes and seconds match"; - break; - - case 1: - alarm_str = "hours, minutes and seconds match"; - break; - - case 0: - alarm_str = "day, hours, minutes and seconds match"; - break; - - default: - alarm_str = "invalid"; - break; - } - - return sprintf(buf, "%s\n", alarm_str); -} - -static DEVICE_ATTR(alarm_mode, S_IRUGO, ds1343_show_alarmmode, NULL); - static ssize_t ds1343_show_tricklecharger(struct device *dev, struct device_attribute *attr, char *buf) { @@ -313,7 +245,6 @@ static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL); static int ds1343_sysfs_register(struct device *dev) { - struct ds1343_priv *priv = dev_get_drvdata(dev); int err; err = device_create_file(dev, &dev_attr_glitch_filter); @@ -325,26 +256,9 @@ static int ds1343_sysfs_register(struct device *dev) goto error1; err = device_create_bin_file(dev, &nvram_attr); - if (err) - goto error2; - - if (priv->irq <= 0) - return err; - - err = device_create_file(dev, &dev_attr_alarm_mode); - if (err) - goto error3; - - err = device_create_file(dev, &dev_attr_alarm_status); if (!err) - return err; + return 0; - device_remove_file(dev, &dev_attr_alarm_mode); - -error3: - device_remove_bin_file(dev, &nvram_attr); - -error2: device_remove_file(dev, &dev_attr_trickle_charger); error1: @@ -355,17 +269,9 @@ error1: static void ds1343_sysfs_unregister(struct device *dev) { - struct ds1343_priv *priv = dev_get_drvdata(dev); - device_remove_file(dev, &dev_attr_glitch_filter); device_remove_file(dev, &dev_attr_trickle_charger); device_remove_bin_file(dev, &nvram_attr); - - if (priv->irq <= 0) - return; - - device_remove_file(dev, &dev_attr_alarm_status); - device_remove_file(dev, &dev_attr_alarm_mode); } static int ds1343_read_time(struct device *dev, struct rtc_time *dt) From d7501f709410f6813e84ecd5a28e7dc8f47ff792 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:38 +0100 Subject: [PATCH 029/128] rtc: ds1343: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1343.c | 66 ++++++++++++---------------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 67cae0dd8154..59d27db2fd37 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -153,52 +153,22 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev, static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, ds1343_store_glitchfilter); -static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1343_nvram_write(void *priv, unsigned int off, void *val, + size_t bytes) { - int ret; - unsigned char address; - struct device *dev = kobj_to_dev(kobj); - struct ds1343_priv *priv = dev_get_drvdata(dev); + struct ds1343_priv *ds1343 = priv; - address = DS1343_NVRAM + off; - - ret = regmap_bulk_write(priv->map, address, buf, count); - if (ret < 0) - dev_err(&priv->spi->dev, "Error in nvram write %d", ret); - - return (ret < 0) ? ret : count; + return regmap_bulk_write(ds1343->map, DS1343_NVRAM + off, val, bytes); } - -static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1343_nvram_read(void *priv, unsigned int off, void *val, + size_t bytes) { - int ret; - unsigned char address; - struct device *dev = kobj_to_dev(kobj); - struct ds1343_priv *priv = dev_get_drvdata(dev); + struct ds1343_priv *ds1343 = priv; - address = DS1343_NVRAM + off; - - ret = regmap_bulk_read(priv->map, address, buf, count); - if (ret < 0) - dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret); - - return (ret < 0) ? ret : count; + return regmap_bulk_read(ds1343->map, DS1343_NVRAM + off, val, bytes); } - -static struct bin_attribute nvram_attr = { - .attr.name = "nvram", - .attr.mode = S_IRUGO | S_IWUSR, - .read = ds1343_nvram_read, - .write = ds1343_nvram_write, - .size = DS1343_NVRAM_LEN, -}; - static ssize_t ds1343_show_tricklecharger(struct device *dev, struct device_attribute *attr, char *buf) { @@ -252,16 +222,9 @@ static int ds1343_sysfs_register(struct device *dev) return err; err = device_create_file(dev, &dev_attr_trickle_charger); - if (err) - goto error1; - - err = device_create_bin_file(dev, &nvram_attr); if (!err) return 0; - device_remove_file(dev, &dev_attr_trickle_charger); - -error1: device_remove_file(dev, &dev_attr_glitch_filter); return err; @@ -271,7 +234,6 @@ static void ds1343_sysfs_unregister(struct device *dev) { device_remove_file(dev, &dev_attr_glitch_filter); device_remove_file(dev, &dev_attr_trickle_charger); - device_remove_bin_file(dev, &nvram_attr); } static int ds1343_read_time(struct device *dev, struct rtc_time *dt) @@ -509,6 +471,14 @@ static int ds1343_probe(struct spi_device *spi) .write_flag_mask = 0x80, }; unsigned int data; int res; + struct nvmem_config nvmem_cfg = { + .name = "ds1343-", + .word_size = 1, + .stride = 1, + .size = DS1343_NVRAM_LEN, + .reg_read = ds1343_nvram_read, + .reg_write = ds1343_nvram_write, + }; priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL); if (!priv) @@ -552,12 +522,16 @@ static int ds1343_probe(struct spi_device *spi) if (IS_ERR(priv->rtc)) return PTR_ERR(priv->rtc); + priv->rtc->nvram_old_abi = true; priv->rtc->ops = &ds1343_rtc_ops; res = rtc_register_device(priv->rtc); if (res) return res; + nvmem_cfg.priv = priv; + rtc_nvmem_register(priv->rtc, &nvmem_cfg); + priv->irq = spi->irq; if (priv->irq >= 0) { From affb842b84a27d12ab7fd0a86cefda0a343f0941 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:39 +0100 Subject: [PATCH 030/128] rtc: m48t59: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t59.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index d99a705bec07..e248e56ff8a1 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -480,11 +480,16 @@ static int m48t59_rtc_probe(struct platform_device *pdev) spin_lock_init(&m48t59->lock); platform_set_drvdata(pdev, m48t59); - m48t59->rtc = devm_rtc_device_register(&pdev->dev, name, ops, - THIS_MODULE); + m48t59->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(m48t59->rtc)) return PTR_ERR(m48t59->rtc); + m48t59->rtc->ops = ops; + + ret = rtc_register_device(m48t59->rtc); + if (ret) + return ret; + m48t59_nvram_attr.size = pdata->offset; ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); From 0ff3565d88cde06c4ce20c55e7ce23050e1d6a0d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:40 +0100 Subject: [PATCH 031/128] rtc: m48t59: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t59.c | 60 +++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index e248e56ff8a1..d2ba7d76dbb9 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -334,16 +334,16 @@ static const struct rtc_class_ops m48t02_rtc_ops = { .set_time = m48t59_rtc_set_time, }; -static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int m48t59_nvram_read(void *priv, unsigned int offset, void *val, + size_t size) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); + struct platform_device *pdev = priv; + struct device *dev = &pdev->dev; struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev); ssize_t cnt = 0; unsigned long flags; + u8 *buf = val; spin_lock_irqsave(&m48t59->lock, flags); @@ -352,19 +352,19 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, spin_unlock_irqrestore(&m48t59->lock, flags); - return cnt; + return 0; } -static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int m48t59_nvram_write(void *priv, unsigned int offset, void *val, + size_t size) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); + struct platform_device *pdev = priv; + struct device *dev = &pdev->dev; struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev); ssize_t cnt = 0; unsigned long flags; + u8 *buf = val; spin_lock_irqsave(&m48t59->lock, flags); @@ -373,18 +373,9 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, spin_unlock_irqrestore(&m48t59->lock, flags); - return cnt; + return 0; } -static struct bin_attribute m48t59_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - .read = m48t59_nvram_read, - .write = m48t59_nvram_write, -}; - static int m48t59_rtc_probe(struct platform_device *pdev) { struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); @@ -393,6 +384,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev) int ret = -ENOMEM; char *name; const struct rtc_class_ops *ops; + struct nvmem_config nvmem_cfg = { + .name = "m48t59-", + .word_size = 1, + .stride = 1, + .reg_read = m48t59_nvram_read, + .reg_write = m48t59_nvram_write, + .priv = pdev, + }; /* This chip could be memory-mapped or I/O-mapped */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -484,24 +483,18 @@ static int m48t59_rtc_probe(struct platform_device *pdev) if (IS_ERR(m48t59->rtc)) return PTR_ERR(m48t59->rtc); + m48t59->rtc->nvram_old_abi = true; m48t59->rtc->ops = ops; + nvmem_cfg.size = pdata->offset; + ret = rtc_nvmem_register(m48t59->rtc, &nvmem_cfg); + if (ret) + return ret; + ret = rtc_register_device(m48t59->rtc); if (ret) return ret; - m48t59_nvram_attr.size = pdata->offset; - - ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); - if (ret) - return ret; - - return 0; -} - -static int m48t59_rtc_remove(struct platform_device *pdev) -{ - sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); return 0; } @@ -513,7 +506,6 @@ static struct platform_driver m48t59_rtc_driver = { .name = "rtc-m48t59", }, .probe = m48t59_rtc_probe, - .remove = m48t59_rtc_remove, }; module_platform_driver(m48t59_rtc_driver); From 11ad0b613d35f74dd8453d09b71dc2f0af7cf3e0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:41 +0100 Subject: [PATCH 032/128] rtc: sirfsoc: remove useless sirfsoc_rtc_ioctl sirfsoc_rtc_ioctl() doesn't implement any actual ioctl, remove it. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sirfsoc.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c index 7367f617145c..2a9e151cae99 100644 --- a/drivers/rtc/rtc-sirfsoc.c +++ b/drivers/rtc/rtc-sirfsoc.c @@ -204,23 +204,6 @@ static int sirfsoc_rtc_set_time(struct device *dev, return 0; } -static int sirfsoc_rtc_ioctl(struct device *dev, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { - case RTC_PIE_ON: - case RTC_PIE_OFF: - case RTC_UIE_ON: - case RTC_UIE_OFF: - case RTC_AIE_ON: - case RTC_AIE_OFF: - return 0; - - default: - return -ENOIOCTLCMD; - } -} - static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { @@ -250,7 +233,6 @@ static const struct rtc_class_ops sirfsoc_rtc_ops = { .set_time = sirfsoc_rtc_set_time, .read_alarm = sirfsoc_rtc_read_alarm, .set_alarm = sirfsoc_rtc_set_alarm, - .ioctl = sirfsoc_rtc_ioctl, .alarm_irq_enable = sirfsoc_rtc_alarm_irq_enable }; From 18c88cc9b0483c78562a0192779ec4d7ddc5dcf5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:42 +0100 Subject: [PATCH 033/128] rtc: ds1553: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1553.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 9961ec646fd2..59eab5eceafa 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -308,11 +308,16 @@ static int ds1553_rtc_probe(struct platform_device *pdev) pdata->last_jiffies = jiffies; platform_set_drvdata(pdev, pdata); - pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &ds1553_rtc_ops, THIS_MODULE); + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(pdata->rtc)) return PTR_ERR(pdata->rtc); + pdata->rtc->ops = &ds1553_rtc_ops; + + ret = rtc_register_device(pdata->rtc); + if (ret) + return ret; + if (pdata->irq > 0) { writeb(0, ioaddr + RTC_INTERRUPTS); if (devm_request_irq(&pdev->dev, pdata->irq, From 3a9a06d44bf75a1e0752e2de686729fb2a85ad22 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:43 +0100 Subject: [PATCH 034/128] rtc: ds1553: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1553.c | 55 ++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 59eab5eceafa..6205c28e0cdc 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -233,46 +233,32 @@ static const struct rtc_class_ops ds1553_rtc_ops = { .alarm_irq_enable = ds1553_rtc_alarm_irq_enable, }; -static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int ds1553_nvram_read(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); + struct platform_device *pdev = priv; struct rtc_plat_data *pdata = platform_get_drvdata(pdev); void __iomem *ioaddr = pdata->ioaddr; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) *buf++ = readb(ioaddr + pos++); - return count; + return 0; } -static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int ds1553_nvram_write(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); + struct platform_device *pdev = priv; struct rtc_plat_data *pdata = platform_get_drvdata(pdev); void __iomem *ioaddr = pdata->ioaddr; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) writeb(*buf++, ioaddr + pos++); - return count; + return 0; } -static struct bin_attribute ds1553_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - .size = RTC_OFFSET, - .read = ds1553_nvram_read, - .write = ds1553_nvram_write, -}; - static int ds1553_rtc_probe(struct platform_device *pdev) { struct resource *res; @@ -280,6 +266,15 @@ static int ds1553_rtc_probe(struct platform_device *pdev) struct rtc_plat_data *pdata; void __iomem *ioaddr; int ret = 0; + struct nvmem_config nvmem_cfg = { + .name = "ds1553_nvram", + .word_size = 1, + .stride = 1, + .size = RTC_OFFSET, + .reg_read = ds1553_nvram_read, + .reg_write = ds1553_nvram_write, + .priv = pdev, + }; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -313,6 +308,7 @@ static int ds1553_rtc_probe(struct platform_device *pdev) return PTR_ERR(pdata->rtc); pdata->rtc->ops = &ds1553_rtc_ops; + pdata->rtc->nvram_old_abi = true; ret = rtc_register_device(pdata->rtc); if (ret) @@ -328,10 +324,8 @@ static int ds1553_rtc_probe(struct platform_device *pdev) } } - ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); - if (ret) - dev_err(&pdev->dev, "unable to create sysfs file: %s\n", - ds1553_nvram_attr.attr.name); + if (rtc_nvmem_register(pdata->rtc, &nvmem_cfg)) + dev_err(&pdev->dev, "unable to register nvmem\n"); return 0; } @@ -340,7 +334,6 @@ static int ds1553_rtc_remove(struct platform_device *pdev) { struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); if (pdata->irq > 0) writeb(0, pdata->ioaddr + RTC_INTERRUPTS); return 0; From 1af7068d2a19d333e9280f8a43bc7215c90bfb91 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:44 +0100 Subject: [PATCH 035/128] rtc: ds1553: make alarms useful 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 wakeup the platform. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1553.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 6205c28e0cdc..7334c824371a 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -330,21 +330,11 @@ static int ds1553_rtc_probe(struct platform_device *pdev) return 0; } -static int ds1553_rtc_remove(struct platform_device *pdev) -{ - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - - if (pdata->irq > 0) - writeb(0, pdata->ioaddr + RTC_INTERRUPTS); - return 0; -} - /* work with hotplug and coldplug */ MODULE_ALIAS("platform:rtc-ds1553"); static struct platform_driver ds1553_rtc_driver = { .probe = ds1553_rtc_probe, - .remove = ds1553_rtc_remove, .driver = { .name = "rtc-ds1553", }, From 53d29e0a3afe0567db9e4360e8523b092eb2d4e4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:45 +0100 Subject: [PATCH 036/128] rtc: cmos: fix possible race condition The probe function is not allowed to fail after registering the RTC 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 register the rtc as late as possible. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 9dca53df3584..e6393e784d0c 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -751,8 +751,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) cmos_rtc.dev = dev; dev_set_drvdata(dev, &cmos_rtc); - cmos_rtc.rtc = rtc_device_register(driver_name, dev, - &cmos_rtc_ops, THIS_MODULE); + cmos_rtc.rtc = devm_rtc_allocate_device(dev); if (IS_ERR(cmos_rtc.rtc)) { retval = PTR_ERR(cmos_rtc.rtc); goto cleanup0; @@ -822,6 +821,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) goto cleanup2; } + cmos_rtc.rtc->ops = &cmos_rtc_ops; + retval = rtc_register_device(cmos_rtc.rtc); + if (retval) + goto cleanup3; + dev_info(dev, "%s%s, %zd bytes nvram%s\n", !is_valid_irq(rtc_irq) ? "no alarms" : cmos_rtc.mon_alrm ? "alarms up to one year" : @@ -833,12 +837,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) return 0; +cleanup3: + sysfs_remove_bin_file(&dev->kobj, &nvram); cleanup2: if (is_valid_irq(rtc_irq)) free_irq(rtc_irq, cmos_rtc.rtc); cleanup1: cmos_rtc.dev = NULL; - rtc_device_unregister(cmos_rtc.rtc); cleanup0: if (RTC_IOMAPPED) release_region(ports->start, resource_size(ports)); @@ -869,7 +874,6 @@ static void cmos_do_remove(struct device *dev) hpet_unregister_irq_handler(cmos_interrupt); } - rtc_device_unregister(cmos->rtc); cmos->rtc = NULL; ports = cmos->iomem; From 8b5b7958fd1cac54bdca62ec5552c6be0b38def4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:46 +0100 Subject: [PATCH 037/128] rtc: cmos: use generic nvmem Instead of adding a binary sysfs attribute from the driver, use the core to register an nvmem device. This allows to use the in-kernel interface to access the nvram. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 73 +++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index e6393e784d0c..b8ec6009171a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -541,11 +541,10 @@ static const struct rtc_class_ops cmos_rtc_ops = { #define NVRAM_OFFSET (RTC_REG_D + 1) -static ssize_t -cmos_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int cmos_nvram_read(void *priv, unsigned int off, void *val, + size_t count) { + unsigned char *buf = val; int retval; off += NVRAM_OFFSET; @@ -563,16 +562,13 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj, return retval; } -static ssize_t -cmos_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int cmos_nvram_write(void *priv, unsigned int off, void *val, + size_t count) { - struct cmos_rtc *cmos; + struct cmos_rtc *cmos = priv; + unsigned char *buf = val; int retval; - cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); - /* NOTE: on at least PCs and Ataris, the boot firmware uses a * checksum on part of the NVRAM data. That's currently ignored * here. If userspace is smart enough to know what fields of @@ -598,17 +594,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj, return retval; } -static struct bin_attribute nvram = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - - .read = cmos_nvram_read, - .write = cmos_nvram_write, - /* size gets set up later */ -}; - /*----------------------------------------------------------------*/ static struct cmos_rtc cmos_rtc; @@ -675,6 +660,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) unsigned char rtc_control; unsigned address_space; u32 flags = 0; + struct nvmem_config nvmem_cfg = { + .name = "cmos_nvram", + .word_size = 1, + .stride = 1, + .reg_read = cmos_nvram_read, + .reg_write = cmos_nvram_write, + .priv = &cmos_rtc, + }; /* there can be only one ... */ if (cmos_rtc.dev) @@ -813,32 +806,28 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) } } - /* export at least the first block of NVRAM */ - nvram.size = address_space - NVRAM_OFFSET; - retval = sysfs_create_bin_file(&dev->kobj, &nvram); - if (retval < 0) { - dev_dbg(dev, "can't create nvram file? %d\n", retval); - goto cleanup2; - } - cmos_rtc.rtc->ops = &cmos_rtc_ops; + cmos_rtc.rtc->nvram_old_abi = true; retval = rtc_register_device(cmos_rtc.rtc); if (retval) - goto cleanup3; + goto cleanup2; - dev_info(dev, "%s%s, %zd bytes nvram%s\n", - !is_valid_irq(rtc_irq) ? "no alarms" : - cmos_rtc.mon_alrm ? "alarms up to one year" : - cmos_rtc.day_alrm ? "alarms up to one month" : - "alarms up to one day", - cmos_rtc.century ? ", y3k" : "", - nvram.size, - is_hpet_enabled() ? ", hpet irqs" : ""); + /* export at least the first block of NVRAM */ + nvmem_cfg.size = address_space - NVRAM_OFFSET; + if (rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg)) + dev_err(dev, "nvmem registration failed\n"); + + dev_info(dev, "%s%s, %d bytes nvram%s\n", + !is_valid_irq(rtc_irq) ? "no alarms" : + cmos_rtc.mon_alrm ? "alarms up to one year" : + cmos_rtc.day_alrm ? "alarms up to one month" : + "alarms up to one day", + cmos_rtc.century ? ", y3k" : "", + nvmem_cfg.size, + is_hpet_enabled() ? ", hpet irqs" : ""); return 0; -cleanup3: - sysfs_remove_bin_file(&dev->kobj, &nvram); cleanup2: if (is_valid_irq(rtc_irq)) free_irq(rtc_irq, cmos_rtc.rtc); @@ -867,8 +856,6 @@ static void cmos_do_remove(struct device *dev) cmos_do_shutdown(cmos->irq); - sysfs_remove_bin_file(&dev->kobj, &nvram); - if (is_valid_irq(cmos->irq)) { free_irq(cmos->irq, cmos->rtc); hpet_unregister_irq_handler(cmos_interrupt); From 1358e7b2b3312372ba231f6c94902a8dbfc7d2db Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:47 +0100 Subject: [PATCH 038/128] rtc: ds1742: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1742.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 3abf1cbfb8ce..84e19fe2ca3b 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -196,11 +196,17 @@ static int ds1742_rtc_probe(struct platform_device *pdev) pdata->last_jiffies = jiffies; platform_set_drvdata(pdev, pdata); - rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &ds1742_rtc_ops, THIS_MODULE); + + rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + rtc->ops = &ds1742_rtc_ops; + + ret = rtc_register_device(rtc); + if (ret) + return ret; + ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); if (ret) dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", From 87c78d9512cb85c286de5a8941eaeda8ca6f7bac Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:48 +0100 Subject: [PATCH 039/128] rtc: ds1742: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1742.c | 67 ++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 84e19fe2ca3b..52baf925a690 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -53,9 +53,7 @@ struct rtc_plat_data { void __iomem *ioaddr_nvram; void __iomem *ioaddr_rtc; - size_t size_nvram; unsigned long last_jiffies; - struct bin_attribute nvram_attr; }; static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -122,34 +120,28 @@ static const struct rtc_class_ops ds1742_rtc_ops = { .set_time = ds1742_rtc_set_time, }; -static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int ds1742_nvram_read(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = priv; void __iomem *ioaddr = pdata->ioaddr_nvram; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) *buf++ = readb(ioaddr + pos++); - return count; + return 0; } -static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int ds1742_nvram_write(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = priv; void __iomem *ioaddr = pdata->ioaddr_nvram; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) writeb(*buf++, ioaddr + pos++); - return count; + return 0; } static int ds1742_rtc_probe(struct platform_device *pdev) @@ -160,6 +152,14 @@ static int ds1742_rtc_probe(struct platform_device *pdev) struct rtc_plat_data *pdata; void __iomem *ioaddr; 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, + }; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -171,15 +171,10 @@ static int ds1742_rtc_probe(struct platform_device *pdev) return PTR_ERR(ioaddr); pdata->ioaddr_nvram = ioaddr; - pdata->size_nvram = resource_size(res) - RTC_SIZE; - pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; + pdata->ioaddr_rtc = ioaddr + resource_size(res) - RTC_SIZE; - sysfs_bin_attr_init(&pdata->nvram_attr); - pdata->nvram_attr.attr.name = "nvram"; - pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; - pdata->nvram_attr.read = ds1742_nvram_read; - pdata->nvram_attr.write = ds1742_nvram_write; - pdata->nvram_attr.size = pdata->size_nvram; + nvmem_cfg.size = resource_size(res) - RTC_SIZE; + nvmem_cfg.priv = pdata; /* turn RTC on if it was not on */ ioaddr = pdata->ioaddr_rtc; @@ -202,27 +197,18 @@ static int ds1742_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc); rtc->ops = &ds1742_rtc_ops; + rtc->nvram_old_abi = true; ret = rtc_register_device(rtc); if (ret) return ret; - ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); - if (ret) - dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", - pdata->nvram_attr.attr.name); + if (rtc_nvmem_register(rtc, &nvmem_cfg)) + dev_err(&pdev->dev, "Unable to register nvmem\n"); return 0; } -static int ds1742_rtc_remove(struct platform_device *pdev) -{ - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - - sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); - return 0; -} - static const struct of_device_id __maybe_unused ds1742_rtc_of_match[] = { { .compatible = "maxim,ds1742", }, { } @@ -231,7 +217,6 @@ MODULE_DEVICE_TABLE(of, ds1742_rtc_of_match); static struct platform_driver ds1742_rtc_driver = { .probe = ds1742_rtc_probe, - .remove = ds1742_rtc_remove, .driver = { .name = "rtc-ds1742", .of_match_table = of_match_ptr(ds1742_rtc_of_match), From bcdd559268039d8340d38fa58668393596e29fdc Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:49 +0100 Subject: [PATCH 040/128] rtc: rp5c01: fix possible race condition The probe function is not allowed to fail after registering the RTC 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 register the rtc as late as possible. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rp5c01.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index 026035373ae6..38a12435b5a0 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c @@ -249,16 +249,24 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) platform_set_drvdata(dev, priv); - rtc = devm_rtc_device_register(&dev->dev, "rtc-rp5c01", &rp5c01_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_allocate_device(&dev->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + + rtc->ops = &rp5c01_rtc_ops; + priv->rtc = rtc; error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); if (error) return error; + error = rtc_register_device(rtc); + if (error) { + sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); + return error; + } + return 0; } From 7335fb9be32409c43d81c806c14220d4fcb0227f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:50 +0100 Subject: [PATCH 041/128] rtc: rp5c01: use generic nvmem Instead of adding a binary sysfs attribute from the driver, use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rp5c01.c | 65 +++++++++++++++------------------------- 1 file changed, 24 insertions(+), 41 deletions(-) diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index 38a12435b5a0..043b1667b41a 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c @@ -64,7 +64,6 @@ struct rp5c01_priv { u32 __iomem *regs; struct rtc_device *rtc; spinlock_t lock; /* against concurrent RTC/NVRAM access */ - struct bin_attribute nvram_attr; }; static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, @@ -160,17 +159,15 @@ static const struct rtc_class_ops rp5c01_rtc_ops = { * byte is stored in BLOCK10, the low nibble in BLOCK11. */ -static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int rp5c01_nvram_read(void *_priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct rp5c01_priv *priv = dev_get_drvdata(dev); - ssize_t count; + struct rp5c01_priv *priv = _priv; + u8 *buf = val; spin_lock_irq(&priv->lock); - for (count = 0; count < size; count++) { + for (; bytes; bytes--) { u8 data; rp5c01_write(priv, @@ -187,20 +184,18 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, } spin_unlock_irq(&priv->lock); - return count; + return 0; } -static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int rp5c01_nvram_write(void *_priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct rp5c01_priv *priv = dev_get_drvdata(dev); - ssize_t count; + struct rp5c01_priv *priv = _priv; + u8 *buf = val; spin_lock_irq(&priv->lock); - for (count = 0; count < size; count++) { + for (; bytes; bytes--) { u8 data = *buf++; rp5c01_write(priv, @@ -216,7 +211,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, } spin_unlock_irq(&priv->lock); - return count; + return 0; } static int __init rp5c01_rtc_probe(struct platform_device *dev) @@ -225,6 +220,14 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) struct rp5c01_priv *priv; struct rtc_device *rtc; int error; + struct nvmem_config nvmem_cfg = { + .name = "rp5c01_nvram", + .word_size = 1, + .stride = 1, + .size = RP5C01_MODE, + .reg_read = rp5c01_nvram_read, + .reg_write = rp5c01_nvram_write, + }; res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) @@ -238,13 +241,6 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) if (!priv->regs) return -ENOMEM; - sysfs_bin_attr_init(&priv->nvram_attr); - priv->nvram_attr.attr.name = "nvram"; - priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; - priv->nvram_attr.read = rp5c01_nvram_read; - priv->nvram_attr.write = rp5c01_nvram_write; - priv->nvram_attr.size = RP5C01_MODE; - spin_lock_init(&priv->lock); platform_set_drvdata(dev, priv); @@ -254,35 +250,22 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) return PTR_ERR(rtc); rtc->ops = &rp5c01_rtc_ops; + rtc->nvram_old_abi = true; priv->rtc = rtc; - error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); + nvmem_cfg.priv = priv; + error = rtc_nvmem_register(rtc, &nvmem_cfg); if (error) return error; - error = rtc_register_device(rtc); - if (error) { - sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); - return error; - } - - return 0; -} - -static int __exit rp5c01_rtc_remove(struct platform_device *dev) -{ - struct rp5c01_priv *priv = platform_get_drvdata(dev); - - sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); - return 0; + return rtc_register_device(rtc); } static struct platform_driver rp5c01_rtc_driver = { .driver = { .name = "rtc-rp5c01", }, - .remove = __exit_p(rp5c01_rtc_remove), }; module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe); From 8f21092d65fd83e7a227c3aa88b79b3ec33a9b6e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:51 +0100 Subject: [PATCH 042/128] rtc: stk17ta8: make alarms useful 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 wakeup the platform. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stk17ta8.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index a456cb6177ea..39a80491e567 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -340,11 +340,8 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) static int stk17ta8_rtc_remove(struct platform_device *pdev) { - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); - if (pdata->irq > 0) - writeb(0, pdata->ioaddr + RTC_INTERRUPTS); + return 0; } From 91cb6774f6355eff527544181d2bfad1b7d054cf Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:52 +0100 Subject: [PATCH 043/128] rtc: stk17ta8: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stk17ta8.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 39a80491e567..f936accf622f 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -328,11 +328,16 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) } } - pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &stk17ta8_rtc_ops, THIS_MODULE); + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(pdata->rtc)) return PTR_ERR(pdata->rtc); + pdata->rtc->ops = &stk17ta8_rtc_ops; + + ret = rtc_register_device(pdata->rtc); + if (ret) + return ret; + ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); return ret; From 8d3e6b55cedaeadd1216d4b548f346c169099f1f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:53 +0100 Subject: [PATCH 044/128] rtc: stk17ta8: fix possible race condition The probe function is not allowed to fail after registering the RTC. Call rtc_register_device() at the end. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stk17ta8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index f936accf622f..1d6febbe7d39 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -334,11 +334,11 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) pdata->rtc->ops = &stk17ta8_rtc_ops; - ret = rtc_register_device(pdata->rtc); + ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); if (ret) return ret; - ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); + ret = rtc_register_device(pdata->rtc); return ret; } From d7ca4299d7c035969652596f0daa76407f6cfbdd Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:54 +0100 Subject: [PATCH 045/128] rtc: stk17ta8: use generic nvmem Instead of adding a binary sysfs attribute from the driver, use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stk17ta8.c | 64 ++++++++++++++------------------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 1d6febbe7d39..01a3bef77aa5 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -242,46 +242,30 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, }; -static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t pos, size_t size) +static int stk17ta8_nvram_read(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = priv; void __iomem *ioaddr = pdata->ioaddr; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) *buf++ = readb(ioaddr + pos++); - return count; + return 0; } -static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t pos, size_t size) +static int stk17ta8_nvram_write(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + struct rtc_plat_data *pdata = priv; void __iomem *ioaddr = pdata->ioaddr; - ssize_t count; + u8 *buf = val; - for (count = 0; count < size; count++) + for (; bytes; bytes--) writeb(*buf++, ioaddr + pos++); - return count; + return 0; } -static struct bin_attribute stk17ta8_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - .size = RTC_OFFSET, - .read = stk17ta8_nvram_read, - .write = stk17ta8_nvram_write, -}; - static int stk17ta8_rtc_probe(struct platform_device *pdev) { struct resource *res; @@ -290,6 +274,14 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) struct rtc_plat_data *pdata; void __iomem *ioaddr; int ret = 0; + struct nvmem_config nvmem_cfg = { + .name = "stk17ta8_nvram", + .word_size = 1, + .stride = 1, + .size = RTC_OFFSET, + .reg_read = stk17ta8_nvram_read, + .reg_write = stk17ta8_nvram_write, + }; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -333,21 +325,14 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) return PTR_ERR(pdata->rtc); pdata->rtc->ops = &stk17ta8_rtc_ops; + pdata->rtc->nvram_old_abi = true; - ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); + nvmem_cfg.priv = pdata; + ret = rtc_nvmem_register(pdata->rtc, &nvmem_cfg); if (ret) return ret; - ret = rtc_register_device(pdata->rtc); - - return ret; -} - -static int stk17ta8_rtc_remove(struct platform_device *pdev) -{ - sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); - - return 0; + return rtc_register_device(pdata->rtc); } /* work with hotplug and coldplug */ @@ -355,7 +340,6 @@ MODULE_ALIAS("platform:stk17ta8"); static struct platform_driver stk17ta8_rtc_driver = { .probe = stk17ta8_rtc_probe, - .remove = stk17ta8_rtc_remove, .driver = { .name = "stk17ta8", }, From a0151062ead35b3cc100a2b99b5c87b700ee52c0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:55 +0100 Subject: [PATCH 046/128] rtc: tx4939: remove arch/mips dependency Copy RTC definitions from arch/mips/include/asm/txx9/tx4939.h to the RTC driver so it doesn't depend on arch/mips anymore. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 560d9a5e0225..1f4013d8ae7b 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -14,7 +14,30 @@ #include #include #include -#include + +#define TX4939_RTCCTL_ALME 0x00000080 +#define TX4939_RTCCTL_ALMD 0x00000040 +#define TX4939_RTCCTL_BUSY 0x00000020 + +#define TX4939_RTCCTL_COMMAND 0x00000007 +#define TX4939_RTCCTL_COMMAND_NOP 0x00000000 +#define TX4939_RTCCTL_COMMAND_GETTIME 0x00000001 +#define TX4939_RTCCTL_COMMAND_SETTIME 0x00000002 +#define TX4939_RTCCTL_COMMAND_GETALARM 0x00000003 +#define TX4939_RTCCTL_COMMAND_SETALARM 0x00000004 + +#define TX4939_RTCTBC_PM 0x00000080 +#define TX4939_RTCTBC_COMP 0x0000007f + +#define TX4939_RTC_REG_RAMSIZE 0x00000100 +#define TX4939_RTC_REG_RWBSIZE 0x00000006 + +struct tx4939_rtc_reg { + __u32 ctl; + __u32 adr; + __u32 dat; + __u32 tbc; +}; struct tx4939rtc_plat_data { struct rtc_device *rtc; From faec5f7bcca3a2e81aa7bd8412b22e808df508c3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:56 +0100 Subject: [PATCH 047/128] rtc: tx4939: extend test coverage The rtc-tx4939 driver now compiles correctly on other architectures, add COMPILE_TEST to improve code coverage. Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8ab5f0a5d323..f6d7e490e714 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1512,7 +1512,7 @@ config RTC_DRV_STARFIRE config RTC_DRV_TX4939 tristate "TX4939 SoC" - depends on SOC_TX4939 + depends on SOC_TX4939 || COMPILE_TEST help Driver for the internal RTC (Realtime Clock) module found on Toshiba TX4939 SoC. From 68981fd1515de16f8effdd39e81f9a6084a895f7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:57 +0100 Subject: [PATCH 048/128] rtc: tx4939: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 1f4013d8ae7b..75c3887fbc6c 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -283,10 +283,16 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, 0, pdev->name, &pdev->dev) < 0) return -EBUSY; - rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &tx4939_rtc_ops, THIS_MODULE); + rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + + rtc->ops = &tx4939_rtc_ops; + + ret = rtc_register_device(rtc); + if (ret) + return ret; + pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); From a2fa9b8e5abc7d16d5617996638f796fbd61cbb2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:58 +0100 Subject: [PATCH 049/128] rtc: tx4939: fix possible race condition The probe function is not allowed to fail after registering the RTC. Call rtc_register_device() at the end. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 75c3887fbc6c..5a3a6b457b8f 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -289,12 +289,13 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) rtc->ops = &tx4939_rtc_ops; - ret = rtc_register_device(rtc); + ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); if (ret) return ret; pdata->rtc = rtc; - ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); + + ret = rtc_register_device(rtc); return ret; } From dd888c61c9d4ef54d5a9884226989e3cceaacbd3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Feb 2018 23:47:59 +0100 Subject: [PATCH 050/128] rtc: tx4939: use generic nvmem Instead of adding a binary sysfs attribute from the driver, use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 59 ++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 5a3a6b457b8f..fcf837d50b70 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -212,58 +212,52 @@ static const struct rtc_class_ops tx4939_rtc_ops = { .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, }; -static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int tx4939_nvram_read(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); + struct tx4939rtc_plat_data *pdata = priv; struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; - ssize_t count; + u8 *buf = val; spin_lock_irq(&pdata->lock); - for (count = 0; count < size; count++) { + for (; bytes; bytes--) { __raw_writel(pos++, &rtcreg->adr); *buf++ = __raw_readl(&rtcreg->dat); } spin_unlock_irq(&pdata->lock); - return count; + return 0; } -static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int tx4939_nvram_write(void *priv, unsigned int pos, void *val, + size_t bytes) { - struct device *dev = container_of(kobj, struct device, kobj); - struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); + struct tx4939rtc_plat_data *pdata = priv; struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; - ssize_t count; + u8 *buf = val; spin_lock_irq(&pdata->lock); - for (count = 0; count < size; count++) { + for (; bytes; bytes--) { __raw_writel(pos++, &rtcreg->adr); __raw_writel(*buf++, &rtcreg->dat); } spin_unlock_irq(&pdata->lock); - return count; + return 0; } -static struct bin_attribute tx4939_rtc_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - .size = TX4939_RTC_REG_RAMSIZE, - .read = tx4939_rtc_nvram_read, - .write = tx4939_rtc_nvram_write, -}; - static int __init tx4939_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; struct tx4939rtc_plat_data *pdata; struct resource *res; int irq, ret; + struct nvmem_config nvmem_cfg = { + .name = "rv8803_nvram", + .word_size = 4, + .stride = 4, + .size = TX4939_RTC_REG_RAMSIZE, + .reg_read = tx4939_nvram_read, + .reg_write = tx4939_nvram_write, + }; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -288,23 +282,22 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc); rtc->ops = &tx4939_rtc_ops; - - ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); - if (ret) - return ret; + rtc->nvram_old_abi = true; pdata->rtc = rtc; - ret = rtc_register_device(rtc); + nvmem_cfg.priv = pdata; + ret = rtc_nvmem_register(rtc, &nvmem_cfg); + if (ret) + return ret; - return ret; + return rtc_register_device(rtc); } static int __exit tx4939_rtc_remove(struct platform_device *pdev) { struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); - sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); spin_lock_irq(&pdata->lock); tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); spin_unlock_irq(&pdata->lock); From 5b9fc795f90c0c509a24ba1f64d0d960f09e40da Mon Sep 17 00:00:00 2001 From: Denis Osterland Date: Tue, 23 Jan 2018 13:17:58 +0100 Subject: [PATCH 051/128] rtc: isl1208: Fix unintended clear of SR bits After successful sr = isl1208_i2c_set_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); sr will be 0. As a result sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr & ~ISL1208_REG_SR_WRTC); is equal to sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, 0); which clears all flags in SR. Add an additional read of SR, to have value of SR in sr again. Signed-off-by: Denis Osterland Signed-off-by: Michael Grzeschik Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl1208.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 8dd299c6a1f3..c8b495348229 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -459,6 +459,11 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) } /* clear WRTC again */ + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { + dev_err(&client->dev, "%s: reading SR failed\n", __func__); + return sr; + } sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr & ~ISL1208_REG_SR_WRTC); if (sr < 0) { From 588519ff16552c5a6f6a189767692db6689cadad Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 12 Feb 2018 00:38:46 -0200 Subject: [PATCH 052/128] rtc: mxc_v2: Fix _iomem pointer notation Fix the iomem pointer notation in order to fix the following sparse warnings: drivers/rtc/rtc-mxc_v2.c:280:18: warning: incorrect type in argument 1 (different address spaces) drivers/rtc/rtc-mxc_v2.c:280:18: expected void const volatile [noderef] *addr drivers/rtc/rtc-mxc_v2.c:280:18: got void *[noderef] ioaddr drivers/rtc/rtc-mxc_v2.c:329:44: warning: incorrect type in argument 1 (different address spaces) drivers/rtc/rtc-mxc_v2.c:329:44: expected void *[noderef] ioaddr drivers/rtc/rtc-mxc_v2.c:329:44: got void [noderef] * drivers/rtc/rtc-mxc_v2.c:339:44: warning: incorrect type in argument 1 (different address spaces) drivers/rtc/rtc-mxc_v2.c:339:44: expected void *[noderef] ioaddr drivers/rtc/rtc-mxc_v2.c:339:44: got void [noderef] * Signed-off-by: Fabio Estevam Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mxc_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 784221dfc9c7..9e14efb990b2 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -273,7 +273,7 @@ static const struct rtc_class_ops mxc_rtc_ops = { .alarm_irq_enable = mxc_rtc_alarm_irq_enable, }; -static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag) +static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag) { unsigned int timeout = REG_READ_TIMEOUT; From 9e7002a70e4294a093b3cacf2346af33aeefd265 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 6 Feb 2018 23:12:26 +0100 Subject: [PATCH 053/128] char: rtc: remove unused rtc_control() API Since commit 34ce71a96dcb ("ALSA: timer: remove legacy rtctimer"), the rtc_register/rtc_control/rtc_unregister API is unused. As it is highly unlikely to be needed again, remove it. Acked-by: Greg Kroah-Hartman Acked-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/char/rtc.c | 83 --------------------------------------------- include/linux/rtc.h | 4 --- 2 files changed, 87 deletions(-) diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 0c858d027bf3..57dc546628b5 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -809,89 +809,6 @@ static __poll_t rtc_poll(struct file *file, poll_table *wait) } #endif -int rtc_register(rtc_task_t *task) -{ -#ifndef RTC_IRQ - return -EIO; -#else - if (task == NULL || task->func == NULL) - return -EINVAL; - spin_lock_irq(&rtc_lock); - if (rtc_status & RTC_IS_OPEN) { - spin_unlock_irq(&rtc_lock); - return -EBUSY; - } - spin_lock(&rtc_task_lock); - if (rtc_callback) { - spin_unlock(&rtc_task_lock); - spin_unlock_irq(&rtc_lock); - return -EBUSY; - } - rtc_status |= RTC_IS_OPEN; - rtc_callback = task; - spin_unlock(&rtc_task_lock); - spin_unlock_irq(&rtc_lock); - return 0; -#endif -} -EXPORT_SYMBOL(rtc_register); - -int rtc_unregister(rtc_task_t *task) -{ -#ifndef RTC_IRQ - return -EIO; -#else - unsigned char tmp; - - spin_lock_irq(&rtc_lock); - spin_lock(&rtc_task_lock); - if (rtc_callback != task) { - spin_unlock(&rtc_task_lock); - spin_unlock_irq(&rtc_lock); - return -ENXIO; - } - rtc_callback = NULL; - - /* disable controls */ - if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) { - tmp = CMOS_READ(RTC_CONTROL); - tmp &= ~RTC_PIE; - tmp &= ~RTC_AIE; - tmp &= ~RTC_UIE; - CMOS_WRITE(tmp, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - } - if (rtc_status & RTC_TIMER_ON) { - rtc_status &= ~RTC_TIMER_ON; - del_timer(&rtc_irq_timer); - } - rtc_status &= ~RTC_IS_OPEN; - spin_unlock(&rtc_task_lock); - spin_unlock_irq(&rtc_lock); - return 0; -#endif -} -EXPORT_SYMBOL(rtc_unregister); - -int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) -{ -#ifndef RTC_IRQ - return -EIO; -#else - unsigned long flags; - if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET) - return -EINVAL; - spin_lock_irqsave(&rtc_task_lock, flags); - if (rtc_callback != task) { - spin_unlock_irqrestore(&rtc_task_lock, flags); - return -ENXIO; - } - spin_unlock_irqrestore(&rtc_task_lock, flags); - return rtc_do_ioctl(cmd, arg, 1); -#endif -} -EXPORT_SYMBOL(rtc_control); - /* * The various file operations we support. */ diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 37b041f72f8d..3b65b201169c 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -211,10 +211,6 @@ void rtc_aie_update_irq(void *private); void rtc_uie_update_irq(void *private); enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer); -int rtc_register(rtc_task_t *task); -int rtc_unregister(rtc_task_t *task); -int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); - void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data); int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer, ktime_t expires, ktime_t period); From e6a0b0f4085c9a56fa50c9666ee662d197c4707d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 16 Feb 2018 11:06:00 +0100 Subject: [PATCH 054/128] MAINTAINERS: rtc: update my email address Free Electrons is now Bootlin. Signed-off-by: Alexandre Belloni --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3bdc260e36b7..5c676c3c990f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11693,7 +11693,7 @@ X: kernel/torture.c REAL TIME CLOCK (RTC) SUBSYSTEM M: Alessandro Zummo -M: Alexandre Belloni +M: Alexandre Belloni L: linux-rtc@vger.kernel.org Q: http://patchwork.ozlabs.org/project/rtc-linux/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git From 347876ad47b9923ce26e686173bbf46581802ffa Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Feb 2018 19:36:14 +0000 Subject: [PATCH 055/128] rtc: tx4939: avoid unintended sign extension on a 24 bit shift The shifting of buf[5] by 24 bits to the left will be promoted to a 32 bit signed int and then sign-extended to an unsigned long. If the top bit of buf[5] is set then all then all the upper bits sec end up as also being set because of the sign-extension. Fix this by casting buf[5] to an unsigned long before the shift. Detected by CoverityScan, CID#1465292 ("Unintended sign extension") Fixes: 0e1492330cd2 ("rtc: add rtc-tx4939 driver") Signed-off-by: Colin Ian King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tx4939.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index fcf837d50b70..3b83cdb0b828 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -109,7 +109,8 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) for (i = 2; i < 6; i++) buf[i] = __raw_readl(&rtcreg->dat); spin_unlock_irq(&pdata->lock); - sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; + sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) | + (buf[3] << 8) | buf[2]; rtc_time_to_tm(sec, tm); return rtc_valid_tm(tm); } @@ -170,7 +171,8 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; spin_unlock_irq(&pdata->lock); - sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; + sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) | + (buf[3] << 8) | buf[2]; rtc_time_to_tm(sec, &alrm->time); return rtc_valid_tm(&alrm->time); } From 1c90d9f1c80ba28ddb61c3dbdc55ac686c073d75 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 20 Feb 2018 22:05:29 +0100 Subject: [PATCH 056/128] rtc: ds1511: let the core handle invalid time Returning a valid time when the time is invalid is a bad practice, because then userspace is not able to react on the information. Also, it doesn't make sense to return epoch because it is already the default time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 5f55214db9f8..a7d5ca428d68 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -277,10 +277,6 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon--; - if (rtc_valid_tm(rtc_tm) < 0) { - dev_err(dev, "retrieved date/time is not valid.\n"); - rtc_time_to_tm(0, rtc_tm); - } return 0; } From 7d1bd37ff06b9e7c49dc033fce4069f69ad6e564 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 20 Feb 2018 23:43:09 +0100 Subject: [PATCH 057/128] rtc: ds1553: let the core handle invalid time Returning a valid time when the time is invalid is a bad practice, because then userspace is not able to react on the information. Also, it doesn't make sense to return epoch because it is already the default time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1553.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 7334c824371a..2441b9a2b366 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -127,10 +127,6 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm) /* year is 1900 + tm->tm_year */ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; - if (rtc_valid_tm(tm) < 0) { - dev_err(dev, "retrieved date/time is not valid.\n"); - rtc_time_to_tm(0, tm); - } return 0; } From 812318a094d0715194d9f686b22ee67e7dc59d93 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:44:26 +0100 Subject: [PATCH 058/128] rtc: cmos: let the core handle invalid time Setting the rtc to a valid time when the time is invalid is a bad practice, because then userspace doesn't know it shouldn't trust the RTC. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b8ec6009171a..d98ad4874d8b 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1262,8 +1262,6 @@ MODULE_DEVICE_TABLE(of, of_cmos_match); static __init void cmos_of_init(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - struct rtc_time time; - int ret; const __be32 *val; if (!node) @@ -1276,16 +1274,6 @@ static __init void cmos_of_init(struct platform_device *pdev) val = of_get_property(node, "freq-reg", NULL); if (val) CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); - - cmos_read_time(&pdev->dev, &time); - ret = rtc_valid_tm(&time); - if (ret) { - struct rtc_time def_time = { - .tm_year = 1, - .tm_mday = 1, - }; - cmos_set_time(&pdev->dev, &def_time); - } } #else static inline void cmos_of_init(struct platform_device *pdev) {} From bff11e3aa9ccfce1a66ef05871d01c1da533f896 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:20:43 +0100 Subject: [PATCH 059/128] rtc: rs5c348: let the core handle invalid time Returning a valid time when the time is invalid is a bad practice, because then userspace is not able to react on the information. Also, it doesn't make sense to return epoch because it is already the default time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c348.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 9a306983aaba..f2de8b17e7e3 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -135,11 +135,6 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) + ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0); - if (rtc_valid_tm(tm) < 0) { - dev_err(&spi->dev, "retrieved date/time is not valid.\n"); - rtc_time_to_tm(0, tm); - } - return 0; } From bd7f4e7598921506c2ae343954fdbb764840921b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 18 Feb 2018 23:36:18 +0100 Subject: [PATCH 060/128] rtc: stk17ta8: let the core handle invalid time Returning a valid time when the time is invalid is a bad practice, because then userspace is not able to react on the information. Also, it doesn't make sense to return epoch because it is already the default time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stk17ta8.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 01a3bef77aa5..e70b78d17a98 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -129,10 +129,6 @@ static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm) /* year is 1900 + tm->tm_year */ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; - if (rtc_valid_tm(tm) < 0) { - dev_err(dev, "retrieved date/time is not valid.\n"); - rtc_time_to_tm(0, tm); - } return 0; } From 146d21bd9dc167d75bed4c0fdfe790db7565e99b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:23:55 +0100 Subject: [PATCH 061/128] rtc: stop validating rtc_time after rtc_time64_to_tm rtc_time64_to_tm never generates an invalid tm. It is not necessary to validate it. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab3100.c | 2 +- drivers/rtc/rtc-mc13xxx.c | 2 +- drivers/rtc/rtc-zynqmp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index 9b725c553058..821ff52a2222 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c @@ -106,7 +106,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time64_to_tm(time, tm); - return rtc_valid_tm(tm); + return 0; } static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 30b8ef6a3676..1f892b238ddb 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -85,7 +85,7 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm); - return rtc_valid_tm(tm); + return 0; } static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs) diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index da18a8ae3c1d..fba994dc31eb 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -122,7 +122,7 @@ static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time64_to_tm(read_time, tm); } - return rtc_valid_tm(tm); + return 0; } static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) From ab62670e57174c547abbecacf6df78d3dcf03f26 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:23:55 +0100 Subject: [PATCH 062/128] rtc: stop validating rtc_time after rtc_time_to_tm rtc_time_to_tm never generates an invalid tm. It is not necessary to validate it. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab8500.c | 2 +- drivers/rtc/rtc-coh901331.c | 2 +- drivers/rtc/rtc-jz4740.c | 2 +- drivers/rtc/rtc-lpc32xx.c | 2 +- drivers/rtc/rtc-ls1x.c | 2 +- drivers/rtc/rtc-mpc5121.c | 2 +- drivers/rtc/rtc-pcap.c | 2 +- drivers/rtc/rtc-ps3.c | 2 +- drivers/rtc/rtc-starfire.c | 2 +- drivers/rtc/rtc-tps6586x.c | 2 +- drivers/rtc/rtc-tx4939.c | 2 +- drivers/rtc/rtc-wm831x.c | 2 +- drivers/rtc/rtc-xgene.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 24a0af650a1b..98c7123cd7ba 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -131,7 +131,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) secs += get_elapsed_seconds(AB8500_RTC_EPOCH); rtc_time_to_tm(secs, tm); - return rtc_valid_tm(tm); + return 0; } static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index cfc4141d99cd..2fc517498a5d 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -82,7 +82,7 @@ static int coh901331_read_time(struct device *dev, struct rtc_time *tm) if (readl(rtap->virtbase + COH901331_VALID)) { rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); clk_disable(rtap->clk); - return rtc_valid_tm(tm); + return 0; } clk_disable(rtap->clk); return -EINVAL; diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index ff65a7d2b9c9..d0a891777f44 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -173,7 +173,7 @@ static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) rtc_time_to_tm(secs, time); - return rtc_valid_tm(time); + return 0; } static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index 887871c3d526..3ba87239aacc 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -70,7 +70,7 @@ static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); rtc_time_to_tm(elapsed_sec, time); - return rtc_valid_tm(time); + return 0; } static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index e04ca54f21e2..045af1135e48 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -98,7 +98,7 @@ static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm) ls1x_get_min(v), ls1x_get_sec(v)); rtc_time_to_tm(t, rtm); - return rtc_valid_tm(rtm); + return 0; } static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm) diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 4ca4daa0b8f3..dd0364293bc0 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -122,7 +122,7 @@ static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm) */ mpc5121_rtc_update_smh(regs, tm); - return rtc_valid_tm(tm); + return 0; } static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index c4433240d8a9..c05f524ba9af 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c @@ -95,7 +95,7 @@ static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time_to_tm(secs, tm); - return rtc_valid_tm(tm); + return 0; } static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) diff --git a/drivers/rtc/rtc-ps3.c b/drivers/rtc/rtc-ps3.c index 6a8f5d758eac..347288bff438 100644 --- a/drivers/rtc/rtc-ps3.c +++ b/drivers/rtc/rtc-ps3.c @@ -41,7 +41,7 @@ static u64 read_rtc(void) static int ps3_get_time(struct device *dev, struct rtc_time *tm) { rtc_time_to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm); - return rtc_valid_tm(tm); + return 0; } static int ps3_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c index 7fc36973fa33..a7d49329d626 100644 --- a/drivers/rtc/rtc-starfire.c +++ b/drivers/rtc/rtc-starfire.c @@ -28,7 +28,7 @@ static u32 starfire_get_time(void) static int starfire_read_time(struct device *dev, struct rtc_time *tm) { rtc_time_to_tm(starfire_get_time(), tm); - return rtc_valid_tm(tm); + return 0; } static const struct rtc_class_ops starfire_rtc_ops = { diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index a3418a8a3796..d7785ae0a2b4 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -90,7 +90,7 @@ 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); - return rtc_valid_tm(tm); + return 0; } static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 3b83cdb0b828..08dbefc79520 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -112,7 +112,7 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; rtc_time_to_tm(sec, tm); - return rtc_valid_tm(tm); + return 0; } static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 75aea4c4d334..7b824dabf104 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -156,7 +156,7 @@ static int wm831x_rtc_readtime(struct device *dev, struct rtc_time *tm) u32 time = (time1[0] << 16) | time1[1]; rtc_time_to_tm(time, tm); - return rtc_valid_tm(tm); + return 0; } } while (++count < WM831X_GET_TIME_RETRIES); diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index 0c34d3b81279..153820876a82 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -60,7 +60,7 @@ static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm) struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm); - return rtc_valid_tm(tm); + return 0; } static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs) From 22652ba72453d35c8a637d5c0f06b3dc29ff9eb0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:23:56 +0100 Subject: [PATCH 063/128] rtc: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ac100.c | 2 +- drivers/rtc/rtc-au1xxx.c | 2 +- drivers/rtc/rtc-bq32k.c | 2 +- drivers/rtc/rtc-ds1216.c | 2 +- drivers/rtc/rtc-ds1286.c | 2 +- drivers/rtc/rtc-ds1302.c | 3 +-- drivers/rtc/rtc-ds1305.c | 3 +-- drivers/rtc/rtc-ds1307.c | 3 +-- drivers/rtc/rtc-ds1343.c | 2 +- drivers/rtc/rtc-ds1347.c | 2 +- drivers/rtc/rtc-ds1390.c | 2 +- drivers/rtc/rtc-ds1685.c | 2 +- drivers/rtc/rtc-ds1742.c | 2 +- drivers/rtc/rtc-ds2404.c | 2 +- drivers/rtc/rtc-ds3232.c | 2 +- drivers/rtc/rtc-efi.c | 2 +- drivers/rtc/rtc-fm3130.c | 3 +-- drivers/rtc/rtc-isl12022.c | 2 +- drivers/rtc/rtc-lpc24xx.c | 2 +- drivers/rtc/rtc-m41t80.c | 2 +- drivers/rtc/rtc-m41t94.c | 3 +-- drivers/rtc/rtc-m48t35.c | 2 +- drivers/rtc/rtc-m48t59.c | 2 +- drivers/rtc/rtc-m48t86.c | 2 +- drivers/rtc/rtc-max6902.c | 2 +- drivers/rtc/rtc-max6916.c | 2 +- drivers/rtc/rtc-max8997.c | 2 +- drivers/rtc/rtc-max8998.c | 2 +- drivers/rtc/rtc-mcp795.c | 2 +- drivers/rtc/rtc-mrst.c | 2 +- drivers/rtc/rtc-msm6242.c | 2 +- drivers/rtc/rtc-mt7622.c | 2 +- drivers/rtc/rtc-mv.c | 2 +- drivers/rtc/rtc-pcf2123.c | 2 +- drivers/rtc/rtc-pcf2127.c | 2 +- drivers/rtc/rtc-pcf50633.c | 2 +- drivers/rtc/rtc-pcf8523.c | 2 +- drivers/rtc/rtc-pic32.c | 2 +- drivers/rtc/rtc-r9701.c | 2 +- drivers/rtc/rtc-rp5c01.c | 2 +- drivers/rtc/rtc-rx6110.c | 2 +- drivers/rtc/rtc-rx8010.c | 2 +- drivers/rtc/rtc-rx8025.c | 2 +- drivers/rtc/rtc-s3c.c | 2 +- drivers/rtc/rtc-s5m.c | 2 +- drivers/rtc/rtc-sh.c | 2 +- drivers/rtc/rtc-sun6i.c | 2 +- drivers/rtc/rtc-sunxi.c | 2 +- 48 files changed, 48 insertions(+), 53 deletions(-) diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index 8ff9dc3fe5bf..080e3c04be43 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -387,7 +387,7 @@ static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) + AC100_YEAR_OFF; - return rtc_valid_tm(rtc_tm); + return 0; } static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index 2ba44ccb9c3a..7c5530c71285 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c @@ -36,7 +36,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time_to_tm(t, tm); - return rtc_valid_tm(tm); + return 0; } static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 98ac8d5c7901..e8698e9870fe 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -110,7 +110,7 @@ static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_year = bcd2bin(regs.years) + ((regs.cent_hours & BQ32K_CENT) ? 100 : 0); - return rtc_valid_tm(tm); + return 0; } static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 9c82b1da2d45..5f158715fb4c 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c @@ -99,7 +99,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm) if (tm->tm_year < 70) tm->tm_year += 100; - return rtc_valid_tm(tm); + return 0; } static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index ef75c349dff9..0744916b79c5 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -211,7 +211,7 @@ static int ds1286_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mon--; - return rtc_valid_tm(tm); + return 0; } static int ds1286_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 43bcb17c922e..2a881150d51c 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -98,8 +98,7 @@ static int ds1302_rtc_get_time(struct device *dev, struct rtc_time *time) time->tm_mon = bcd2bin(buf[RTC_ADDR_MON]) - 1; time->tm_year = bcd2bin(buf[RTC_ADDR_YEAR]) + 100; - /* Time may not be set */ - return rtc_valid_tm(time); + return 0; } static const struct rtc_class_ops ds1302_rtc_ops = { diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 3d2400a39da9..2d502fc85698 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -203,8 +203,7 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time) time->tm_hour, time->tm_mday, time->tm_mon, time->tm_year, time->tm_wday); - /* Time may not be set */ - return rtc_valid_tm(time); + return 0; } static int ds1305_set_time(struct device *dev, struct rtc_time *time) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4021d478b9f3..a13e59edff53 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -437,8 +437,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) t->tm_hour, t->tm_mday, t->tm_mon, t->tm_year, t->tm_wday); - /* initial clock setting can be undefined */ - return rtc_valid_tm(t); + return 0; } static int ds1307_set_time(struct device *dev, struct rtc_time *t) diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 59d27db2fd37..5208da4cf94a 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -254,7 +254,7 @@ static int ds1343_read_time(struct device *dev, struct rtc_time *dt) dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */ - return rtc_valid_tm(dt); + return 0; } static int ds1343_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-ds1347.c b/drivers/rtc/rtc-ds1347.c index ccfc9d43eb1e..938512c676ee 100644 --- a/drivers/rtc/rtc-ds1347.c +++ b/drivers/rtc/rtc-ds1347.c @@ -66,7 +66,7 @@ static int ds1347_read_time(struct device *dev, struct rtc_time *dt) dt->tm_wday = bcd2bin(buf[5]) - 1; dt->tm_year = bcd2bin(buf[6]) + 100; - return rtc_valid_tm(dt); + return 0; } static int ds1347_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index 4d5b007d7fc6..3b095401f848 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -153,7 +153,7 @@ static int ds1390_read_time(struct device *dev, struct rtc_time *dt) /* adjust for century bit */ dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0); - return rtc_valid_tm(dt); + return 0; } static int ds1390_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index ed43b4311660..1a39829d2b40 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -306,7 +306,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_isdst = 0; /* RTC has hardcoded timezone, so don't use. */ - return rtc_valid_tm(tm); + return 0; } /** diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 52baf925a690..2d781180e968 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -112,7 +112,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) /* year is 1900 + tm->tm_year */ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; - return rtc_valid_tm(tm); + return 0; } static const struct rtc_class_ops ds1742_rtc_ops = { diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 9a1582ed7070..b886b6a5c178 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -207,7 +207,7 @@ static int ds2404_read_time(struct device *dev, struct rtc_time *dt) time = le32_to_cpu(time); rtc_time_to_tm(time, dt); - return rtc_valid_tm(dt); + return 0; } static int ds2404_set_mmss(struct device *dev, unsigned long secs) diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 0550f7ba464f..7184e5145f12 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -145,7 +145,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time) time->tm_year = bcd2bin(year) + add_century; - return rtc_valid_tm(time); + return 0; } static int ds3232_set_time(struct device *dev, struct rtc_time *time) diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 0130afd7fe88..3454e7814524 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -176,7 +176,7 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm) if (!convert_from_efi_time(&eft, tm)) return -EIO; - return rtc_valid_tm(tm); + return 0; } static int efi_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 576eadbba296..e1137670d4d2 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -136,8 +136,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) t->tm_hour, t->tm_mday, t->tm_mon, t->tm_year, t->tm_wday); - /* initial clock setting can be undefined */ - return rtc_valid_tm(t); + return 0; } diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 38586a024ee8..46093cd13d5e 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -149,7 +149,7 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c index 59d99596fdeb..14dc7b04fae0 100644 --- a/drivers/rtc/rtc-lpc24xx.c +++ b/drivers/rtc/rtc-lpc24xx.c @@ -110,7 +110,7 @@ static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_year = CT1_YEAR(ct1); tm->tm_yday = CT2_DOY(ct2); - return rtc_valid_tm(tm); + return 0; } static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index c90fba3ed861..1103cdc33bfa 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -230,7 +230,7 @@ static int m41t80_get_datetime(struct i2c_client *client, /* assume 20YY not 19YY, and ignore the Century Bit */ tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; - return rtc_valid_tm(tm); + return 0; } /* Sets the given date and time to the real time clock. */ diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index 1f0eb79e69f9..bab82b4be356 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -99,8 +99,7 @@ static int m41t94_read_time(struct device *dev, struct rtc_time *tm) tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - /* initial clock setting can be undefined */ - return rtc_valid_tm(tm); + return 0; } static const struct rtc_class_ops m41t94_rtc_ops = { diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 810f4ea481e4..0cf6507de3c7 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -84,7 +84,7 @@ static int m48t35_read_time(struct device *dev, struct rtc_time *tm) tm->tm_year += 100; tm->tm_mon--; - return rtc_valid_tm(tm); + return 0; } static int m48t35_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index d2ba7d76dbb9..216fac62c888 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -105,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - return rtc_valid_tm(tm); + return 0; } static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 8d17be1e6650..a9533535c3b7 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -100,7 +100,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) if (m48t86_readb(dev, M48T86_HOUR) & 0x80) tm->tm_hour += 12; - return rtc_valid_tm(tm); + return 0; } static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 315d09e0f2c1..745827463367 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -85,7 +85,7 @@ static int max6902_read_time(struct device *dev, struct rtc_time *dt) dt->tm_year += century; dt->tm_year -= 1900; - return rtc_valid_tm(dt); + return 0; } static int max6902_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c index 623ab27b2757..7e908a490cf6 100644 --- a/drivers/rtc/rtc-max6916.c +++ b/drivers/rtc/rtc-max6916.c @@ -75,7 +75,7 @@ static int max6916_read_time(struct device *dev, struct rtc_time *dt) dt->tm_wday = bcd2bin(buf[5]) - 1; dt->tm_year = bcd2bin(buf[6]) + 100; - return rtc_valid_tm(dt); + return 0; } static int max6916_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index db984d4bf952..e8cee123e8aa 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -153,7 +153,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm) max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); - return rtc_valid_tm(tm); + return 0; } static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 30804b00985e..d8c0f9b3f87d 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -120,7 +120,7 @@ static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm) max8998_data_to_tm(data, tm); - return rtc_valid_tm(tm); + return 0; } static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index 77f21331ae21..79e24eadbe99 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -262,7 +262,7 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim) tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec); - return rtc_valid_tm(tim); + return 0; } static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm) diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 7334c44fa7c3..901a8d170f68 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -105,7 +105,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time) /* Adjust for the 1972/1900 */ time->tm_year += 72; time->tm_mon--; - return rtc_valid_tm(time); + return 0; } static int mrst_set_time(struct device *dev, struct rtc_time *time) diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index c1c5c4e3b3b4..0c72a2e8ec67 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c @@ -155,7 +155,7 @@ static int msm6242_read_time(struct device *dev, struct rtc_time *tm) msm6242_unlock(priv); - return rtc_valid_tm(tm); + return 0; } static int msm6242_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c index d79b9ae4d237..da213278f343 100644 --- a/drivers/rtc/rtc-mt7622.c +++ b/drivers/rtc/rtc-mt7622.c @@ -232,7 +232,7 @@ static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm) mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC); - return rtc_valid_tm(tm); + return 0; } static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 79bb28617d45..944c5c0fadd0 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -94,7 +94,7 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm) /* hw counts from year 2000, but tm_year is relative to 1900 */ tm->tm_year = bcd2bin(year) + 100; - return rtc_valid_tm(tm); + return 0; } static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 8895f77726e8..e5222c5d8223 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -289,7 +289,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index f33447c5db85..e83be1852c2f 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -111,7 +111,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 00c31c91b245..ef72b0c389d7 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -135,7 +135,7 @@ static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); - return rtc_valid_tm(tm); + return 0; } static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index c312af0db729..453615f8ac9a 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -192,7 +192,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1; tm->tm_year = bcd2bin(regs[6]) + 100; - return rtc_valid_tm(tm); + return 0; } static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c index 5cfb6df5c430..3c08eab4f1a8 100644 --- a/drivers/rtc/rtc-pic32.c +++ b/drivers/rtc/rtc-pic32.c @@ -175,7 +175,7 @@ static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); clk_disable(pdata->clk); - return rtc_valid_tm(rtc_tm); + return 0; } static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index b6c5eb97051c..a39ccd1cf6e8 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -92,7 +92,7 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) * according to the data sheet. make sure they are valid. */ - return rtc_valid_tm(dt); + return 0; } static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index 043b1667b41a..f1c160fe7d37 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c @@ -115,7 +115,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) rp5c01_unlock(priv); spin_unlock_irq(&priv->lock); - return rtc_valid_tm(tm); + return 0; } static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index 7c9c08eab5e5..8e322d884cc2 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -252,7 +252,7 @@ static int rx6110_get_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year); - return rtc_valid_tm(tm); + return 0; } static const struct reg_sequence rx6110_default_regs[] = { diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 5c5938ab3d86..7ddc22eb5b0f 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -138,7 +138,7 @@ static int rx8010_get_time(struct device *dev, struct rtc_time *dt) dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100; dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f); - return rtc_valid_tm(dt); + return 0; } static int rx8010_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 91857d8d2df8..41127adf5765 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -214,7 +214,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt) dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_mday, dt->tm_mon, dt->tm_year); - return rtc_valid_tm(dt); + return 0; } static int rx8025_set_time(struct device *dev, struct rtc_time *dt) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a8992c227f61..75c8c5033e08 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -232,7 +232,7 @@ retry_get_time: rtc_tm->tm_mon -= 1; - return rtc_valid_tm(rtc_tm); + return 0; } static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 0477678d968f..6deae10c14ac 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -407,7 +407,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 6c2d3989f967..4e8ab370ce63 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -414,7 +414,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 5bc28eed1adf..2e6fb275acc8 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -349,7 +349,7 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) */ rtc_tm->tm_year += SUN6I_YEAR_OFF; - return rtc_valid_tm(rtc_tm); + return 0; } static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index abada609ddc7..dadbf8b324ad 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -261,7 +261,7 @@ static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) */ rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); - return rtc_valid_tm(rtc_tm); + return 0; } static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) From ce2e5a7613c64ac919d403fd957a472a0f12360e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:23:54 +0100 Subject: [PATCH 064/128] rtc: ab-b5ze-s3: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab-b5ze-s3.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index a319bf1e49de..e55f35fa0b58 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -217,7 +217,7 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN]; - int ret; + int ret = 0; /* * As we need to read CTRL1 register anyway to access 24/12h @@ -255,8 +255,6 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mon = bcd2bin(regs[ABB5ZES3_REG_RTC_MO]) - 1; /* starts at 1 */ tm->tm_year = bcd2bin(regs[ABB5ZES3_REG_RTC_YR]) + 100; - ret = rtc_valid_tm(tm); - err: return ret; } From 35a2112377a626033d3067d126a3f79092fcfc36 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:23:57 +0100 Subject: [PATCH 065/128] rtc: cpcap: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Reviewed-by: Sebastian Reichel Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cpcap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c index 3a0333e1f21a..a8856f2b9bc2 100644 --- a/drivers/rtc/rtc-cpcap.c +++ b/drivers/rtc/rtc-cpcap.c @@ -119,7 +119,7 @@ static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm) cpcap2rtc_time(tm, &cpcap_tm); - return rtc_valid_tm(tm); + return 0; } static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm) From bb54be134a363f57d698b0c2887df36e468f3077 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 2 Mar 2018 10:08:47 +0100 Subject: [PATCH 066/128] rtc: diasemi: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Acked-by: Steve Twiss Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-da9052.c | 3 +-- drivers/rtc/rtc-da9055.c | 2 +- drivers/rtc/rtc-da9063.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 4273377562ec..03044e1bc497 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -187,8 +187,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN; rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC; - ret = rtc_valid_tm(rtc_tm); - return ret; + return 0; } idx = (1-idx); diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 678af8648c45..e08cd8130c23 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c @@ -158,7 +158,7 @@ static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_min = v[1] & DA9055_RTC_MIN; rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC; - return rtc_valid_tm(rtc_tm); + return 0; } static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c index f85cae240f12..b4e054c64bad 100644 --- a/drivers/rtc/rtc-da9063.c +++ b/drivers/rtc/rtc-da9063.c @@ -256,7 +256,7 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm) else rtc->rtc_sync = false; - return rtc_valid_tm(tm); + return 0; } static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm) From b6cb398444bd64d28f7f25516148842913ef6594 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:27:10 +0100 Subject: [PATCH 067/128] rtc: nuc900: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-nuc900.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index 4ed81117cf5f..7da664a77181 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c @@ -102,8 +102,8 @@ static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) return NULL; } -static int nuc900_rtc_bcd2bin(unsigned int timereg, - unsigned int calreg, struct rtc_time *tm) +static void nuc900_rtc_bcd2bin(unsigned int timereg, + unsigned int calreg, struct rtc_time *tm) { tm->tm_mday = bcd2bin(calreg >> 0); tm->tm_mon = bcd2bin(calreg >> 8); @@ -112,8 +112,6 @@ static int nuc900_rtc_bcd2bin(unsigned int timereg, tm->tm_sec = bcd2bin(timereg >> 0); tm->tm_min = bcd2bin(timereg >> 8); tm->tm_hour = bcd2bin(timereg >> 16); - - return rtc_valid_tm(tm); } static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, @@ -156,7 +154,9 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); - return nuc900_rtc_bcd2bin(timeval, clrval, tm); + nuc900_rtc_bcd2bin(timeval, clrval, tm); + + return 0; } static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -189,7 +189,9 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); - return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); + nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); + + return rtc_valid_tm(&alrm->time); } static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) From 50a9a35ac6a6466814c23e6178d9babefbfca71f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:18:23 +0100 Subject: [PATCH 068/128] rtc: r7301: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-r7301.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-r7301.c b/drivers/rtc/rtc-r7301.c index 500e8c8a2605..169704b2ce13 100644 --- a/drivers/rtc/rtc-r7301.c +++ b/drivers/rtc/rtc-r7301.c @@ -224,7 +224,7 @@ static int rtc7301_read_time(struct device *dev, struct rtc_time *tm) spin_unlock_irqrestore(&priv->lock, flags); - return err ? err : rtc_valid_tm(tm); + return err; } static int rtc7301_set_time(struct device *dev, struct rtc_time *tm) From 66b32fc54c8e04079102ad356b88a448aad4cb81 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 19 Feb 2018 16:24:19 +0100 Subject: [PATCH 069/128] rtc: sc27xx: stop validating rtc_time in .read_time rtc_time64_to_tm never generates an invalid tm. It is not necessary to validate it. Also, the RTC core is always calling rtc_valid_tm after the read_time callback. Reviewed-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sc27xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index d544d5268757..00d87d138984 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -376,7 +376,7 @@ static int sprd_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; rtc_time64_to_tm(secs, tm); - return rtc_valid_tm(tm); + return 0; } static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm) From 143d92bea3dcda36a2233fa30737b1f818ea4ca3 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 20 Feb 2018 23:55:40 +0100 Subject: [PATCH 070/128] rtc: isl12022: remove useless indirection isl12022_get_datetime and isl12022_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl12022.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 46093cd13d5e..fa5c15d45070 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -104,8 +104,9 @@ static int isl12022_write_reg(struct i2c_client *client, * In the routines that deal directly with the isl12022 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. */ -static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); uint8_t buf[ISL12022_REG_INT + 1]; int ret; @@ -152,8 +153,9 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct isl12022 *isl12022 = i2c_get_clientdata(client); size_t i; int ret; @@ -228,16 +230,6 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return isl12022_get_datetime(to_i2c_client(dev), tm); -} - -static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return isl12022_set_datetime(to_i2c_client(dev), tm); -} - static const struct rtc_class_ops isl12022_rtc_ops = { .read_time = isl12022_rtc_read_time, .set_time = isl12022_rtc_set_time, From 3d809cedae7e83c8968f8f994186324283766cb7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:02:08 +0100 Subject: [PATCH 071/128] rtc: m41t93: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t93.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 5ac45fc1a787..4a08a9dabc82 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -159,7 +159,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm) tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - return ret < 0 ? ret : rtc_valid_tm(tm); + return ret; } From e115a2bf14266bb4fe0ec75cd770a0a5eb77091e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:05:20 +0100 Subject: [PATCH 072/128] rtc: max77686: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 182fdd00e290..cefde273fae6 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -364,11 +364,9 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) max77686_rtc_data_to_tm(data, tm, info); - ret = rtc_valid_tm(tm); - out: mutex_unlock(&info->lock); - return ret; + return 0; } static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) From 7ddc153d5f9442124cc083b15489932e45202661 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:33:37 +0100 Subject: [PATCH 073/128] rtc: omap: stop validating rtc_time in .set_time and .set_alarm The RTC core is always validating the rtc_time struct before calling .set_time or .set_alarm. It is not necessary to do it again. Also, rtc_time_to_tm never generates an invalid rtc_tm (it can be out of range though). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index e53cb27f4118..39086398833e 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -273,9 +273,6 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) /* this hardware doesn't support "don't care" alarm fields */ static int tm2bcd(struct rtc_time *tm) { - if (rtc_valid_tm(tm) != 0) - return -EINVAL; - tm->tm_sec = bin2bcd(tm->tm_sec); tm->tm_min = bin2bcd(tm->tm_min); tm->tm_hour = bin2bcd(tm->tm_hour); From 9fb7aa7501b0293b44405f1b8053727266436dc6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:23:19 +0100 Subject: [PATCH 074/128] rtc: spear: stop validating rtc_time in .set_time and .set_alarm The RTC core is always validating the rtc_time struct before calling .set_time or .set_alarm. It is not necessary to do it again. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-spear.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index e377f42abae7..0567944fd4f8 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -170,18 +170,14 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id) } -static int tm2bcd(struct rtc_time *tm) +static void tm2bcd(struct rtc_time *tm) { - if (rtc_valid_tm(tm) != 0) - return -EINVAL; tm->tm_sec = bin2bcd(tm->tm_sec); tm->tm_min = bin2bcd(tm->tm_min); tm->tm_hour = bin2bcd(tm->tm_hour); tm->tm_mday = bin2bcd(tm->tm_mday); tm->tm_mon = bin2bcd(tm->tm_mon + 1); tm->tm_year = bin2bcd(tm->tm_year); - - return 0; } static void bcd2tm(struct rtc_time *tm) @@ -237,8 +233,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) struct spear_rtc_config *config = dev_get_drvdata(dev); unsigned int time, date; - if (tm2bcd(tm) < 0) - return -EINVAL; + tm2bcd(tm); rtc_wait_not_busy(config); time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) | @@ -295,8 +290,7 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) unsigned int time, date; int err; - if (tm2bcd(&alm->time) < 0) - return -EINVAL; + tm2bcd(&alm->time); rtc_wait_not_busy(config); From c4f2eafe52aab77f9481595b180d8ae01903a07c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:03:49 +0100 Subject: [PATCH 075/128] rtc: tegra: stop validating rtc_time in .set_time The RTC core is always validating the rtc_time struct before calling .set_time. It is not necessary to do it again in .set_time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-tegra.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index d30d57b048d3..66efff60c4d5 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -144,10 +144,6 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm) int ret; /* convert tm to seconds. */ - ret = rtc_valid_tm(tm); - if (ret) - return ret; - rtc_tm_to_time(tm, &sec); dev_vdbg(dev, "time set to %lu. %d/%d/%d %d:%02u:%02u\n", From fbfd36fdd26cab41844f0b869de0cf120017c15c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 20 Feb 2018 23:42:27 +0100 Subject: [PATCH 076/128] rtc: abx80x: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index b033bc556f5d..2cefa67a1132 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -172,11 +172,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1; tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100; - err = rtc_valid_tm(tm); - if (err < 0) - dev_err(&client->dev, "retrieved date/time is not valid.\n"); - - return err; + return 0; } static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) From b1b8394edc3b9b4093f3a2a6b98b8d76ac46dc7e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:10:41 +0100 Subject: [PATCH 077/128] rtc: pm8xxx: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pm8xxx.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index fac835530671..8e0128796824 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -190,12 +190,6 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) rtc_time_to_tm(secs, tm); - rc = rtc_valid_tm(tm); - if (rc < 0) { - dev_err(dev, "Invalid time read from RTC\n"); - return rc; - } - dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", secs, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_mday, tm->tm_mon, tm->tm_year); From 02d289975a3bd0b8dbc924893d15e7859ae41625 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:23:31 +0100 Subject: [PATCH 078/128] rtc: rx4581: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx4581.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c index de3fe4f8d133..c59a218bdd87 100644 --- a/drivers/rtc/rtc-rx4581.c +++ b/drivers/rtc/rtc-rx4581.c @@ -172,11 +172,7 @@ static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - err = rtc_valid_tm(tm); - if (err < 0) - dev_err(dev, "retrieved date/time is not valid.\n"); - - return err; + return 0; } static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm) From 24f421b73918741666b57933316c711b0063ca84 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 00:25:18 +0100 Subject: [PATCH 079/128] rtc: rx8581: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8581.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 9998d7937688..32caadf912ca 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -164,11 +164,7 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - err = rtc_valid_tm(tm); - if (err < 0) - dev_err(&client->dev, "retrieved date/time is not valid.\n"); - - return err; + return 0; } static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) From 4cda172bc338abf770dcdbcf61049ef0d76b17fc Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:48:46 +0100 Subject: [PATCH 080/128] rtc: rk808: remove useless debug message At probe time, printing a message when the time is invalid doesn't have much value. Also, as the comment suggest, this is a leftover from development wherhe this was used to set the RTc to a default time. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rk808.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 35c9aada07c8..e40f35d1ced3 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -375,7 +375,6 @@ static int rk808_rtc_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); struct rk808_rtc *rk808_rtc; - struct rtc_time tm; int ret; rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL); @@ -404,16 +403,6 @@ static int rk808_rtc_probe(struct platform_device *pdev) return ret; } - /* set init time */ - ret = rk808_rtc_readtime(&pdev->dev, &tm); - if (ret) { - dev_err(&pdev->dev, "Failed to read RTC time\n"); - return ret; - } - ret = rtc_valid_tm(&tm); - if (ret) - dev_warn(&pdev->dev, "invalid date/time\n"); - device_init_wakeup(&pdev->dev, 1); rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc", From 201fac95e799c3d0304ec724d555e1251b9f6e84 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 11:57:05 +0100 Subject: [PATCH 081/128] rtc: rk808: fix possible race condition The probe function is not allowed to fail after registering the RTC 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 register the rtc as late as possible. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rk808.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index e40f35d1ced3..739c0d42e835 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -405,12 +405,11 @@ static int rk808_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc", - &rk808_rtc_ops, THIS_MODULE); - if (IS_ERR(rk808_rtc->rtc)) { - ret = PTR_ERR(rk808_rtc->rtc); - return ret; - } + rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rk808_rtc->rtc)) + return PTR_ERR(rk808_rtc->rtc); + + rk808_rtc->rtc->ops = &rk808_rtc_ops; rk808_rtc->irq = platform_get_irq(pdev, 0); if (rk808_rtc->irq < 0) { @@ -427,9 +426,10 @@ static int rk808_rtc_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", rk808_rtc->irq, ret); + return ret; } - return ret; + return rtc_register_device(rk808_rtc->rtc); } static struct platform_driver rk808_rtc_driver = { From 488c6dfe40a6fc83329596e4b1e4cd9abf67ef1d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 13:52:35 +0100 Subject: [PATCH 082/128] rtc: s35390a: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 7067bca5c20d..604f527a1235 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -450,7 +450,6 @@ static int s35390a_probe(struct i2c_client *client, int err, err_read; unsigned int i; struct s35390a *s35390a; - struct rtc_time tm; char buf, status1; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { @@ -508,9 +507,6 @@ static int s35390a_probe(struct i2c_client *client, } } - if (err_read > 0 || s35390a_get_datetime(client, &tm) < 0) - dev_warn(&client->dev, "clock needs to be set\n"); - device_set_wakeup_capable(&client->dev, 1); s35390a->rtc = devm_rtc_device_register(&client->dev, From bb530199a84593504e4cdf1ffd4636726df4f139 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 13:54:46 +0100 Subject: [PATCH 083/128] rtc: s35390a: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 604f527a1235..18c1d8a9f447 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -271,7 +271,7 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - return rtc_valid_tm(tm); + return 0; } static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) From 779e1aabb49e4f3749be659eb4edfe23db09a800 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 14:00:18 +0100 Subject: [PATCH 084/128] rtc: s35390a: remove useless indirection s35390a_set_datetime, s35390a_get_datetime, s35390a_set_alarm and s35390a_read_alarm are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s35390a.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 18c1d8a9f447..77feb603cd4c 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -210,8 +210,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg) return hour; } -static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); int i, err; char buf[7], status; @@ -241,8 +242,9 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) return err; } -static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); char buf[7], status; int i, err; @@ -274,8 +276,9 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) +static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { + struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); char buf[3], sts = 0; int err, i; @@ -329,8 +332,9 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) return err; } -static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) +static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { + struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); char buf[3], sts; int i, err; @@ -384,26 +388,6 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) return 0; } -static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - return s35390a_read_alarm(to_i2c_client(dev), alm); -} - -static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - return s35390a_set_alarm(to_i2c_client(dev), alm); -} - -static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return s35390a_get_datetime(to_i2c_client(dev), tm); -} - -static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return s35390a_set_datetime(to_i2c_client(dev), tm); -} - static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { From ce5abb1939d3de92e971a0a3a59c473b34ca7383 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 15:42:32 +0100 Subject: [PATCH 085/128] rtc: rs5c372: remove useless message It is not necessary to print a message when the time is invalid as userspace will already get an error (and an optional dev_dbg message). Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c372.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index d4eff8d7131f..37aa78fd2c4d 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -581,7 +581,6 @@ static int rs5c372_probe(struct i2c_client *client, int err = 0; int smbus_mode = 0; struct rs5c372 *rs5c372; - struct rtc_time tm; dev_dbg(&client->dev, "%s\n", __func__); @@ -662,9 +661,6 @@ static int rs5c372_probe(struct i2c_client *client, goto exit; } - if (rs5c372_get_datetime(client, &tm) < 0) - dev_warn(&client->dev, "clock needs to be set\n"); - dev_info(&client->dev, "%s found, %s\n", ({ char *s; switch (rs5c372->type) { case rtc_r2025sd: s = "r2025sd"; break; From 57f454fb52f631fb94fc64bcc7e77bf9ed52be9e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 15:43:53 +0100 Subject: [PATCH 086/128] rtc: rs5c372: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c372.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 37aa78fd2c4d..ae7fa4324b0a 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -234,8 +234,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - /* rtc might need initialization */ - return rtc_valid_tm(tm); + return 0; } static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) From 44db5c92a7110e70b45a5caa1d56f8706b7fc76d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 15:47:14 +0100 Subject: [PATCH 087/128] rtc: rs5c372: remove useless indirection rs5c372_get_datetime and rs5c372_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rs5c372.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index ae7fa4324b0a..c5038329058c 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -207,8 +207,9 @@ static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour) return bin2bcd(hour); } -static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct rs5c372 *rs5c = i2c_get_clientdata(client); int status = rs5c_get_regs(rs5c); @@ -237,8 +238,9 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct rs5c372 *rs5c = i2c_get_clientdata(client); unsigned char buf[7]; int addr; @@ -304,17 +306,6 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) } #endif -static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return rs5c372_get_datetime(to_i2c_client(dev), tm); -} - -static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return rs5c372_set_datetime(to_i2c_client(dev), tm); -} - - static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct i2c_client *client = to_i2c_client(dev); From ceed43f719e61f437659569b57e171263dadda08 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 16:01:52 +0100 Subject: [PATCH 088/128] rtc: max6900: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max6900.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index cbdc86a560ba..84f06106f5ba 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -157,7 +157,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); - return rtc_valid_tm(tm); + return 0; } static int max6900_i2c_clear_write_protect(struct i2c_client *client) From 859a6ddbe5d95fa95a66247c290c2c266fe67bf8 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 16:04:27 +0100 Subject: [PATCH 089/128] rtc: max6900: remove useless indirection max6900_i2c_read_time and max6900_i2c_set_time are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max6900.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 84f06106f5ba..ab60f13fa3ef 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -139,8 +139,9 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) return -EIO; } -static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) +static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); int rc; u8 regs[MAX6900_REG_LEN]; @@ -165,9 +166,9 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client) return i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0); } -static int -max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) +static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); u8 regs[MAX6900_REG_LEN]; int rc; @@ -193,16 +194,6 @@ max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) return 0; } -static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return max6900_i2c_read_time(to_i2c_client(dev), tm); -} - -static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return max6900_i2c_set_time(to_i2c_client(dev), tm); -} - static const struct rtc_class_ops max6900_rtc_ops = { .read_time = max6900_rtc_read_time, .set_time = max6900_rtc_set_time, From 0a6b8886fd6a2117a7582ad8385c061bf7e6d0fb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 16:07:34 +0100 Subject: [PATCH 090/128] rtc: pcf85063: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it before returning from the callback. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85063.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index a06dff994c83..6ad4511d7ee1 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -114,7 +114,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_year = bcd2bin(regs[6]); tm->tm_year += 100; - return rtc_valid_tm(tm); + return 0; } static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) From 965271df5afdc5c641c98e1d5f32310e3ba1a5e1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 16:09:27 +0100 Subject: [PATCH 091/128] rtc: pcf85063: remove useless indirection pcf85063_get_datetime and pcf85063_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85063.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 6ad4511d7ee1..3558433e8787 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -81,8 +81,9 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) return 0; } -static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); int rc; u8 regs[7]; @@ -117,8 +118,9 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); int rc; u8 regs[7]; u8 ctrl1; @@ -172,16 +174,6 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return pcf85063_get_datetime(to_i2c_client(dev), tm); -} - -static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return pcf85063_set_datetime(to_i2c_client(dev), tm); -} - static const struct rtc_class_ops pcf85063_rtc_ops = { .read_time = pcf85063_rtc_read_time, .set_time = pcf85063_rtc_set_time From 76384f319a9adff8cb9a87d64c62f61a5d3b7c09 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 9 Feb 2018 19:05:34 +0100 Subject: [PATCH 092/128] rtc: m41t80: move m41t80_rtc_mutex to the block where it is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without CONFIG_RTC_DRV_M41T80_WDT the compiler complains: |drivers/rtc/rtc-m41t80.c:76 ‘m41t80_rtc_mutex’ defined but not used [-Wunused-variable] Move the variable to the block where it is used. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 1103cdc33bfa..b3e33320c0bf 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -73,7 +73,6 @@ #define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */ #define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */ -static DEFINE_MUTEX(m41t80_rtc_mutex); static const struct i2c_device_id m41t80_id[] = { { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, @@ -598,6 +597,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80) * ***************************************************************************** */ +static DEFINE_MUTEX(m41t80_rtc_mutex); static struct i2c_client *save_client; /* Default margin */ From 10d0c768cc6d581523d673b9d1b54213f8a5eb24 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 25 Feb 2018 21:14:31 +0100 Subject: [PATCH 093/128] rtc: m41t80: fix race conditions The IRQ is requested before the struct rtc is allocated and registered, but this struct is used in the IRQ handler, leading to: Unable to handle kernel NULL pointer dereference at virtual address 0000017c pgd = a38a2f9b [0000017c] *pgd=00000000 Internal error: Oops: 5 [#1] ARM Modules linked in: CPU: 0 PID: 613 Comm: irq/48-m41t80 Not tainted 4.16.0-rc1+ #42 Hardware name: Atmel SAMA5 PC is at mutex_lock+0x14/0x38 LR is at m41t80_handle_irq+0x1c/0x9c pc : [] lr : [] psr: 20000013 sp : dec73f30 ip : 00000000 fp : dec56d98 r10: df437cf0 r9 : c0a03008 r8 : c0145ffc r7 : df5c4300 r6 : dec568d0 r5 : df593000 r4 : 0000017c r3 : df592800 r2 : 60000013 r1 : df593000 r0 : 0000017c Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c53c7d Table: 20004059 DAC: 00000051 Process irq/48-m41t80 (pid: 613, stack limit = 0xb52d091e) Stack: (0xdec73f30 to 0xdec74000) 3f20: dec56840 df5c4300 00000001 df5c4300 3f40: c0145ffc c0146018 dec56840 ffffe000 00000001 c0146290 dec567c0 00000000 3f60: c0146084 ed7c9a62 c014615c dec56d80 dec567c0 00000000 dec72000 dec56840 3f80: c014615c c012ffc0 dec72000 dec567c0 c012fe80 00000000 00000000 00000000 3fa0: 00000000 00000000 00000000 c01010e8 00000000 00000000 00000000 00000000 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 29282726 2d2c2b2a [] (mutex_lock) from [] (m41t80_handle_irq+0x1c/0x9c) [] (m41t80_handle_irq) from [] (irq_thread_fn+0x1c/0x54) [] (irq_thread_fn) from [] (irq_thread+0x134/0x1c0) [] (irq_thread) from [] (kthread+0x140/0x148) [] (kthread) from [] (ret_from_fork+0x14/0x2c) Exception stack(0xdec73fb0 to 0xdec73ff8) 3fa0: 00000000 00000000 00000000 00000000 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: e3c33d7f e3c3303f f5d0f000 e593300c (e1901f9f) ---[ end trace 22b027302eb7c604 ]--- genirq: exiting task "irq/48-m41t80" (613) is an active IRQ thread (irq 48) Also, there is another 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* */ Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before requesting the IRQ and register it as late as possible. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index b3e33320c0bf..f77320948fc4 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -885,7 +885,6 @@ static int m41t80_probe(struct i2c_client *client, { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int rc = 0; - struct rtc_device *rtc = NULL; struct rtc_time tm; struct m41t80_data *m41t80_data = NULL; bool wakeup_source = false; @@ -909,6 +908,10 @@ static int m41t80_probe(struct i2c_client *client, m41t80_data->features = id->driver_data; i2c_set_clientdata(client, m41t80_data); + m41t80_data->rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(m41t80_data->rtc)) + return PTR_ERR(m41t80_data->rtc); + #ifdef CONFIG_OF wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source"); @@ -932,15 +935,11 @@ static int m41t80_probe(struct i2c_client *client, device_init_wakeup(&client->dev, true); } - rtc = devm_rtc_device_register(&client->dev, client->name, - &m41t80_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); + m41t80_data->rtc->ops = &m41t80_rtc_ops; - m41t80_data->rtc = rtc; if (client->irq <= 0) { /* We cannot support UIE mode if we do not have an IRQ line */ - rtc->uie_unsupported = 1; + m41t80_data->rtc->uie_unsupported = 1; } /* Make sure HT (Halt Update) bit is cleared */ @@ -993,6 +992,11 @@ static int m41t80_probe(struct i2c_client *client, if (m41t80_data->features & M41T80_FEATURE_SQ) m41t80_sqw_register_clk(m41t80_data); #endif + + rc = rtc_register_device(m41t80_data->rtc); + if (rc) + return rc; + return 0; } From e2c8e1a9f7e52203c9a2712a2e35326d212ad5d7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 25 Feb 2018 23:15:00 +0100 Subject: [PATCH 094/128] rtc: m41t80: remove useless indirection m41t80_get_datetime and m41t80_set_datetime are only used after casting dev to an i2c_client. Remove that useless indirection. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index f77320948fc4..ad03e2f12f5d 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -198,9 +198,9 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int m41t80_get_datetime(struct i2c_client *client, - struct rtc_time *tm) +static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); unsigned char buf[8]; int err, flags; @@ -232,9 +232,9 @@ static int m41t80_get_datetime(struct i2c_client *client, return 0; } -/* Sets the given date and time to the real time clock. */ -static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct m41t80_data *clientdata = i2c_get_clientdata(client); unsigned char buf[8]; int err, flags; @@ -297,16 +297,6 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq) return 0; } -static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return m41t80_get_datetime(to_i2c_client(dev), tm); -} - -static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return m41t80_set_datetime(to_i2c_client(dev), tm); -} - static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct i2c_client *client = to_i2c_client(dev); @@ -947,7 +937,7 @@ static int m41t80_probe(struct i2c_client *client, if (rc >= 0 && rc & M41T80_ALHOUR_HT) { if (m41t80_data->features & M41T80_FEATURE_HT) { - m41t80_get_datetime(client, &tm); + m41t80_rtc_read_time(&client->dev, &tm); dev_info(&client->dev, "HT bit was set!\n"); dev_info(&client->dev, "Power Down at %04i-%02i-%02i %02i:%02i:%02i\n", From c57849dde003db3e21d33eab906dba2202f9294e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 24 Feb 2018 01:08:50 +0100 Subject: [PATCH 095/128] rtc: pcf85363: add .max_register in regmap_config This helps debugging as it allows reading registers from debugfs. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index 64573cccf7fe..3c5e5e1a5ead 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -157,6 +157,7 @@ static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val, static const struct regmap_config regmap_config = { .reg_bits = 8, .val_bits = 8, + .max_register = 0x7f, }; static int pcf85363_probe(struct i2c_client *client, From e5aac267a10a8fd571032ffba42ccb61ea16ca80 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 1 Mar 2018 01:42:19 +0100 Subject: [PATCH 096/128] rtc: pcf85363: add alarm support Handle alarms, currently only on INTA Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 159 +++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index 3c5e5e1a5ead..3fa5bda59987 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -73,6 +73,39 @@ #define CTRL_RESETS 0x2f #define CTRL_RAM 0x40 +#define ALRM_SEC_A1E BIT(0) +#define ALRM_MIN_A1E BIT(1) +#define ALRM_HR_A1E BIT(2) +#define ALRM_DAY_A1E BIT(3) +#define ALRM_MON_A1E BIT(4) +#define ALRM_MIN_A2E BIT(5) +#define ALRM_HR_A2E BIT(6) +#define ALRM_DAY_A2E BIT(7) + +#define INT_WDIE BIT(0) +#define INT_BSIE BIT(1) +#define INT_TSRIE BIT(2) +#define INT_A2IE BIT(3) +#define INT_A1IE BIT(4) +#define INT_OIE BIT(5) +#define INT_PIE BIT(6) +#define INT_ILP BIT(7) + +#define FLAGS_TSR1F BIT(0) +#define FLAGS_TSR2F BIT(1) +#define FLAGS_TSR3F BIT(2) +#define FLAGS_BSF BIT(3) +#define FLAGS_WDF BIT(4) +#define FLAGS_A1F BIT(5) +#define FLAGS_A2F BIT(6) +#define FLAGS_PIF BIT(7) + +#define PIN_IO_INTAPM GENMASK(1, 0) +#define PIN_IO_INTA_CLK 0 +#define PIN_IO_INTA_BAT 1 +#define PIN_IO_INTA_OUT 2 +#define PIN_IO_INTA_HIZ 3 + #define NVRAM_SIZE 0x40 static struct i2c_driver pcf85363_driver; @@ -131,11 +164,123 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) buf, len); } +static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pcf85363 *pcf85363 = dev_get_drvdata(dev); + unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1]; + unsigned int val; + int ret; + + ret = regmap_bulk_read(pcf85363->regmap, DT_SECOND_ALM1, buf, + sizeof(buf)); + if (ret) + return ret; + + alrm->time.tm_sec = bcd2bin(buf[0]); + alrm->time.tm_min = bcd2bin(buf[1]); + alrm->time.tm_hour = bcd2bin(buf[2]); + alrm->time.tm_mday = bcd2bin(buf[3]); + alrm->time.tm_mon = bcd2bin(buf[4]) - 1; + + ret = regmap_read(pcf85363->regmap, CTRL_INTA_EN, &val); + if (ret) + return ret; + + alrm->enabled = !!(val & INT_A1IE); + + return 0; +} + +static int _pcf85363_rtc_alarm_irq_enable(struct pcf85363 *pcf85363, unsigned + int enabled) +{ + unsigned int alarm_flags = ALRM_SEC_A1E | ALRM_MIN_A1E | ALRM_HR_A1E | + ALRM_DAY_A1E | ALRM_MON_A1E; + int ret; + + ret = regmap_update_bits(pcf85363->regmap, DT_ALARM_EN, alarm_flags, + enabled ? alarm_flags : 0); + if (ret) + return ret; + + ret = regmap_update_bits(pcf85363->regmap, CTRL_INTA_EN, + INT_A1IE, enabled ? INT_A1IE : 0); + + if (ret || enabled) + return ret; + + /* clear current flags */ + return regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0); +} + +static int pcf85363_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct pcf85363 *pcf85363 = dev_get_drvdata(dev); + + return _pcf85363_rtc_alarm_irq_enable(pcf85363, enabled); +} + +static int pcf85363_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pcf85363 *pcf85363 = dev_get_drvdata(dev); + unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1]; + int ret; + + buf[0] = bin2bcd(alrm->time.tm_sec); + buf[1] = bin2bcd(alrm->time.tm_min); + buf[2] = bin2bcd(alrm->time.tm_hour); + buf[3] = bin2bcd(alrm->time.tm_mday); + buf[4] = bin2bcd(alrm->time.tm_mon + 1); + + /* + * Disable the alarm interrupt before changing the value to avoid + * spurious interrupts + */ + ret = _pcf85363_rtc_alarm_irq_enable(pcf85363, 0); + if (ret) + return ret; + + ret = regmap_bulk_write(pcf85363->regmap, DT_SECOND_ALM1, buf, + sizeof(buf)); + if (ret) + return ret; + + return _pcf85363_rtc_alarm_irq_enable(pcf85363, alrm->enabled); +} + +static irqreturn_t pcf85363_rtc_handle_irq(int irq, void *dev_id) +{ + struct pcf85363 *pcf85363 = i2c_get_clientdata(dev_id); + unsigned int flags; + int err; + + err = regmap_read(pcf85363->regmap, CTRL_FLAGS, &flags); + if (err) + return IRQ_NONE; + + if (flags & FLAGS_A1F) { + rtc_update_irq(pcf85363->rtc, 1, RTC_IRQF | RTC_AF); + regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + static const struct rtc_class_ops rtc_ops = { .read_time = pcf85363_rtc_read_time, .set_time = pcf85363_rtc_set_time, }; +static const struct rtc_class_ops rtc_ops_alarm = { + .read_time = pcf85363_rtc_read_time, + .set_time = pcf85363_rtc_set_time, + .read_alarm = pcf85363_rtc_read_alarm, + .set_alarm = pcf85363_rtc_set_alarm, + .alarm_irq_enable = pcf85363_rtc_alarm_irq_enable, +}; + static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { @@ -197,6 +342,20 @@ static int pcf85363_probe(struct i2c_client *client, pcf85363->rtc->ops = &rtc_ops; + if (client->irq > 0) { + regmap_write(pcf85363->regmap, CTRL_FLAGS, 0); + regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO, + PIN_IO_INTA_OUT, PIN_IO_INTAPM); + ret = devm_request_threaded_irq(pcf85363->dev, client->irq, + NULL, pcf85363_rtc_handle_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "pcf85363", client); + if (ret) + dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); + else + pcf85363->rtc->ops = &rtc_ops_alarm; + } + ret = rtc_register_device(pcf85363->rtc); nvmem_cfg.priv = pcf85363; From 188306ac9536ec47674ffa9dd330f69927679aeb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 24 Feb 2018 01:08:53 +0100 Subject: [PATCH 097/128] rtc: pcf85363: set time accurately As per 8.2.6 Setting and reading the time in RTC mode, first stop the clok, then reset it before setting the date and time registers. Finally, start the clock. This uses register address wrap around from 0x2f to 0x00 for efficiency. This allows to set the clock with a millisecond accuracy (drift is not corrected in this example): RTC System 1325388767 1325388767.000029180 1325388768 1325388768.000018362 1325388769 1325388769.000006544 1325388770 1325388769.999992725 1325388771 1325388770.999974544 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85363.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index 3fa5bda59987..c04a1edcd571 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -106,6 +106,10 @@ #define PIN_IO_INTA_OUT 2 #define PIN_IO_INTA_HIZ 3 +#define STOP_EN_STOP BIT(0) + +#define RESET_CPR 0xa4 + #define NVRAM_SIZE 0x40 static struct i2c_driver pcf85363_driver; @@ -148,8 +152,12 @@ static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct pcf85363 *pcf85363 = dev_get_drvdata(dev); - unsigned char buf[DT_YEARS + 1]; - int len = sizeof(buf); + unsigned char tmp[11]; + unsigned char *buf = &tmp[2]; + int ret; + + tmp[0] = STOP_EN_STOP; + tmp[1] = RESET_CPR; buf[DT_100THS] = 0; buf[DT_SECS] = bin2bcd(tm->tm_sec); @@ -160,8 +168,12 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1); buf[DT_YEARS] = bin2bcd(tm->tm_year % 100); - return regmap_bulk_write(pcf85363->regmap, DT_100THS, - buf, len); + ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN, + tmp, sizeof(tmp)); + if (ret) + return ret; + + return regmap_write(pcf85363->regmap, CTRL_STOP_EN, 0); } static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) From 561f8281cf90051bc5f11017ac5ebb21eec45ad9 Mon Sep 17 00:00:00 2001 From: Philipp Rossak Date: Mon, 26 Feb 2018 22:19:01 +0100 Subject: [PATCH 098/128] rtc: ac100: Fix ac100 determine rate bug This patch fixes a bug, that prevents the Allwinner A83T and the A80 from a successful boot. The bug is there since v4.16-rc1 and appeared after the clk branch was merged. You can find the shortend trace below: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = (ptrval) [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 49 Comm: kworker/0:1 Not tainted 4.15.0-10190-gb89e32ccd1be #2 Hardware name: Allwinner sun8i Family Workqueue: events deferred_probe_work_func PC is at clk_hw_get_rate+0x0/0x34 LR is at ac100_clkout_determine_rate+0x48/0x19c [ ... ] (clk_hw_get_rate) from (ac100_clkout_determine_rate+0x48/0x19c) (ac100_clkout_determine_rate) from (clk_core_set_rate_nolock+0x3c/0x1a0) (clk_core_set_rate_nolock) from (clk_set_rate+0x30/0x88) (clk_set_rate) from (of_clk_set_defaults+0x200/0x364) (of_clk_set_defaults) from (platform_drv_probe+0x18/0xb0) To fix that bug, we first check if the return of the clk_hw_get_parent_by_index is non zero. If it is zero we skip that clock parent. The BUG report could be found here: https://lkml.org/lkml/2018/2/10/198 Fixes: 04940631b8d2 ("rtc: ac100: Add clk output support") Signed-off-by: Philipp Rossak Acked-by: Maxime Ripard Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ac100.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index 080e3c04be43..3fe576fdd45e 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -183,7 +183,29 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw, for (i = 0; i < num_parents; i++) { struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); - unsigned long tmp, prate = clk_hw_get_rate(parent); + unsigned long tmp, prate; + + /* + * The clock has two parents, one is a fixed clock which is + * internally registered by the ac100 driver. The other parent + * is a clock from the codec side of the chip, which we + * properly declare and reference in the devicetree and is + * not implemented in any driver right now. + * If the clock core looks for the parent of that second + * missing clock, it can't find one that is registered and + * returns NULL. + * So we end up in a situation where clk_hw_get_num_parents + * returns the amount of clocks we can be parented to, but + * clk_hw_get_parent_by_index will not return the orphan + * clocks. + * Thus we need to check if the parent exists before + * we get the parent rate, so we could use the RTC + * without waiting for the codec to be supported. + */ + if (!parent) + continue; + + prate = clk_hw_get_rate(parent); tmp = ac100_clkout_round_rate(hw, req->rate, prate); From f18046c50d2bb726538a83dfb035bfa592779e9c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 28 Feb 2018 22:50:53 +0100 Subject: [PATCH 099/128] rtc: fix rtc_time64_to_tm for 3477 The current correction for leap years will fail in 3477. 3476-12-31 being 3477-01-00 because this is 366 leap years after 1970 and 3477 isn't a leap year. Fix that by looping over until days is positive or zero. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index ad5bb21908e5..4a3c0f3aab14 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -65,7 +65,7 @@ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) days -= (year - 1970) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(1970 - 1); - if (days < 0) { + while (days < 0) { year -= 1; days += 365 + is_leap_year(year); } From 58d3d5e79ece544b50829ac409064b58fec32000 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Mon, 26 Feb 2018 12:09:58 -0800 Subject: [PATCH 100/128] rtc: brcmstb-waketimer: Set wktmr prescaler The HW default is one tick per second, however instead of assuming this, lets make sure the waketimer is actually one tick per second before arming the alarm. Reviewed-by: Florian Fainelli Signed-off-by: Justin Chen Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-brcmstb-waketimer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index 6cee61201c30..bdd6674a1054 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -60,6 +60,9 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr *timer, { brcmstb_waketmr_clear_alarm(timer); + /* Make sure we are actually counting in seconds */ + writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER); + writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM); } From 4731a43169b799a9b4337579793a24fcc85943f5 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 22 Feb 2018 12:04:32 -0800 Subject: [PATCH 101/128] rtc: isl12026: new driver. The ISL12026 is a combination RTC and EEPROM device with I2C interface. The standard RTC driver interface is provided. The EEPROM is accessed via the NVMEM interface. Reviewed-by: Rob Herring Reviewed-by: Andy Shevchenko Signed-off-by: David Daney Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/rtc/isil,isl12026.txt | 28 + drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-isl12026.c | 505 ++++++++++++++++++ 4 files changed, 544 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/isil,isl12026.txt create mode 100644 drivers/rtc/rtc-isl12026.c diff --git a/Documentation/devicetree/bindings/rtc/isil,isl12026.txt b/Documentation/devicetree/bindings/rtc/isil,isl12026.txt new file mode 100644 index 000000000000..2e0be45193bb --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/isil,isl12026.txt @@ -0,0 +1,28 @@ +ISL12026 I2C RTC/EEPROM + +ISL12026 is an I2C RTC/EEPROM combination device. The RTC and control +registers respond at bus address 0x6f, and the EEPROM array responds +at bus address 0x57. The canonical "reg" value will be for the RTC portion. + +Required properties supported by the device: + + - "compatible": must be "isil,isl12026" + - "reg": I2C bus address of the device (always 0x6f) + +Optional properties: + + - "isil,pwr-bsw": If present PWR.BSW bit must be set to the specified + value for proper operation. + + - "isil,pwr-sbib": If present PWR.SBIB bit must be set to the specified + value for proper operation. + + +Example: + + rtc@6f { + compatible = "isil,isl12026"; + reg = <0x6f>; + isil,pwr-bsw = <0>; + isil,pwr-sbib = <1>; + } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f6d7e490e714..3bf649cd7b83 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -407,6 +407,16 @@ config RTC_DRV_ISL12022 This driver can also be built as a module. If so, the module will be called rtc-isl12022. +config RTC_DRV_ISL12026 + tristate "Intersil ISL12026" + depends on OF || COMPILE_TEST + help + If you say yes here you get support for the + Intersil ISL12026 RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-isl12026. + config RTC_DRV_X1205 tristate "Xicor/Intersil X1205" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 4fbf87e45a7c..f481661a6eae 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o +obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c new file mode 100644 index 000000000000..ada9849d8d97 --- /dev/null +++ b/drivers/rtc/rtc-isl12026.c @@ -0,0 +1,505 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * An I2C driver for the Intersil ISL 12026 + * + * Copyright (c) 2018 Cavium, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register offsets */ +#define ISL12026_REG_PWR 0x14 +# define ISL12026_REG_PWR_BSW BIT(6) +# define ISL12026_REG_PWR_SBIB BIT(7) +#define ISL12026_REG_SC 0x30 +#define ISL12026_REG_HR 0x32 +# define ISL12026_REG_HR_MIL BIT(7) /* military or 24 hour time */ +#define ISL12026_REG_SR 0x3f +# define ISL12026_REG_SR_RTCF BIT(0) +# define ISL12026_REG_SR_WEL BIT(1) +# define ISL12026_REG_SR_RWEL BIT(2) +# define ISL12026_REG_SR_MBZ BIT(3) +# define ISL12026_REG_SR_OSCF BIT(4) + +/* The EEPROM array responds at i2c address 0x57 */ +#define ISL12026_EEPROM_ADDR 0x57 + +#define ISL12026_PAGESIZE 16 +#define ISL12026_NVMEM_WRITE_TIME 20 + +struct isl12026 { + struct rtc_device *rtc; + struct i2c_client *nvm_client; +}; + +static int isl12026_read_reg(struct i2c_client *client, int reg) +{ + u8 addr[] = {0, reg}; + u8 val; + int ret; + + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(addr), + .buf = addr + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "read reg error, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + } else { + ret = val; + } + + return ret; +} + +static int isl12026_arm_write(struct i2c_client *client) +{ + int ret; + u8 op[3]; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = op + }; + + /* Set SR.WEL */ + op[0] = 0; + op[1] = ISL12026_REG_SR; + op[2] = ISL12026_REG_SR_WEL; + msg.len = 3; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "write error SR.WEL, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } + + /* Set SR.WEL and SR.RWEL */ + op[2] = ISL12026_REG_SR_WEL | ISL12026_REG_SR_RWEL; + msg.len = 3; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, + "write error SR.WEL|SR.RWEL, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } else { + ret = 0; + } +out: + return ret; +} + +static int isl12026_disarm_write(struct i2c_client *client) +{ + int ret; + u8 op[3] = {0, ISL12026_REG_SR, 0}; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = sizeof(op), + .buf = op + }; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, + "write error SR, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + } else { + ret = 0; + } + + return ret; +} + +static int isl12026_write_reg(struct i2c_client *client, int reg, u8 val) +{ + int ret; + u8 op[3] = {0, reg, val}; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = sizeof(op), + .buf = op + }; + + ret = isl12026_arm_write(client); + if (ret) + return ret; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "write error CCR, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } + + msleep(ISL12026_NVMEM_WRITE_TIME); + + ret = isl12026_disarm_write(client); +out: + return ret; +} + +static int isl12026_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + int ret; + u8 op[10]; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = sizeof(op), + .buf = op + }; + + ret = isl12026_arm_write(client); + if (ret) + return ret; + + /* Set the CCR registers */ + op[0] = 0; + op[1] = ISL12026_REG_SC; + op[2] = bin2bcd(tm->tm_sec); /* SC */ + op[3] = bin2bcd(tm->tm_min); /* MN */ + op[4] = bin2bcd(tm->tm_hour) | ISL12026_REG_HR_MIL; /* HR */ + op[5] = bin2bcd(tm->tm_mday); /* DT */ + op[6] = bin2bcd(tm->tm_mon + 1); /* MO */ + op[7] = bin2bcd(tm->tm_year % 100); /* YR */ + op[8] = bin2bcd(tm->tm_wday & 7); /* DW */ + op[9] = bin2bcd(tm->tm_year >= 100 ? 20 : 19); /* Y2K */ + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "write error CCR, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } + + ret = isl12026_disarm_write(client); +out: + return ret; +} + +static int isl12026_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 ccr[8]; + u8 addr[2]; + u8 sr; + int ret; + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(addr), + .buf = addr + }, { + .addr = client->addr, + .flags = I2C_M_RD, + } + }; + + /* First, read SR */ + addr[0] = 0; + addr[1] = ISL12026_REG_SR; + msgs[1].len = 1; + msgs[1].buf = &sr; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "read error, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } + + if (sr & ISL12026_REG_SR_RTCF) + dev_warn(&client->dev, "Real-Time Clock Failure on read\n"); + if (sr & ISL12026_REG_SR_OSCF) + dev_warn(&client->dev, "Oscillator Failure on read\n"); + + /* Second, CCR regs */ + addr[0] = 0; + addr[1] = ISL12026_REG_SC; + msgs[1].len = sizeof(ccr); + msgs[1].buf = ccr; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "read error, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + goto out; + } + + tm->tm_sec = bcd2bin(ccr[0] & 0x7F); + tm->tm_min = bcd2bin(ccr[1] & 0x7F); + if (ccr[2] & ISL12026_REG_HR_MIL) + tm->tm_hour = bcd2bin(ccr[2] & 0x3F); + else + tm->tm_hour = bcd2bin(ccr[2] & 0x1F) + + ((ccr[2] & 0x20) ? 12 : 0); + tm->tm_mday = bcd2bin(ccr[3] & 0x3F); + tm->tm_mon = bcd2bin(ccr[4] & 0x1F) - 1; + tm->tm_year = bcd2bin(ccr[5]); + if (bcd2bin(ccr[7]) == 20) + tm->tm_year += 100; + tm->tm_wday = ccr[6] & 0x07; + + ret = 0; +out: + return ret; +} + +static const struct rtc_class_ops isl12026_rtc_ops = { + .read_time = isl12026_rtc_read_time, + .set_time = isl12026_rtc_set_time, +}; + +static int isl12026_nvm_read(void *p, unsigned int offset, + void *val, size_t bytes) +{ + struct isl12026 *priv = p; + int ret; + u8 addr[2]; + struct i2c_msg msgs[] = { + { + .addr = priv->nvm_client->addr, + .flags = 0, + .len = sizeof(addr), + .buf = addr + }, { + .addr = priv->nvm_client->addr, + .flags = I2C_M_RD, + .buf = val + } + }; + + /* + * offset and bytes checked and limited by nvmem core, so + * proceed without further checks. + */ + ret = mutex_lock_interruptible(&priv->rtc->ops_lock); + if (ret) + return ret; + + /* 2 bytes of address, most significant first */ + addr[0] = offset >> 8; + addr[1] = offset; + msgs[1].len = bytes; + ret = i2c_transfer(priv->nvm_client->adapter, msgs, ARRAY_SIZE(msgs)); + + mutex_unlock(&priv->rtc->ops_lock); + + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&priv->nvm_client->dev, + "nvmem read error, ret=%d\n", ret); + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int isl12026_nvm_write(void *p, unsigned int offset, + void *val, size_t bytes) +{ + struct isl12026 *priv = p; + int ret; + u8 *v = val; + size_t chunk_size, num_written; + u8 payload[ISL12026_PAGESIZE + 2]; /* page + 2 address bytes */ + struct i2c_msg msgs[] = { + { + .addr = priv->nvm_client->addr, + .flags = 0, + .buf = payload + } + }; + + /* + * offset and bytes checked and limited by nvmem core, so + * proceed without further checks. + */ + ret = mutex_lock_interruptible(&priv->rtc->ops_lock); + if (ret) + return ret; + + num_written = 0; + while (bytes) { + chunk_size = round_down(offset, ISL12026_PAGESIZE) + + ISL12026_PAGESIZE - offset; + chunk_size = min(bytes, chunk_size); + /* + * 2 bytes of address, most significant first, followed + * by page data bytes + */ + memcpy(payload + 2, v + num_written, chunk_size); + payload[0] = offset >> 8; + payload[1] = offset; + msgs[0].len = chunk_size + 2; + ret = i2c_transfer(priv->nvm_client->adapter, + msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&priv->nvm_client->dev, + "nvmem write error, ret=%d\n", ret); + ret = ret < 0 ? ret : -EIO; + break; + } + ret = 0; + bytes -= chunk_size; + offset += chunk_size; + num_written += chunk_size; + msleep(ISL12026_NVMEM_WRITE_TIME); + } + + mutex_unlock(&priv->rtc->ops_lock); + + return ret; +} + +static void isl12026_force_power_modes(struct i2c_client *client) +{ + int ret; + int pwr, requested_pwr; + u32 bsw_val, sbib_val; + bool set_bsw, set_sbib; + + /* + * If we can read the of_property, set the specified value. + * If there is an error reading the of_property (likely + * because it does not exist), keep the current value. + */ + ret = of_property_read_u32(client->dev.of_node, + "isil,pwr-bsw", &bsw_val); + set_bsw = (ret == 0); + + ret = of_property_read_u32(client->dev.of_node, + "isil,pwr-sbib", &sbib_val); + set_sbib = (ret == 0); + + /* Check if PWR.BSW and/or PWR.SBIB need specified values */ + if (!set_bsw && !set_sbib) + return; + + pwr = isl12026_read_reg(client, ISL12026_REG_PWR); + if (pwr < 0) { + dev_warn(&client->dev, "Error: Failed to read PWR %d\n", pwr); + return; + } + + requested_pwr = pwr; + + if (set_bsw) { + if (bsw_val) + requested_pwr |= ISL12026_REG_PWR_BSW; + else + requested_pwr &= ~ISL12026_REG_PWR_BSW; + } /* else keep current BSW */ + + if (set_sbib) { + if (sbib_val) + requested_pwr |= ISL12026_REG_PWR_SBIB; + else + requested_pwr &= ~ISL12026_REG_PWR_SBIB; + } /* else keep current SBIB */ + + if (pwr >= 0 && pwr != requested_pwr) { + dev_dbg(&client->dev, "PWR: %02x\n", pwr); + dev_dbg(&client->dev, "Updating PWR to: %02x\n", requested_pwr); + isl12026_write_reg(client, ISL12026_REG_PWR, requested_pwr); + } +} + +static int isl12026_probe_new(struct i2c_client *client) +{ + struct isl12026 *priv; + int ret; + struct nvmem_config nvm_cfg; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + i2c_set_clientdata(client, priv); + + isl12026_force_power_modes(client); + + priv->nvm_client = i2c_new_dummy(client->adapter, ISL12026_EEPROM_ADDR); + if (!priv->nvm_client) + return -ENOMEM; + + priv->rtc = devm_rtc_allocate_device(&client->dev); + ret = PTR_ERR_OR_ZERO(priv->rtc); + if (ret) + return ret; + + priv->rtc->ops = &isl12026_rtc_ops; + priv->rtc->nvram_old_abi = false; + ret = rtc_register_device(priv->rtc); + if (ret) + return ret; + + memset(&nvm_cfg, 0, sizeof(nvm_cfg)); + nvm_cfg.name = "eeprom"; + nvm_cfg.read_only = false; + nvm_cfg.root_only = true; + nvm_cfg.base_dev = &client->dev; + nvm_cfg.priv = priv; + nvm_cfg.stride = 1; + nvm_cfg.word_size = 1; + nvm_cfg.size = 512; + nvm_cfg.reg_read = isl12026_nvm_read; + nvm_cfg.reg_write = isl12026_nvm_write; + + return rtc_nvmem_register(priv->rtc, &nvm_cfg); +} + +static int isl12026_remove(struct i2c_client *client) +{ + struct isl12026 *priv = i2c_get_clientdata(client); + + i2c_unregister_device(priv->nvm_client); + return 0; +} + +static const struct of_device_id isl12026_dt_match[] = { + { .compatible = "isil,isl12026" }, + { } +}; +MODULE_DEVICE_TABLE(of, isl12026_dt_match); + +static struct i2c_driver isl12026_driver = { + .driver = { + .name = "rtc-isl12026", + .of_match_table = isl12026_dt_match, + }, + .probe_new = isl12026_probe_new, + .remove = isl12026_remove, +}; + +module_i2c_driver(isl12026_driver); + +MODULE_DESCRIPTION("ISL 12026 RTC driver"); +MODULE_LICENSE("GPL"); From 6735f6dcf71e722ee2fc4fb38ed14ae0e2c119b4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 3 Mar 2018 00:50:29 +0100 Subject: [PATCH 102/128] rtc: isl12026: fixup nvmem registration The probe function must not fail after rtc_register_device. Also, rename the nvmem device so it is easily identifiable in /sys/bus/nvmem. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl12026.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c index ada9849d8d97..97f594f9667c 100644 --- a/drivers/rtc/rtc-isl12026.c +++ b/drivers/rtc/rtc-isl12026.c @@ -433,7 +433,15 @@ static int isl12026_probe_new(struct i2c_client *client) { struct isl12026 *priv; int ret; - struct nvmem_config nvm_cfg; + struct nvmem_config nvm_cfg = { + .name = "isl12026-", + .base_dev = &client->dev, + .stride = 1, + .word_size = 1, + .size = 512, + .reg_read = isl12026_nvm_read, + .reg_write = isl12026_nvm_write, + }; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; @@ -456,24 +464,12 @@ static int isl12026_probe_new(struct i2c_client *client) return ret; priv->rtc->ops = &isl12026_rtc_ops; - priv->rtc->nvram_old_abi = false; - ret = rtc_register_device(priv->rtc); + nvm_cfg.priv = priv; + ret = rtc_nvmem_register(priv->rtc, &nvm_cfg); if (ret) return ret; - memset(&nvm_cfg, 0, sizeof(nvm_cfg)); - nvm_cfg.name = "eeprom"; - nvm_cfg.read_only = false; - nvm_cfg.root_only = true; - nvm_cfg.base_dev = &client->dev; - nvm_cfg.priv = priv; - nvm_cfg.stride = 1; - nvm_cfg.word_size = 1; - nvm_cfg.size = 512; - nvm_cfg.reg_read = isl12026_nvm_read; - nvm_cfg.reg_write = isl12026_nvm_write; - - return rtc_nvmem_register(priv->rtc, &nvm_cfg); + return rtc_register_device(priv->rtc); } static int isl12026_remove(struct i2c_client *client) From e22e2d941c948c682b0a3fb293c277993b81dc46 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 6 Mar 2018 20:08:11 +0900 Subject: [PATCH 103/128] rtc: at91sam: add 'depends on HAS_IOMEM' to fix unmet dependency This config select's MFD_SYSCON, but does not depend on HAS_IOMEM. Compile testing on architecture without HAS_IOMEM causes "unmet direct dependencies" in Kconfig phase. Detected by "make ARCH=score allyesconfig". Signed-off-by: Masahiro Yamada Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3bf649cd7b83..5457d15bbcc0 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1423,6 +1423,7 @@ config RTC_DRV_AT91RM9200 config RTC_DRV_AT91SAM9 tristate "AT91SAM9 RTT as RTC" depends on ARCH_AT91 || COMPILE_TEST + depends on HAS_IOMEM select MFD_SYSCON help Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which From 83220bf38b77a830f8e62ab1a0d0408304f9b966 Mon Sep 17 00:00:00 2001 From: Mohit Aggarwal Date: Mon, 5 Mar 2018 14:35:58 +0530 Subject: [PATCH 104/128] rtc: pm8xxx: Fix issue in RTC write path In order to set time in rtc, need to disable rtc hw before writing into rtc registers. Also fixes disabling of alarm while setting rtc time. Signed-off-by: Mohit Aggarwal Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pm8xxx.c | 51 ++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 8e0128796824..29358a045925 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -74,16 +74,18 @@ struct pm8xxx_rtc { /* * Steps to write the RTC registers. * 1. Disable alarm if enabled. - * 2. Write 0x00 to LSB. - * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. - * 4. Enable alarm if disabled in step 1. + * 2. Disable rtc if enabled. + * 3. Write 0x00 to LSB. + * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0]. + * 5. Enable rtc if disabled in step 2. + * 6. Enable alarm if disabled in step 1. */ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) { int rc, i; unsigned long secs, irq_flags; - u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0; - unsigned int ctrl_reg; + u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0; + unsigned int ctrl_reg, rtc_ctrl_reg; struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; @@ -92,23 +94,38 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_tm_to_time(tm, &secs); + dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); + for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { value[i] = secs & 0xFF; secs >>= 8; } - dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); - spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); - rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg); + rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); if (rc) goto rtc_rw_fail; if (ctrl_reg & regs->alarm_en) { alarm_enabled = 1; ctrl_reg &= ~regs->alarm_en; - rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); + rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); + if (rc) { + dev_err(dev, "Write to RTC Alarm control register failed\n"); + goto rtc_rw_fail; + } + } + + /* Disable RTC H/w before writing on RTC register */ + rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg); + if (rc) + goto rtc_rw_fail; + + if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) { + rtc_disabled = 1; + rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE; + rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); if (rc) { dev_err(dev, "Write to RTC control register failed\n"); goto rtc_rw_fail; @@ -137,15 +154,25 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) goto rtc_rw_fail; } - if (alarm_enabled) { - ctrl_reg |= regs->alarm_en; - rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); + /* Enable RTC H/w after writing on RTC register */ + if (rtc_disabled) { + rtc_ctrl_reg |= PM8xxx_RTC_ENABLE; + rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); if (rc) { dev_err(dev, "Write to RTC control register failed\n"); goto rtc_rw_fail; } } + if (alarm_enabled) { + ctrl_reg |= regs->alarm_en; + rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); + if (rc) { + dev_err(dev, "Write to RTC Alarm control register failed\n"); + goto rtc_rw_fail; + } + } + rtc_rw_fail: spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); From 72dd71f0dae47183efdf92279927ff26f0ed9f3f Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 27 Feb 2018 10:50:03 +0800 Subject: [PATCH 105/128] rtc: cros-ec: return -ETIME when refused to set alarms in the past Since accessing a Chrome OS EC based rtc is a slow operation, there is a race window where if the alarm is set for the next second and the second ticks over right before calculating the alarm offset. In this case the current driver is setting a 0-second alarm, which would be considered as disabling alarms by the EC(EC_RTC_ALARM_CLEAR). This breaks, e.g., hwclock which relies on RTC_UIE_ON -> rtc_update_irq_enable(), which sets a 1-second alarm and expects it to fire an interrupt. So return -ETIME when the alarm is in the past, follow __rtc_set_alarm(). Signed-off-by: Jeffy Chen Reviewed-by: Brian Norris Tested-by: Brian Norris Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cros-ec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index f0ea6899c731..bf7ced095c94 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c @@ -197,10 +197,10 @@ static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) cros_ec_rtc->saved_alarm = (u32)alarm_time; } else { /* Don't set an alarm in the past. */ - if ((u32)alarm_time < current_time) - alarm_offset = EC_RTC_ALARM_CLEAR; - else - alarm_offset = (u32)alarm_time - current_time; + if ((u32)alarm_time <= current_time) + return -ETIME; + + alarm_offset = (u32)alarm_time - current_time; } ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset); From 9d327c2d929161a6ca4d7ca0672414cc72100659 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Mon, 5 Mar 2018 10:43:53 +0000 Subject: [PATCH 106/128] rtc: isl1208: enable interrupt after context preparation The interrupt handler got enabled very early. If the interrupt cause is triggering immediately before the context is fully prepared. This can lead to undefined behaviour. Therefor we move the interrupt enable code to the end of the probe function. Signed-off-by: Michael Grzeschik Signed-off-by: Denis Osterland Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl1208.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index c8b495348229..a13a4ba79004 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -635,23 +635,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) if (isl1208_i2c_validate_client(client) < 0) return -ENODEV; - if (client->irq > 0) { - rc = devm_request_threaded_irq(&client->dev, client->irq, NULL, - isl1208_rtc_interrupt, - IRQF_SHARED | IRQF_ONESHOT, - isl1208_driver.driver.name, - client); - if (!rc) { - device_init_wakeup(&client->dev, 1); - enable_irq_wake(client->irq); - } else { - dev_err(&client->dev, - "Unable to request irq %d, no alarm support\n", - client->irq); - client->irq = 0; - } - } - rtc = devm_rtc_device_register(&client->dev, isl1208_driver.driver.name, &isl1208_rtc_ops, THIS_MODULE); @@ -674,6 +657,23 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) if (rc) return rc; + if (client->irq > 0) { + rc = devm_request_threaded_irq(&client->dev, client->irq, NULL, + isl1208_rtc_interrupt, + IRQF_SHARED | IRQF_ONESHOT, + isl1208_driver.driver.name, + client); + if (!rc) { + device_init_wakeup(&client->dev, 1); + enable_irq_wake(client->irq); + } else { + dev_err(&client->dev, + "Unable to request irq %d, no alarm support\n", + client->irq); + client->irq = 0; + } + } + return 0; } From 236b7187034e87bd46eb535ab4f276267ef66ee4 Mon Sep 17 00:00:00 2001 From: Denis Osterland Date: Mon, 5 Mar 2018 10:43:53 +0000 Subject: [PATCH 107/128] rtc: isl1208: switch to rtc_register_device Fix possible race condition. It is not allowed to return with an error code after RTC is registered. Suggested-by: Alexandre Belloni Signed-off-by: Denis Osterland Reviewed-by: Michael Grzeschik Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl1208.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index a13a4ba79004..1a2c38cc0178 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -635,12 +635,12 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) if (isl1208_i2c_validate_client(client) < 0) return -ENODEV; - rtc = devm_rtc_device_register(&client->dev, isl1208_driver.driver.name, - &isl1208_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + rtc->ops = &isl1208_rtc_ops; + i2c_set_clientdata(client, rtc); rc = isl1208_i2c_get_sr(client); @@ -674,7 +674,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) } } - return 0; + return rtc_register_device(rtc); } static int From 71db049e7355f31604e2c04b6cabb71d02bd487d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 17 Feb 2018 14:58:40 +0100 Subject: [PATCH 108/128] rtc: Add RTC range Add a way for drivers to inform the core of the supported date/time range. The core can then check whether the date/time or alarm is in the range before calling ->set_time, ->set_mmss or ->set_alarm. It returns -ERANGE when the time is out of range. Signed-off-by: Alexandre Belloni --- Documentation/ABI/testing/sysfs-class-rtc | 8 ++++++++ drivers/rtc/interface.c | 14 ++++++++++++++ drivers/rtc/rtc-sysfs.c | 12 ++++++++++++ include/linux/rtc.h | 3 +++ 4 files changed, 37 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-rtc b/Documentation/ABI/testing/sysfs-class-rtc index 792a38300336..95984289a4ee 100644 --- a/Documentation/ABI/testing/sysfs-class-rtc +++ b/Documentation/ABI/testing/sysfs-class-rtc @@ -43,6 +43,14 @@ Contact: linux-rtc@vger.kernel.org Description: (RO) The name of the RTC corresponding to this sysfs directory +What: /sys/class/rtc/rtcX/range +Date: January 2018 +KernelVersion: 4.16 +Contact: linux-rtc@vger.kernel.org +Description: + Valid time range for the RTC, as seconds from epoch, formatted + as [min, max] + What: /sys/class/rtc/rtcX/since_epoch Date: March 2006 KernelVersion: 2.6.17 diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 7e253be19ba7..c068daebeec2 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -70,6 +70,13 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) if (err != 0) return err; + if (rtc->range_min != rtc->range_max) { + time64_t time = rtc_tm_to_time64(tm); + + if (time < rtc->range_min || time > rtc->range_max) + return -ERANGE; + } + err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; @@ -374,6 +381,13 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) if (err != 0) return err; + if (rtc->range_min != rtc->range_max) { + time64_t time = rtc_tm_to_time64(&alarm->time); + + if (time < rtc->range_min || time > rtc->range_max) + return -ERANGE; + } + err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 92ff2edb86a6..454da38c6012 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -248,6 +248,14 @@ offset_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(offset); +static ssize_t +range_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "[%lld,%llu]\n", to_rtc_device(dev)->range_min, + to_rtc_device(dev)->range_max); +} +static DEVICE_ATTR_RO(range); + static struct attribute *rtc_attrs[] = { &dev_attr_name.attr, &dev_attr_date.attr, @@ -257,6 +265,7 @@ static struct attribute *rtc_attrs[] = { &dev_attr_hctosys.attr, &dev_attr_wakealarm.attr, &dev_attr_offset.attr, + &dev_attr_range.attr, NULL, }; @@ -286,6 +295,9 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj, } else if (attr == &dev_attr_offset.attr) { if (!rtc->ops->set_offset) mode = 0; + } else if (attr == &dev_attr_range.attr) { + if (!(rtc->range_max - rtc->range_min)) + mode = 0; } return mode; diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 3b65b201169c..c78528c394e5 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -150,6 +150,9 @@ struct rtc_device { bool nvram_old_abi; struct bin_attribute *nvram; + time64_t range_min; + timeu64_t range_max; + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL struct work_struct uie_task; struct timer_list uie_timer; From 4c4e5df1f346f70802bf4999de13d06dbbdf7a01 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 8 Jan 2018 14:04:49 +0800 Subject: [PATCH 109/128] rtc: Factor out the RTC range validation into rtc_valid_range() The RTC range validation code can be factored into rtc_valid_range() function to avoid duplicate code. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index c068daebeec2..25aebc5b448d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -23,6 +23,18 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); +static int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm) +{ + if (rtc->range_min != rtc->range_max) { + time64_t time = rtc_tm_to_time64(tm); + + if (time < rtc->range_min || time > rtc->range_max) + return -ERANGE; + } + + return 0; +} + static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) { int err; @@ -70,12 +82,9 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) if (err != 0) return err; - if (rtc->range_min != rtc->range_max) { - time64_t time = rtc_tm_to_time64(tm); - - if (time < rtc->range_min || time > rtc->range_max) - return -ERANGE; - } + err = rtc_valid_range(rtc, tm); + if (err) + return err; err = mutex_lock_interruptible(&rtc->ops_lock); if (err) @@ -381,12 +390,9 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) if (err != 0) return err; - if (rtc->range_min != rtc->range_max) { - time64_t time = rtc_tm_to_time64(&alarm->time); - - if (time < rtc->range_min || time > rtc->range_max) - return -ERANGE; - } + err = rtc_valid_range(rtc, &alarm->time); + if (err) + return err; err = mutex_lock_interruptible(&rtc->ops_lock); if (err) From 989515647e783221f9737ed1cf519573d26ce99b Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 8 Jan 2018 14:04:50 +0800 Subject: [PATCH 110/128] rtc: Add one offset seconds to expand RTC range From our investigation for all RTC drivers, 1 driver will be expired before year 2017, 7 drivers will be expired before year 2038, 23 drivers will be expired before year 2069, 72 drivers will be expired before 2100 and 104 drivers will be expired before 2106. Especially for these early expired drivers, we need to expand the RTC range to make the RTC can still work after the expired year. So we can expand the RTC range by adding one offset to the time when reading from hardware, and subtracting it when writing back. For example, if you have an RTC that can do 100 years, and currently is configured to be based in Jan 1 1970, so it can represents times from 1970 to 2069. Then if you change the start year from 1970 to 2000, which means it can represents times from 2000 to 2099. By adding or subtracting the offset produced by moving the wrap point, all times between 1970 and 1999 from RTC hardware could get interpreted as times from 2070 to 2099, but the interpretation of dates between 2000 and 2069 would not change. Signed-off-by: Baolin Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/class.c | 70 +++++++++++++++++++++++++++++++++++++++++ drivers/rtc/interface.c | 59 +++++++++++++++++++++++++++++++++- include/linux/rtc.h | 3 ++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 5a5ab4fa14f9..d37588f08055 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -211,6 +211,73 @@ static int rtc_device_get_id(struct device *dev) return id; } +static void rtc_device_get_offset(struct rtc_device *rtc) +{ + time64_t range_secs; + u32 start_year; + int ret; + + /* + * If RTC driver did not implement the range of RTC hardware device, + * then we can not expand the RTC range by adding or subtracting one + * offset. + */ + if (rtc->range_min == rtc->range_max) + return; + + ret = device_property_read_u32(rtc->dev.parent, "start-year", + &start_year); + if (!ret) { + rtc->start_secs = mktime64(start_year, 1, 1, 0, 0, 0); + rtc->set_start_time = true; + } + + /* + * If user did not implement the start time for RTC driver, then no + * need to expand the RTC range. + */ + if (!rtc->set_start_time) + return; + + range_secs = rtc->range_max - rtc->range_min + 1; + + /* + * If the start_secs is larger than the maximum seconds (rtc->range_max) + * supported by RTC hardware or the maximum seconds of new expanded + * range (start_secs + rtc->range_max - rtc->range_min) is less than + * rtc->range_min, which means the minimum seconds (rtc->range_min) of + * RTC hardware will be mapped to start_secs by adding one offset, so + * the offset seconds calculation formula should be: + * rtc->offset_secs = rtc->start_secs - rtc->range_min; + * + * If the start_secs is larger than the minimum seconds (rtc->range_min) + * supported by RTC hardware, then there is one region is overlapped + * between the original RTC hardware range and the new expanded range, + * and this overlapped region do not need to be mapped into the new + * expanded range due to it is valid for RTC device. So the minimum + * seconds of RTC hardware (rtc->range_min) should be mapped to + * rtc->range_max + 1, then the offset seconds formula should be: + * rtc->offset_secs = rtc->range_max - rtc->range_min + 1; + * + * If the start_secs is less than the minimum seconds (rtc->range_min), + * which is similar to case 2. So the start_secs should be mapped to + * start_secs + rtc->range_max - rtc->range_min + 1, then the + * offset seconds formula should be: + * rtc->offset_secs = -(rtc->range_max - rtc->range_min + 1); + * + * Otherwise the offset seconds should be 0. + */ + if (rtc->start_secs > rtc->range_max || + rtc->start_secs + range_secs - 1 < rtc->range_min) + rtc->offset_secs = rtc->start_secs - rtc->range_min; + else if (rtc->start_secs > rtc->range_min) + rtc->offset_secs = range_secs; + else if (rtc->start_secs < rtc->range_min) + rtc->offset_secs = -range_secs; + else + rtc->offset_secs = 0; +} + /** * rtc_device_register - register w/ RTC class * @dev: the device to register @@ -247,6 +314,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, dev_set_name(&rtc->dev, "rtc%d", id); + rtc_device_get_offset(rtc); + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); @@ -436,6 +505,7 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) return -EINVAL; rtc->owner = owner; + rtc_device_get_offset(rtc); /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 25aebc5b448d..7cbdc9228dd5 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -23,12 +23,61 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); +static void rtc_add_offset(struct rtc_device *rtc, struct rtc_time *tm) +{ + time64_t secs; + + if (!rtc->offset_secs) + return; + + secs = rtc_tm_to_time64(tm); + + /* + * Since the reading time values from RTC device are always in the RTC + * original valid range, but we need to skip the overlapped region + * between expanded range and original range, which is no need to add + * the offset. + */ + if ((rtc->start_secs > rtc->range_min && secs >= rtc->start_secs) || + (rtc->start_secs < rtc->range_min && + secs <= (rtc->start_secs + rtc->range_max - rtc->range_min))) + return; + + rtc_time64_to_tm(secs + rtc->offset_secs, tm); +} + +static void rtc_subtract_offset(struct rtc_device *rtc, struct rtc_time *tm) +{ + time64_t secs; + + if (!rtc->offset_secs) + return; + + secs = rtc_tm_to_time64(tm); + + /* + * If the setting time values are in the valid range of RTC hardware + * device, then no need to subtract the offset when setting time to RTC + * device. Otherwise we need to subtract the offset to make the time + * values are valid for RTC hardware device. + */ + if (secs >= rtc->range_min && secs <= rtc->range_max) + return; + + rtc_time64_to_tm(secs - rtc->offset_secs, tm); +} + static int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm) { if (rtc->range_min != rtc->range_max) { time64_t time = rtc_tm_to_time64(tm); + time64_t range_min = rtc->set_start_time ? rtc->start_secs : + rtc->range_min; + time64_t range_max = rtc->set_start_time ? + (rtc->start_secs + rtc->range_max - rtc->range_min) : + rtc->range_max; - if (time < rtc->range_min || time > rtc->range_max) + if (time < range_min || time > range_max) return -ERANGE; } @@ -51,6 +100,8 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) return err; } + rtc_add_offset(rtc, tm); + err = rtc_valid_tm(tm); if (err < 0) dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n"); @@ -86,6 +137,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) if (err) return err; + rtc_subtract_offset(rtc, tm); + err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; @@ -355,6 +408,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) err = rtc_valid_tm(&alarm->time); if (err) return err; + + rtc_subtract_offset(rtc, &alarm->time); scheduled = rtc_tm_to_time64(&alarm->time); /* Make sure we're not setting alarms in the past */ @@ -406,6 +461,8 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) err = rtc_timer_enqueue(rtc, &rtc->aie_timer); mutex_unlock(&rtc->ops_lock); + + rtc_add_offset(rtc, &alarm->time); return err; } EXPORT_SYMBOL_GPL(rtc_set_alarm); diff --git a/include/linux/rtc.h b/include/linux/rtc.h index c78528c394e5..82a3038f16ab 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -152,6 +152,9 @@ struct rtc_device { time64_t range_min; timeu64_t range_max; + time64_t start_secs; + time64_t offset_secs; + bool set_start_time; #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL struct work_struct uie_task; From 83bbc5ac63326433755592829caf02920b3d8dc0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 8 Mar 2018 00:13:52 +0100 Subject: [PATCH 111/128] rtc: Add useful timestamp definitions Add commonly used timestamps for range definition. Signed-off-by: Alexandre Belloni --- include/linux/rtc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 82a3038f16ab..4c007f69082f 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -169,6 +169,11 @@ struct rtc_device { }; #define to_rtc_device(d) container_of(d, struct rtc_device, dev) +/* useful timestamps */ +#define RTC_TIMESTAMP_BEGIN_1900 -2208989361LL /* 1900-01-01 00:00:00 */ +#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */ +#define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */ + extern struct rtc_device *rtc_device_register(const char *name, struct device *dev, const struct rtc_class_ops *ops, From fed9b18611f75110d5b26d650819665d528038da Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 7 Mar 2018 20:27:56 -0600 Subject: [PATCH 112/128] rtc: remove VLA usage In preparation to enabling -Wvla, remove VLA and replace it with a fixed-length array instead. >From a security viewpoint, the use of Variable Length Arrays can be a vector for stack overflow attacks. Also, in general, as the code evolves it is easy to lose track of how big a VLA can get. Thus, we can end up having segfaults that are hard to debug. Also, fixed as part of the directive to remove all VLAs from the kernel: https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-bq32k.c | 6 +++++- drivers/rtc/rtc-mcp795.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index e8698e9870fe..ef52741000a8 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -36,6 +36,10 @@ #define BQ32K_CFG2 0x09 /* Trickle charger control */ #define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */ +#define MAX_LEN 10 /* Maximum number of consecutive + * register for this particular RTC. + */ + struct bq32k_regs { uint8_t seconds; uint8_t minutes; @@ -74,7 +78,7 @@ static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len) static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len) { struct i2c_client *client = to_i2c_client(dev); - uint8_t buffer[len + 1]; + uint8_t buffer[MAX_LEN + 1]; buffer[0] = off; memcpy(&buffer[1], data, len); diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index 79e24eadbe99..00e11c1b2186 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -82,7 +82,7 @@ static int mcp795_rtcc_write(struct device *dev, u8 addr, u8 *data, u8 count) { struct spi_device *spi = to_spi_device(dev); int ret; - u8 tx[2 + count]; + u8 tx[257]; tx[0] = MCP795_WRITE; tx[1] = addr; From 4a681243cc2d2cea98c6b5e57224f3bcb08bce6c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 10 Mar 2018 00:27:15 -0600 Subject: [PATCH 113/128] rtc: s5m: Move enum from rtc.h to rtc-s5m.c Move this enum to rtc-s5m.c once it is meaningless to others drivers [1]. [1] https://marc.info/?l=linux-rtc&m=152060068925948&w=2 Suggested-by: Krzysztof Kozlowski Signed-off-by: Gustavo A. R. Silva Reviewed-by: Krzysztof Kozlowski Acked-by: Lee Jones Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s5m.c | 11 +++++++++++ include/linux/mfd/samsung/rtc.h | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 6deae10c14ac..4c363deb79fd 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -38,6 +38,17 @@ */ #define UDR_READ_RETRY_CNT 5 +enum { + RTC_SEC = 0, + RTC_MIN, + RTC_HOUR, + RTC_WEEKDAY, + RTC_DATE, + RTC_MONTH, + RTC_YEAR1, + RTC_YEAR2, +}; + /* * Registers used by the driver which are different between chipsets. * diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index 48c3c5be7eb1..9ed2871ea335 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -141,15 +141,4 @@ enum s2mps_rtc_reg { #define WTSR_ENABLE_SHIFT 6 #define WTSR_ENABLE_MASK (1 << WTSR_ENABLE_SHIFT) -enum { - RTC_SEC = 0, - RTC_MIN, - RTC_HOUR, - RTC_WEEKDAY, - RTC_DATE, - RTC_MONTH, - RTC_YEAR1, - RTC_YEAR2, -}; - #endif /* __LINUX_MFD_SEC_RTC_H */ From 756d5282bf04db868b1c0b93f41981dabe2af57f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 10 Mar 2018 00:27:35 -0600 Subject: [PATCH 114/128] rtc: s5m: Remove VLA usage In preparation to enabling -Wvla, remove VLAs and replace them with fixed-length arrays instead. >From a security viewpoint, the use of Variable Length Arrays can be a vector for stack overflow attacks. Also, in general, as the code evolves it is easy to lose track of how big a VLA can get. Thus, we can end up having segfaults that are hard to debug. Also, fixed as part of the directive to remove all VLAs from the kernel: https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Gustavo A. R. Silva Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s5m.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 4c363deb79fd..8428455432ca 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -47,6 +47,8 @@ enum { RTC_MONTH, RTC_YEAR1, RTC_YEAR2, + /* Make sure this is always the last enum name. */ + RTC_MAX_NUM_TIME_REGS }; /* @@ -378,7 +380,7 @@ static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data) static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; int ret; if (info->regs->read_time_udr_mask) { @@ -424,7 +426,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; int ret = 0; switch (info->device_type) { @@ -461,7 +463,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; unsigned int val; int ret, i; @@ -511,7 +513,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) { - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; int ret, i; struct rtc_time tm; @@ -556,7 +558,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) { int ret; - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; u8 alarm0_conf; struct rtc_time tm; @@ -609,7 +611,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); - u8 data[info->regs->regs_count]; + u8 data[RTC_MAX_NUM_TIME_REGS]; int ret; switch (info->device_type) { From 65d211b307655e352385bfdee7aa9754d5acb66e Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 12 Mar 2018 17:51:40 +0800 Subject: [PATCH 115/128] rtc: at91sam9: Set name of regmap_config We are now allowing to register debugfs without a valid device, and not having a valid name will end up using "dummy*" to create debugfs dir. Signed-off-by: Jeffy Chen Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-at91sam9.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 7418a763ce52..ee71e647fd43 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = { }; static const struct regmap_config gpbr_regmap_config = { + .name = "gpbr", .reg_bits = 32, .val_bits = 32, .reg_stride = 4, From 051abf552468d4b80c0ccf8c69667bfab672cec0 Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Thu, 22 Feb 2018 11:29:24 +1300 Subject: [PATCH 116/128] rtc: pcf85063: fix clearing bits in pcf85063_start_clock Bit clear operation was missing ~ Signed-off-by: Michael McCormick Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf85063.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 3558433e8787..49bcbb3d4a69 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -70,7 +70,7 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) s32 ret; /* start the clock */ - ctrl1 &= PCF85063_REG_CTRL1_STOP; + ctrl1 &= ~PCF85063_REG_CTRL1_STOP; ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); if (ret < 0) { From f6b1a3a4a72e27234a02d9095080fc811848598c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 21 Feb 2018 22:40:23 +0100 Subject: [PATCH 117/128] parisc: time: stop validating rtc_time in .read_time The RTC core is always calling rtc_valid_tm after the read_time callback. It is not necessary to call it just before returning from the callback. Signed-off-by: Alexandre Belloni Acked-by: Helge Deller Signed-off-by: Alexandre Belloni --- arch/parisc/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 4b8fd6dc22da..f2890bd240f8 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -173,7 +173,7 @@ static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) /* we treat tod_sec as unsigned, so this can work until year 2106 */ rtc_time64_to_tm(tod_data.tod_sec, tm); - return rtc_valid_tm(tm); + return 0; } static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) From b3a5ac42ab18b7d1a8f2f072ca0ee76a3b754a43 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 8 Mar 2018 23:27:31 +0100 Subject: [PATCH 118/128] rtc: hctosys: Ensure system time doesn't overflow time_t On 32bit platforms, time_t is still a signed 32bit long. If it is overflowed, userspace and the kernel cant agree on the current system time. This causes multiple issues, in particular with systemd: https://github.com/systemd/systemd/issues/1143 A good workaround is to simply avoid using hctosys which is something I greatly encourage as the time is better set by userspace. However, many distribution enable it and use systemd which is rendering the system unusable in case the RTC holds a date after 2038 (and more so after 2106). Many drivers have workaround for this case and they should be eliminated so there is only one place left to fix when userspace is able to cope with dates after the 31bit overflow. Acked-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/rtc/hctosys.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index e1cfa06810ef..e79f2a181ad2 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -49,6 +49,11 @@ static int __init rtc_hctosys(void) tv64.tv_sec = rtc_tm_to_time64(&tm); +#if BITS_PER_LONG == 32 + if (tv64.tv_sec > INT_MAX) + goto err_read; +#endif + err = do_settimeofday64(&tv64); dev_info(rtc->dev.parent, From 844cba65bf92863ebdb05047eeb843d895d6b7c2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 8 Mar 2018 23:32:51 +0100 Subject: [PATCH 119/128] rtc: mv: remove artificial limitation Dates after 2038 actually fit on 32 bits. The counter will overflow in 2106. Also, it is bad practice to reset the RTC to a default value. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mv.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 944c5c0fadd0..bc52dbb0c0e2 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -223,7 +223,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev) struct resource *res; struct rtc_plat_data *pdata; u32 rtc_time; - u32 rtc_date; int ret = 0; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); @@ -259,17 +258,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev) } } - /* - * A date after January 19th, 2038 does not fit on 32 bits and - * will confuse the kernel and userspace. Reset to a sane date - * (January 1st, 2013) if we're after 2038. - */ - rtc_date = readl(pdata->ioaddr + RTC_DATE_REG_OFFS); - if (bcd2bin((rtc_date >> RTC_YEAR_OFFS) & 0xff) >= 38) { - dev_info(&pdev->dev, "invalid RTC date, resetting to January 1st, 2013\n"); - writel(0x130101, pdata->ioaddr + RTC_DATE_REG_OFFS); - } - pdata->irq = platform_get_irq(pdev, 0); platform_set_drvdata(pdev, pdata); From f441f98f5834a7f9734f6b183b5580f510344a87 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 10 Mar 2018 06:32:00 +0100 Subject: [PATCH 120/128] rtc: mrst: remove artificial limitation The hardware supports years up to 100 so don't limit the year to 2038 artificially. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mrst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 901a8d170f68..fcb9de5218b2 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -122,7 +122,7 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time) min = time->tm_min; sec = time->tm_sec; - if (yrs < 72 || yrs > 138) + if (yrs < 72 || yrs > 172) return -EINVAL; yrs -= 72; From 88c998743105806f6564ccb660b5b993dba0e741 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 10 Mar 2018 06:35:08 +0100 Subject: [PATCH 121/128] rtc: st-lpc: remove artificial limitation The LPC RTC supports dates way beyond 2038, don't limit it artificially as the kernel handles dates after 2038 properly. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-st-lpc.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 82b0af159a28..d5222667f892 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -195,7 +195,6 @@ static int st_rtc_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct st_rtc *rtc; struct resource *res; - struct rtc_time tm_check; uint32_t mode; int ret = 0; @@ -254,21 +253,6 @@ static int st_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - /* - * The RTC-LPC is able to manage date.year > 2038 - * but currently the kernel can not manage this date! - * If the RTC-LPC has a date.year > 2038 then - * it's set to the epoch "Jan 1st 2000" - */ - st_rtc_read_time(&pdev->dev, &tm_check); - - if (tm_check.tm_year >= (2038 - 1900)) { - memset(&tm_check, 0, sizeof(tm_check)); - tm_check.tm_year = 100; - tm_check.tm_mday = 1; - st_rtc_set_time(&pdev->dev, &tm_check); - } - rtc->rtc_dev = rtc_device_register("st-lpc-rtc", &pdev->dev, &st_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc_dev)) { From df15ee19da4615705b82a3975410d42c8da406e0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 10 Mar 2018 14:29:28 +0100 Subject: [PATCH 122/128] rtc: 88pm80x: remove artificial limitation The 88pm80x supports time up to 2106 (it is a 32 bit counter). Also, the year will never be before 1970 as the RTC core forbids that. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm80x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 466bf7f9a285..6cbafefa80a2 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -134,9 +134,9 @@ 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 < 70) || (tm->tm_year > 138)) { + if (tm->tm_year > 206) { dev_dbg(info->dev, - "Set time %d out of range. Please set time between 1970 to 2038.\n", + "Set time %d out of range. Please set time between 1970 to 2106.\n", 1900 + tm->tm_year); return -EINVAL; } From 9dddb1bdf60b9eeb8e37d92afe53f6bc69aa6410 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 Mar 2018 03:00:53 +0100 Subject: [PATCH 123/128] rtc: 88pm860x: remove artificial limitation The 88pm860x supports time up to 2106 (it is a 32 bit counter). Also, the year will never be before 1970 as the RTC core forbids that. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-88pm860x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 19e53b3b8e00..01ffc0ef8033 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -135,9 +135,9 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[4]; unsigned long ticks, base, data; - if ((tm->tm_year < 70) || (tm->tm_year > 138)) { + if (tm->tm_year > 206) { dev_dbg(info->dev, "Set time %d out of range. " - "Please set time between 1970 to 2038.\n", + "Please set time between 1970 to 2106.\n", 1900 + tm->tm_year); return -EINVAL; } From c7d50d2b728cc29535fbc1de7cae25ab14629642 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Thu, 1 Feb 2018 17:47:14 +0100 Subject: [PATCH 124/128] rtc: remove a warning during scripts/kernel-doc step During compilation using W=1 one would get: drivers/rtc/systohc.c:11: info: Scanning doc for rtc_set_ntp_time drivers/rtc/systohc.c:23: warning: bad line: ( Signed-off-by: Mathieu Malaterre Signed-off-by: Alexandre Belloni --- drivers/rtc/systohc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c index 0c177647ea6c..718293d72426 100644 --- a/drivers/rtc/systohc.c +++ b/drivers/rtc/systohc.c @@ -20,7 +20,7 @@ * cases. * * -EPROTO is returned if now.tv_nsec is not close enough to *target_nsec. - ( + * * If temporary failure is indicated the caller should try again 'soon' */ int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec) From 7bbd523c73c9fe0dac7938065f7f5a7167f59b5d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 22 Mar 2018 11:18:30 +0100 Subject: [PATCH 125/128] rtc: ab8500: Drop AB8540 support The AB8540 was an evolved version of the AB8500, but it was never mass produced or put into products, only reference designs exist. The upstream support was never completed and it is unlikely that this will happen so drop the support for now to simplify maintenance of the AB8500. Cc: Loic Pallardy Signed-off-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ab8500.c | 55 ---------------------------------------- 1 file changed, 55 deletions(-) diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 98c7123cd7ba..e28f4401fd35 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -36,10 +36,6 @@ #define AB8500_RTC_FORCE_BKUP_REG 0x0D #define AB8500_RTC_CALIB_REG 0x0E #define AB8500_RTC_SWITCH_STAT_REG 0x0F -#define AB8540_RTC_ALRM_SEC 0x22 -#define AB8540_RTC_ALRM_MIN_LOW_REG 0x23 -#define AB8540_RTC_ALRM_MIN_MID_REG 0x24 -#define AB8540_RTC_ALRM_MIN_HI_REG 0x25 /* RtcReadRequest bits */ #define RTC_READ_REQUEST 0x01 @@ -63,11 +59,6 @@ static const u8 ab8500_rtc_alarm_regs[] = { AB8500_RTC_ALRM_MIN_LOW_REG }; -static const u8 ab8540_rtc_alarm_regs[] = { - AB8540_RTC_ALRM_MIN_HI_REG, AB8540_RTC_ALRM_MIN_MID_REG, - AB8540_RTC_ALRM_MIN_LOW_REG, AB8540_RTC_ALRM_SEC -}; - /* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ static unsigned long get_elapsed_seconds(int year) { @@ -277,43 +268,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) return ab8500_rtc_irq_enable(dev, alarm->enabled); } -static int ab8540_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - int retval, i; - unsigned char buf[ARRAY_SIZE(ab8540_rtc_alarm_regs)]; - unsigned long mins, secs = 0; - - if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - - /* Get the number of seconds since 1970 */ - rtc_tm_to_time(&alarm->time, &secs); - - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00 - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); - mins = secs / 60; - - buf[3] = secs % 60; - buf[2] = mins & 0xFF; - buf[1] = (mins >> 8) & 0xFF; - buf[0] = (mins >> 16) & 0xFF; - - /* Set the alarm time */ - for (i = 0; i < ARRAY_SIZE(ab8540_rtc_alarm_regs); i++) { - retval = abx500_set_register_interruptible(dev, AB8500_RTC, - ab8540_rtc_alarm_regs[i], buf[i]); - if (retval < 0) - return retval; - } - - return ab8500_rtc_irq_enable(dev, alarm->enabled); -} - static int ab8500_rtc_set_calibration(struct device *dev, int calibration) { int retval; @@ -435,17 +389,8 @@ static const struct rtc_class_ops ab8500_rtc_ops = { .alarm_irq_enable = ab8500_rtc_irq_enable, }; -static const struct rtc_class_ops ab8540_rtc_ops = { - .read_time = ab8500_rtc_read_time, - .set_time = ab8500_rtc_set_time, - .read_alarm = ab8500_rtc_read_alarm, - .set_alarm = ab8540_rtc_set_alarm, - .alarm_irq_enable = ab8500_rtc_irq_enable, -}; - static const struct platform_device_id ab85xx_rtc_ids[] = { { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, }, - { "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids); From c1f5f0549d62c534d3d102b87c856a8907862d8f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 22 Mar 2018 14:53:28 -0500 Subject: [PATCH 126/128] rtc: isl12022: use true and false for boolean values Assign true or false to boolean variables instead of an integer value. This issue was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-isl12022.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index fa5c15d45070..890ccfc9e5aa 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -201,7 +201,7 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - isl12022->write_enabled = 1; + isl12022->write_enabled = true; } /* hours, minutes and seconds */ From 3fc990a5dbfff26fe2ef1286d9268d55a3136206 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 26 Mar 2018 18:05:52 +0800 Subject: [PATCH 127/128] rtc: mt7622: fix module autoloading for OF platform drivers It's required to create a modules.alias via MODULE_DEVICE_TABLE helper for the OF platform driver. Otherwise, module autoloading cannot work. Signed-off-by: Sean Wang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-mt7622.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c index da213278f343..fd0cea722286 100644 --- a/drivers/rtc/rtc-mt7622.c +++ b/drivers/rtc/rtc-mt7622.c @@ -307,6 +307,7 @@ static const struct of_device_id mtk_rtc_match[] = { { .compatible = "mediatek,soc-rtc" }, {}, }; +MODULE_DEVICE_TABLE(of, mtk_rtc_match); static int mtk_rtc_probe(struct platform_device *pdev) { From 1485991c024603b2fb4ae77beb7a0d741128a48e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 28 Mar 2018 20:14:05 +0100 Subject: [PATCH 128/128] rtc: snvs: Fix usage of snvs_rtc_enable commit 179a502f8c46 ("rtc: snvs: add Freescale rtc-snvs driver") introduces the SNVS RTC driver with a function snvs_rtc_enable(). snvs_rtc_enable() can return an error on the enable path however this driver does not currently trap that failure on the probe() path and consequently if enabling the RTC fails we encounter a later error spinning forever in rtc_write_sync_lp(). [ 36.093481] [] (__irq_svc) from [] (_raw_spin_unlock_irqrestore+0x34/0x44) [ 36.102122] [] (_raw_spin_unlock_irqrestore) from [] (regmap_read+0x4c/0x5c) [ 36.110938] [] (regmap_read) from [] (rtc_write_sync_lp+0x6c/0x98) [ 36.118881] [] (rtc_write_sync_lp) from [] (snvs_rtc_alarm_irq_enable+0x40/0x4c) [ 36.128041] [] (snvs_rtc_alarm_irq_enable) from [] (rtc_timer_do_work+0xd8/0x1a8) [ 36.137291] [] (rtc_timer_do_work) from [] (process_one_work+0x28c/0x76c) [ 36.145840] [] (process_one_work) from [] (worker_thread+0x34/0x58c) [ 36.153961] [] (worker_thread) from [] (kthread+0x138/0x150) [ 36.161388] [] (kthread) from [] (ret_from_fork+0x14/0x20) [ 36.168635] rcu_sched kthread starved for 2602 jiffies! g496 c495 f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0 ->cpu=0 [ 36.178564] rcu_sched R running task 0 8 2 0x00000000 [ 36.185664] [] (__schedule) from [] (schedule+0x3c/0xa0) [ 36.192739] [] (schedule) from [] (schedule_timeout+0x78/0x4e0) [ 36.200422] [] (schedule_timeout) from [] (rcu_gp_kthread+0x648/0x1864) [ 36.208800] [] (rcu_gp_kthread) from [] (kthread+0x138/0x150) [ 36.216309] [] (kthread) from [] (ret_from_fork+0x14/0x20) This patch fixes by parsing the result of rtc_write_sync_lp() and propagating both in the probe and elsewhere. If the RTC doesn't start we don't proceed loading the driver and don't get into this loop mess later on. Fixes: 179a502f8c46 ("rtc: snvs: add Freescale rtc-snvs driver") Signed-off-by: Bryan O'Donoghue Acked-by: Shawn Guo Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index d8ef9e052c4f..9af591d5223c 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -132,20 +132,23 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct snvs_rtc_data *data = dev_get_drvdata(dev); unsigned long time; + int ret; rtc_tm_to_time(tm, &time); /* Disable RTC first */ - snvs_rtc_enable(data, false); + ret = snvs_rtc_enable(data, false); + if (ret) + return ret; /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */ regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH); regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH)); /* Enable RTC again */ - snvs_rtc_enable(data, true); + ret = snvs_rtc_enable(data, true); - return 0; + return ret; } static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) @@ -288,7 +291,11 @@ static int snvs_rtc_probe(struct platform_device *pdev) regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff); /* Enable RTC */ - snvs_rtc_enable(data, true); + ret = snvs_rtc_enable(data, true); + if (ret) { + dev_err(&pdev->dev, "failed to enable rtc %d\n", ret); + goto error_rtc_device_register; + } device_init_wakeup(&pdev->dev, true);