summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eichenberger <stefan.eichenberger@toradex.com>2022-11-03 16:29:08 +0100
committerFrancesco Dolcini <francesco.dolcini@toradex.com>2022-11-09 17:34:03 +0000
commit7fa95acb6fdcc61bd128183f19c47e51eafcbc6b (patch)
tree9bb66de2e833dc4f86409c7254ef4af358c4f879
parentb6a453bdcd4841f44dc6c86f2abd06fe97936580 (diff)
linux-toradex-mainline: Add patch to fix an RTC issue appearing on iMX6ULL
This is a fix for an issue with the RTC on the Colibri iMX6ULL. The issue can be triggered as follows: echo 0 > /sys/class/rtc/rtc1/wakealarm rtc rtc1: Timeout trying to get valid LPSRT Counter read Related-to: ELB-4814 Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
-rw-r--r--recipes-kernel/linux/linux-toradex-mainline-git/0001-rtc-snvs-Allow-a-time-difference-on-clock-register-r.patch84
-rw-r--r--recipes-kernel/linux/linux-toradex-mainline_git.bb1
2 files changed, 85 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-toradex-mainline-git/0001-rtc-snvs-Allow-a-time-difference-on-clock-register-r.patch b/recipes-kernel/linux/linux-toradex-mainline-git/0001-rtc-snvs-Allow-a-time-difference-on-clock-register-r.patch
new file mode 100644
index 0000000..5f7e6e9
--- /dev/null
+++ b/recipes-kernel/linux/linux-toradex-mainline-git/0001-rtc-snvs-Allow-a-time-difference-on-clock-register-r.patch
@@ -0,0 +1,84 @@
+From 97bddda523427274f0fb45971a5d33407449a054 Mon Sep 17 00:00:00 2001
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Date: Wed, 2 Nov 2022 13:24:23 +0100
+Subject: [PATCH] rtc: snvs: Allow a time difference on clock register read
+
+On an iMX6ULL the following message appears when a wakealarm is set:
+
+echo 0 > /sys/class/rtc/rtc1/wakealarm
+rtc rtc1: Timeout trying to get valid LPSRT Counter read
+
+This does not always happen but is reproducible quite often (7 out of 10
+times). The problem appears because the iMX6ULL is not able to read the
+registers within one 32kHz clock cycle which is the base clock of the
+RTC. Therefore, this patch allows a difference of up to 320 cycles
+(10ms). 10ms was chosen to be big enough even on systems with less cpu
+power (e.g. iMX6ULL). According to the reference manual a difference is
+fine:
+- If the two consecutive reads are similar, the value is correct.
+The values have to be similar, not equal.
+
+Upstream-Status: Submitted [https://lore.kernel.org/linux-rtc/20221106115915.7930-1-francesco@dolcini.it]
+Fixes: cd7f3a249dbe ("rtc: snvs: Add timeouts to avoid kernel lockups")
+Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+---
+ drivers/rtc/rtc-snvs.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
+index bd929b0e7d7de..d82acf1af1fae 100644
+--- a/drivers/rtc/rtc-snvs.c
++++ b/drivers/rtc/rtc-snvs.c
+@@ -32,6 +32,14 @@
+ #define SNVS_LPPGDR_INIT 0x41736166
+ #define CNTR_TO_SECS_SH 15
+
++/* The maximum RTC clock cycles that are allowed to pass between two
++ * consecutive clock counter register reads. If the values are corrupted a
++ * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles
++ * we end at 10ms which should be enough for most cases. If it once takes
++ * longer than expected we do a retry.
++ */
++#define MAX_RTC_READ_DIFF_CYCLES 320
++
+ struct snvs_rtc_data {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+@@ -56,6 +64,7 @@ static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
+ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
+ {
+ u64 read1, read2;
++ s64 diff;
+ unsigned int timeout = 100;
+
+ /* As expected, the registers might update between the read of the LSB
+@@ -66,7 +75,8 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
+ do {
+ read2 = read1;
+ read1 = rtc_read_lpsrt(data);
+- } while (read1 != read2 && --timeout);
++ diff = read1 - read2;
++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
+ if (!timeout)
+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+
+@@ -78,13 +88,15 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
+ static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
+ {
+ u32 count1, count2;
++ s32 diff;
+ unsigned int timeout = 100;
+
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+ do {
+ count2 = count1;
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+- } while (count1 != count2 && --timeout);
++ diff = count1 - count2;
++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
+ if (!timeout) {
+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+ return -ETIMEDOUT;
+--
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-toradex-mainline_git.bb b/recipes-kernel/linux/linux-toradex-mainline_git.bb
index e066e62..6fdc488 100644
--- a/recipes-kernel/linux/linux-toradex-mainline_git.bb
+++ b/recipes-kernel/linux/linux-toradex-mainline_git.bb
@@ -35,6 +35,7 @@ SRC_URI:append = " \
file://0002-arm-dts-colibri-imx6ull-enable-default-peripherals.patch \
file://0001-ARM-dts-colibri-imx6ull-Enable-dual-role-switching.patch \
file://0002-drivers-chipidea-disable-runtime-pm-for-imx6ul.patch \
+ file://0001-rtc-snvs-Allow-a-time-difference-on-clock-register-r.patch \
"
LINUX_VERSION ?= "6.0.6"