Patch "rtc: snvs: Allow a time difference on clock register read" has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    rtc: snvs: Allow a time difference on clock register read

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     rtc-snvs-allow-a-time-difference-on-clock-register-r.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 5702194b3191c90db0e52c1f9014673b47f3dc7a
Author: Stefan Eichenberger <stefan.eichenberger@xxxxxxxxxxx>
Date:   Sun Nov 6 12:59:15 2022 +0100

    rtc: snvs: Allow a time difference on clock register read
    
    [ Upstream commit 0462681e207ccc44778a77b3297af728b1cf5b9f ]
    
    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.
    
    Fixes: cd7f3a249dbe ("rtc: snvs: Add timeouts to avoid kernel lockups")
    Reviewed-by: Francesco Dolcini <francesco.dolcini@xxxxxxxxxxx>
    Signed-off-by: Stefan Eichenberger <stefan.eichenberger@xxxxxxxxxxx>
    Signed-off-by: Francesco Dolcini <francesco@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20221106115915.7930-1-francesco@xxxxxxxxxx
    Signed-off-by: Alexandre Belloni <alexandre.belloni@xxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index bd929b0e7d7d..d82acf1af1fa 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;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux