.. | .. |
---|
32 | 32 | #define SNVS_LPPGDR_INIT 0x41736166 |
---|
33 | 33 | #define CNTR_TO_SECS_SH 15 |
---|
34 | 34 | |
---|
| 35 | +/* The maximum RTC clock cycles that are allowed to pass between two |
---|
| 36 | + * consecutive clock counter register reads. If the values are corrupted a |
---|
| 37 | + * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles |
---|
| 38 | + * we end at 10ms which should be enough for most cases. If it once takes |
---|
| 39 | + * longer than expected we do a retry. |
---|
| 40 | + */ |
---|
| 41 | +#define MAX_RTC_READ_DIFF_CYCLES 320 |
---|
| 42 | + |
---|
35 | 43 | struct snvs_rtc_data { |
---|
36 | 44 | struct rtc_device *rtc; |
---|
37 | 45 | struct regmap *regmap; |
---|
.. | .. |
---|
56 | 64 | static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) |
---|
57 | 65 | { |
---|
58 | 66 | u64 read1, read2; |
---|
| 67 | + s64 diff; |
---|
59 | 68 | unsigned int timeout = 100; |
---|
60 | 69 | |
---|
61 | 70 | /* As expected, the registers might update between the read of the LSB |
---|
.. | .. |
---|
66 | 75 | do { |
---|
67 | 76 | read2 = read1; |
---|
68 | 77 | read1 = rtc_read_lpsrt(data); |
---|
69 | | - } while (read1 != read2 && --timeout); |
---|
| 78 | + diff = read1 - read2; |
---|
| 79 | + } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); |
---|
70 | 80 | if (!timeout) |
---|
71 | 81 | dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); |
---|
72 | 82 | |
---|
.. | .. |
---|
78 | 88 | static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb) |
---|
79 | 89 | { |
---|
80 | 90 | u32 count1, count2; |
---|
| 91 | + s32 diff; |
---|
81 | 92 | unsigned int timeout = 100; |
---|
82 | 93 | |
---|
83 | 94 | regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); |
---|
84 | 95 | do { |
---|
85 | 96 | count2 = count1; |
---|
86 | 97 | regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); |
---|
87 | | - } while (count1 != count2 && --timeout); |
---|
| 98 | + diff = count1 - count2; |
---|
| 99 | + } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); |
---|
88 | 100 | if (!timeout) { |
---|
89 | 101 | dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); |
---|
90 | 102 | return -ETIMEDOUT; |
---|