* [PATCH 1/5] rtc: rv8803: factor out existing register initialization to function
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
@ 2022-04-26 7:10 ` Sascha Hauer
2022-04-26 7:10 ` [PATCH 2/5] rtc: rv8803: initialize registers on post-probe voltage loss Sascha Hauer
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2022-04-26 7:10 UTC (permalink / raw)
To: linux-rtc
Cc: Alessandro Zummo, Alexandre Belloni, kernel, Ahmad Fatoum,
Sascha Hauer
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
The driver probe currently initializes some registers to non-POR
values. These values are not reinstated if the RTC experiences voltage
loss later on. Prepare for fixing this by factoring out the
initialization to a separate function.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/rtc/rtc-rv8803.c | 43 +++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index f69e0b1137cd0..c880f8d6c7423 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -64,6 +64,7 @@ struct rv8803_data {
struct rtc_device *rtc;
struct mutex flags_lock;
u8 ctrl;
+ u8 backup;
enum rv8803_type type;
};
@@ -498,18 +499,32 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
if (err < 0)
return err;
- flags = ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF) & (u8)err;
-
- if (of_property_read_bool(node, "epson,vdet-disable"))
- flags |= RX8900_FLAG_VDETOFF;
-
- if (of_property_read_bool(node, "trickle-diode-disable"))
- flags |= RX8900_FLAG_SWOFF;
+ flags = (u8)err;
+ flags &= ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF);
+ flags |= rv8803->backup;
return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL,
flags);
}
+/* configure registers with values different than the Power-On reset defaults */
+static int rv8803_regs_configure(struct rv8803_data *rv8803)
+{
+ int err;
+
+ err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
+ if (err)
+ return err;
+
+ err = rx8900_trickle_charger_init(rv8803);
+ if (err) {
+ dev_err(&rv8803->client->dev, "failed to init charger\n");
+ return err;
+ }
+
+ return 0;
+}
+
static int rv8803_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -576,15 +591,15 @@ static int rv8803_probe(struct i2c_client *client,
if (!client->irq)
clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
- err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
- if (err)
- return err;
+ if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable"))
+ rv8803->backup |= RX8900_FLAG_VDETOFF;
- err = rx8900_trickle_charger_init(rv8803);
- if (err) {
- dev_err(&client->dev, "failed to init charger\n");
+ if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
+ rv8803->backup |= RX8900_FLAG_SWOFF;
+
+ err = rv8803_regs_configure(rv8803);
+ if (err)
return err;
- }
rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 2/5] rtc: rv8803: initialize registers on post-probe voltage loss
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
2022-04-26 7:10 ` [PATCH 1/5] rtc: rv8803: factor out existing register initialization to function Sascha Hauer
@ 2022-04-26 7:10 ` Sascha Hauer
2022-04-26 7:10 ` [PATCH 3/5] rtc: rv8803: re-initialize all Epson RX8803 registers on " Sascha Hauer
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2022-04-26 7:10 UTC (permalink / raw)
To: linux-rtc
Cc: Alessandro Zummo, Alexandre Belloni, kernel, Ahmad Fatoum,
Sascha Hauer
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
The driver probe currently initializes some registers to non-POR
values. These values are not reinstated if the RTC experiences voltage
loss later on. Fix this.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/rtc/rtc-rv8803.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index c880f8d6c7423..21a6f1eddb092 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -137,6 +137,13 @@ static int rv8803_write_regs(const struct i2c_client *client,
return ret;
}
+static int rv8803_regs_configure(struct rv8803_data *rv8803);
+
+static int rv8803_regs_reset(struct rv8803_data *rv8803)
+{
+ return rv8803_regs_configure(rv8803);
+}
+
static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
@@ -270,6 +277,12 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
return flags;
}
+ if (flags & RV8803_FLAG_V2F) {
+ ret = rv8803_regs_reset(rv8803);
+ if (ret)
+ return ret;
+ }
+
ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 3/5] rtc: rv8803: re-initialize all Epson RX8803 registers on voltage loss
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
2022-04-26 7:10 ` [PATCH 1/5] rtc: rv8803: factor out existing register initialization to function Sascha Hauer
2022-04-26 7:10 ` [PATCH 2/5] rtc: rv8803: initialize registers on post-probe voltage loss Sascha Hauer
@ 2022-04-26 7:10 ` Sascha Hauer
2022-04-26 7:10 ` [PATCH 4/5] include/linux/bcd.h: provide bcd_is_valid() helper Sascha Hauer
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2022-04-26 7:10 UTC (permalink / raw)
To: linux-rtc
Cc: Alessandro Zummo, Alexandre Belloni, kernel, Ahmad Fatoum,
Sascha Hauer
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
The reference manuals of both the RX8803 and RV8803 dictate that
"[On V2F/VLF = ] all registers must be initialized".
The RV-8803 application manual (rev. 1.6) further specifies that crossing
V_LOW2 threshold enables flag V2F and triggers a Power-On reset.
According to table 3.11 in the document, all control registers are
defined to sensible values.
However, The Epson RX-8803 doesn't offer the same guarantees.
It explicitly states:
During the initial power-up, the TEST bit is reset to "0" and the VLF
bit is set to "1".
∗ At this point, all other register values are _undefined_, so be sure to
perform a reset before using the module.
Commit d3700b6b6479 ("rtc: rv8803: Stop the clock while setting the time")
also had this rationale:
Indeed, all the registers must be initialized if the voltage has been
lower than VLOW2 (triggering V2F), but not low enough to trigger a POR.
We should follow the advice and initialize all applicable registers.
We can group the registers into 3 groups:
A) Already correctly handled registers:
* 0B-0Ch | Timer Counter | unused and disabled by clearing TE in 0Dh
* 0Dh | Extension Reg | already initialized in rv8803_regs_configure
* 0Eh | Flag Reg | handled in IRQ handler, except for VLF, VDET
* 0Eh | VLF, VDET | cleared in ->set_time
* 10h | 100th Seconds | Already reset via RESET bit
* 20-21h | Capture Buffer | holds timestamp unused by driver
* 2Fh | Event Control | resets automatically
B) Registers that are hardware initialized on POR, but not on VLF:
* 0Fh | Control Reg
* 2Ch | OSC Offset
C) RAM that is undefined on voltage loss:
* 00-06h | Date/Time
* 07h | RAM
* 08-0Ah | Alarm
This means we should initialize after VLF the registers in group B
(RV8803_CTRL and RV8803_OSC_OFFSET).
Group C is all-zero after voltage loss on the RV-8803, but undefined on
the RX-8803. This is ok for Date/Time because ->get_time returns an
error code for as long as the voltage loss flag is active. It's cleared
on ->set_time however. Zeroing both RAM and alarm ensures a fixed value
is read afterwards.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/rtc/rtc-rv8803.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 21a6f1eddb092..fe1247e771b98 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -9,6 +9,7 @@
#include <linux/bcd.h>
#include <linux/bitops.h>
+#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -33,6 +34,7 @@
#define RV8803_EXT 0x0D
#define RV8803_FLAG 0x0E
#define RV8803_CTRL 0x0F
+#define RV8803_OSC_OFFSET 0x2C
#define RV8803_EXT_WADA BIT(6)
@@ -49,12 +51,15 @@
#define RV8803_CTRL_TIE BIT(4)
#define RV8803_CTRL_UIE BIT(5)
+#define RX8803_CTRL_CSEL GENMASK(7, 6)
+
#define RX8900_BACKUP_CTRL 0x18
#define RX8900_FLAG_SWOFF BIT(2)
#define RX8900_FLAG_VDETOFF BIT(3)
enum rv8803_type {
rv_8803,
+ rx_8803,
rx_8804,
rx_8900
};
@@ -137,10 +142,41 @@ static int rv8803_write_regs(const struct i2c_client *client,
return ret;
}
+static int rv8803_regs_init(struct rv8803_data *rv8803)
+{
+ int ret;
+
+ ret = rv8803_write_reg(rv8803->client, RV8803_OSC_OFFSET, 0x00);
+ if (ret)
+ return ret;
+
+ ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+ FIELD_PREP(RX8803_CTRL_CSEL, 1)); /* 2s */
+ if (ret)
+ return ret;
+
+ ret = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3,
+ (u8[]){ 0, 0, 0 });
+ if (ret)
+ return ret;
+
+ return rv8803_write_reg(rv8803->client, RV8803_RAM, 0x00);
+}
+
static int rv8803_regs_configure(struct rv8803_data *rv8803);
static int rv8803_regs_reset(struct rv8803_data *rv8803)
{
+ /*
+ * The RV-8803 resets all registers to POR defaults after voltage-loss,
+ * the Epson RTCs don't, so we manually reset the remainder here.
+ */
+ if (rv8803->type == rx_8803 || rv8803->type == rx_8900) {
+ int ret = rv8803_regs_init(rv8803);
+ if (ret)
+ return ret;
+ }
+
return rv8803_regs_configure(rv8803);
}
@@ -631,7 +667,7 @@ static int rv8803_probe(struct i2c_client *client,
static const struct i2c_device_id rv8803_id[] = {
{ "rv8803", rv_8803 },
{ "rv8804", rx_8804 },
- { "rx8803", rv_8803 },
+ { "rx8803", rx_8803 },
{ "rx8900", rx_8900 },
{ }
};
@@ -644,7 +680,7 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
},
{
.compatible = "epson,rx8803",
- .data = (void *)rv_8803
+ .data = (void *)rx_8803
},
{
.compatible = "epson,rx8804",
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 4/5] include/linux/bcd.h: provide bcd_is_valid() helper
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
` (2 preceding siblings ...)
2022-04-26 7:10 ` [PATCH 3/5] rtc: rv8803: re-initialize all Epson RX8803 registers on " Sascha Hauer
@ 2022-04-26 7:10 ` Sascha Hauer
2022-04-26 7:10 ` [PATCH 5/5] rtc: rv8803: invalidate date/time if alarm time is invalid Sascha Hauer
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2022-04-26 7:10 UTC (permalink / raw)
To: linux-rtc
Cc: Alessandro Zummo, Alexandre Belloni, kernel, Ahmad Fatoum,
Sascha Hauer
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
bcd2bin(0x0A) happily returns 10, despite this being an invalid BCD
value. RTC drivers converting possibly corrupted BCD timestamps might
want to validate their input before calling bcd2bin().
Provide a macro to do so. Unlike bcd2bin and bin2bcd, out-of-line
versions are not implemented. Should the macro experience enough use,
this can be retrofitted.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
include/linux/bcd.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/bcd.h b/include/linux/bcd.h
index 118bea36d7d49..abbc8149178e6 100644
--- a/include/linux/bcd.h
+++ b/include/linux/bcd.h
@@ -14,8 +14,12 @@
const_bin2bcd(x) : \
_bin2bcd(x))
+#define bcd_is_valid(x) \
+ const_bcd_is_valid(x)
+
#define const_bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10)
#define const_bin2bcd(x) ((((x) / 10) << 4) + (x) % 10)
+#define const_bcd_is_valid(x) (((x) & 0x0f) < 10 && ((x) >> 4) < 10)
unsigned _bcd2bin(unsigned char val) __attribute_const__;
unsigned char _bin2bcd(unsigned val) __attribute_const__;
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 5/5] rtc: rv8803: invalidate date/time if alarm time is invalid
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
` (3 preceding siblings ...)
2022-04-26 7:10 ` [PATCH 4/5] include/linux/bcd.h: provide bcd_is_valid() helper Sascha Hauer
@ 2022-04-26 7:10 ` Sascha Hauer
2022-06-24 16:33 ` Alexandre Belloni
2022-05-23 10:25 ` [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
2022-06-24 16:57 ` (subset) " Alexandre Belloni
6 siblings, 1 reply; 9+ messages in thread
From: Sascha Hauer @ 2022-04-26 7:10 UTC (permalink / raw)
To: linux-rtc
Cc: Alessandro Zummo, Alexandre Belloni, kernel, Ahmad Fatoum,
Sascha Hauer
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
RTC core never calls rv8803_set_alarm with an invalid alarm time,
so if an invalid alarm time > 0 is set, external factors must have
corrupted the RTC's alarm time and possibly other registers.
Play it safe by marking the date/time invalid, so all registers are
reinitialized on a ->set_time.
This may cause existing setups to lose time if they so far set only
date/time, but ignored that the alarm registers had an invalid date
value, e.g.:
rtc rtc0: invalid alarm value: 2020-3-27 7:82:0
These systems will have their ->get_time return -EINVAL till
->set_time initializes the alarm value (and sets a new time).
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/rtc/rtc-rv8803.c | 46 +++++++++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 10 deletions(-)
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index fe1247e771b98..036c449cf1c20 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -70,6 +70,7 @@ struct rv8803_data {
struct mutex flags_lock;
u8 ctrl;
u8 backup;
+ u8 alarm_invalid:1;
enum rv8803_type type;
};
@@ -165,13 +166,13 @@ static int rv8803_regs_init(struct rv8803_data *rv8803)
static int rv8803_regs_configure(struct rv8803_data *rv8803);
-static int rv8803_regs_reset(struct rv8803_data *rv8803)
+static int rv8803_regs_reset(struct rv8803_data *rv8803, bool full)
{
/*
* The RV-8803 resets all registers to POR defaults after voltage-loss,
* the Epson RTCs don't, so we manually reset the remainder here.
*/
- if (rv8803->type == rx_8803 || rv8803->type == rx_8900) {
+ if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900) {
int ret = rv8803_regs_init(rv8803);
if (ret)
return ret;
@@ -238,6 +239,11 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
u8 *date = date1;
int ret, flags;
+ if (rv8803->alarm_invalid) {
+ dev_warn(dev, "Corruption detected, data may be invalid.\n");
+ return -EINVAL;
+ }
+
flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0)
return flags;
@@ -313,10 +319,16 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
return flags;
}
- if (flags & RV8803_FLAG_V2F) {
- ret = rv8803_regs_reset(rv8803);
+ if ((flags & RV8803_FLAG_V2F) || rv8803->alarm_invalid) {
+ /*
+ * If we sense corruption in the alarm registers, but see no
+ * voltage loss flag, we can't rely on other registers having
+ * sensible values. Reset them fully.
+ */
+ ret = rv8803_regs_reset(rv8803, rv8803->alarm_invalid);
if (ret)
return ret;
+ rv8803->alarm_invalid = false;
}
ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
@@ -342,13 +354,27 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (flags < 0)
return flags;
- alrm->time.tm_sec = 0;
- alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
- alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
- alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
+ alarmvals[0] &= 0x7f;
+ alarmvals[1] &= 0x3f;
+ alarmvals[2] &= 0x3f;
+
+ if (bcd_is_valid(alarmvals[0]) && bcd_is_valid(alarmvals[1]) &&
+ bcd_is_valid(alarmvals[2])) {
+ alrm->time.tm_sec = 0;
+ alrm->time.tm_min = bcd2bin(alarmvals[0]);
+ alrm->time.tm_hour = bcd2bin(alarmvals[1]);
+ alrm->time.tm_mday = bcd2bin(alarmvals[2]);
- alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
- alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
+ alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
+ alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
+ }
+
+ if ((unsigned)alrm->time.tm_mday > 31 ||
+ (unsigned)alrm->time.tm_hour >= 24 ||
+ (unsigned)alrm->time.tm_min >= 60) {
+ rv8803->alarm_invalid = true;
+ return -EINVAL;
+ }
return 0;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH 5/5] rtc: rv8803: invalidate date/time if alarm time is invalid
2022-04-26 7:10 ` [PATCH 5/5] rtc: rv8803: invalidate date/time if alarm time is invalid Sascha Hauer
@ 2022-06-24 16:33 ` Alexandre Belloni
0 siblings, 0 replies; 9+ messages in thread
From: Alexandre Belloni @ 2022-06-24 16:33 UTC (permalink / raw)
To: Sascha Hauer; +Cc: linux-rtc, Alessandro Zummo, kernel, Ahmad Fatoum
Hello Sascha,
Sorry for the very late review. I'm mostly fine with the whole series.
On 26/04/2022 09:10:56+0200, Sascha Hauer wrote:
> From: Ahmad Fatoum <a.fatoum@pengutronix.de>
>
> RTC core never calls rv8803_set_alarm with an invalid alarm time,
> so if an invalid alarm time > 0 is set, external factors must have
> corrupted the RTC's alarm time and possibly other registers.
>
> Play it safe by marking the date/time invalid, so all registers are
> reinitialized on a ->set_time.
>
> This may cause existing setups to lose time if they so far set only
> date/time, but ignored that the alarm registers had an invalid date
> value, e.g.:
>
> rtc rtc0: invalid alarm value: 2020-3-27 7:82:0
>
> These systems will have their ->get_time return -EINVAL till
> ->set_time initializes the alarm value (and sets a new time).
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/rtc/rtc-rv8803.c | 46 +++++++++++++++++++++++++++++++---------
> 1 file changed, 36 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
> index fe1247e771b98..036c449cf1c20 100644
> --- a/drivers/rtc/rtc-rv8803.c
> +++ b/drivers/rtc/rtc-rv8803.c
> @@ -70,6 +70,7 @@ struct rv8803_data {
> struct mutex flags_lock;
> u8 ctrl;
> u8 backup;
> + u8 alarm_invalid:1;
> enum rv8803_type type;
> };
>
> @@ -165,13 +166,13 @@ static int rv8803_regs_init(struct rv8803_data *rv8803)
>
> static int rv8803_regs_configure(struct rv8803_data *rv8803);
>
> -static int rv8803_regs_reset(struct rv8803_data *rv8803)
> +static int rv8803_regs_reset(struct rv8803_data *rv8803, bool full)
> {
> /*
> * The RV-8803 resets all registers to POR defaults after voltage-loss,
> * the Epson RTCs don't, so we manually reset the remainder here.
> */
> - if (rv8803->type == rx_8803 || rv8803->type == rx_8900) {
> + if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900) {
> int ret = rv8803_regs_init(rv8803);
> if (ret)
> return ret;
> @@ -238,6 +239,11 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
> u8 *date = date1;
> int ret, flags;
>
> + if (rv8803->alarm_invalid) {
> + dev_warn(dev, "Corruption detected, data may be invalid.\n");
> + return -EINVAL;
> + }
> +
> flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
> if (flags < 0)
> return flags;
> @@ -313,10 +319,16 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
> return flags;
> }
>
> - if (flags & RV8803_FLAG_V2F) {
> - ret = rv8803_regs_reset(rv8803);
> + if ((flags & RV8803_FLAG_V2F) || rv8803->alarm_invalid) {
> + /*
> + * If we sense corruption in the alarm registers, but see no
> + * voltage loss flag, we can't rely on other registers having
> + * sensible values. Reset them fully.
> + */
> + ret = rv8803_regs_reset(rv8803, rv8803->alarm_invalid);
> if (ret)
> return ret;
> + rv8803->alarm_invalid = false;
> }
>
> ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
> @@ -342,13 +354,27 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> if (flags < 0)
> return flags;
>
> - alrm->time.tm_sec = 0;
> - alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
> - alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
> - alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
> + alarmvals[0] &= 0x7f;
> + alarmvals[1] &= 0x3f;
> + alarmvals[2] &= 0x3f;
> +
> + if (bcd_is_valid(alarmvals[0]) && bcd_is_valid(alarmvals[1]) &&
> + bcd_is_valid(alarmvals[2])) {
> + alrm->time.tm_sec = 0;
> + alrm->time.tm_min = bcd2bin(alarmvals[0]);
> + alrm->time.tm_hour = bcd2bin(alarmvals[1]);
> + alrm->time.tm_mday = bcd2bin(alarmvals[2]);
>
> - alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
> - alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
> + alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
> + alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
> + }
> +
> + if ((unsigned)alrm->time.tm_mday > 31 ||
You'd need to use (unsigned int) here, else I'll get follow up patches
doing the conversion. My only issue is actually this check as it would
be better to use rtc_valid_tm that checks tm_month but obviously, your
rtc_tm is missing information at this time and this would require to
replicate what is done in __rtc_read_alarm. I don't have a great
solution to that though
> + (unsigned)alrm->time.tm_hour >= 24 ||
> + (unsigned)alrm->time.tm_min >= 60) {
> + rv8803->alarm_invalid = true;
> + return -EINVAL;
> + }
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/5] rtc: rv8803 patches
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
` (4 preceding siblings ...)
2022-04-26 7:10 ` [PATCH 5/5] rtc: rv8803: invalidate date/time if alarm time is invalid Sascha Hauer
@ 2022-05-23 10:25 ` Sascha Hauer
2022-06-24 16:57 ` (subset) " Alexandre Belloni
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2022-05-23 10:25 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc
Alessandro, Alexandre,
Any input to this one?
Thanks,
Sascha
On Tue, Apr 26, 2022 at 09:10:51AM +0200, Sascha Hauer wrote:
> This series has some patches for the rx8803 RTC handled by the rv8803
> driver. These patches mostly improve the voltage loss handling in the
> rx8803. While the rv8803 resets its registers on voltage loss the rx8803
> leaves registers in an undefined state after voltage loss. The patches
> are used here for a customer for quite a while, it's time to upstream
> them.
>
> Sascha
>
> Ahmad Fatoum (5):
> rtc: rv8803: factor out existing register initialization to function
> rtc: rv8803: initialize registers on post-probe voltage loss
> rtc: rv8803: re-initialize all Epson RX8803 registers on voltage loss
> include/linux/bcd.h: provide bcd_is_valid() helper
> rtc: rv8803: invalidate date/time if alarm time is invalid
>
> drivers/rtc/rtc-rv8803.c | 134 ++++++++++++++++++++++++++++++++-------
> include/linux/bcd.h | 4 ++
> 2 files changed, 116 insertions(+), 22 deletions(-)
>
> --
> 2.30.2
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: (subset) [PATCH 0/5] rtc: rv8803 patches
2022-04-26 7:10 [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
` (5 preceding siblings ...)
2022-05-23 10:25 ` [PATCH 0/5] rtc: rv8803 patches Sascha Hauer
@ 2022-06-24 16:57 ` Alexandre Belloni
6 siblings, 0 replies; 9+ messages in thread
From: Alexandre Belloni @ 2022-06-24 16:57 UTC (permalink / raw)
To: linux-rtc, Sascha Hauer; +Cc: kernel, a.zummo
On Tue, 26 Apr 2022 09:10:51 +0200, Sascha Hauer wrote:
> This series has some patches for the rx8803 RTC handled by the rv8803
> driver. These patches mostly improve the voltage loss handling in the
> rx8803. While the rv8803 resets its registers on voltage loss the rx8803
> leaves registers in an undefined state after voltage loss. The patches
> are used here for a customer for quite a while, it's time to upstream
> them.
>
> [...]
Applied, thanks!
[1/5] rtc: rv8803: factor out existing register initialization to function
commit: 924e4892b167eb8adbcb2399d2b26f7667ff266d
[2/5] rtc: rv8803: initialize registers on post-probe voltage loss
commit: 7f1a1106537217edbdc68781e95b356df8463559
[3/5] rtc: rv8803: re-initialize all Epson RX8803 registers on voltage loss
commit: 084dc7c0072a7f93a947824d2b69883ed66a657f
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 9+ messages in thread