2022-10-07 17:01:19

by Sean Anderson

[permalink] [raw]
Subject: [PATCH] rtc: abx80x: Don't warn about oscillator failure after PoR

According to the datasheet, the "oscillator failure" bit is set

> ...on a power on reset, when both the system and battery voltages have
> dropped below acceptable levels. It is also set if an Oscillator Failure
> occurs....

From testing, this bit is also set if a software reset is initiated.

This bit has a confusing name; it really tells us whether the time data
is valid. We clear it when writing the time. If it is still set, that
means there is a persistent issue (such as an oscillator failure),
instead of a transient one (such as power loss).

Because there are several other reasons which might cause this bit
to be set (including booting for the first time or a battery failure),
do not warn about oscillator failures willy-nilly. This may cause system
integrators to waste time looking into the wrong line of investigation.

Signed-off-by: Sean Anderson <[email protected]>
---

drivers/rtc/rtc-abx80x.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 9b0138d07232..1eb752e4e39d 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -115,6 +115,7 @@ struct abx80x_priv {
struct rtc_device *rtc;
struct i2c_client *client;
struct watchdog_device wdog;
+ bool wrote_time;
};

static int abx80x_write_config_key(struct i2c_client *client, u8 key)
@@ -167,6 +168,7 @@ static int abx80x_enable_trickle_charger(struct i2c_client *client,
static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct abx80x_priv *priv = i2c_get_clientdata(client);
unsigned char buf[8];
int err, flags, rc_mode = 0;

@@ -181,7 +183,18 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
return flags;

if (flags & ABX8XX_OSS_OF) {
- dev_err(dev, "Oscillator failure, data is invalid.\n");
+ /*
+ * The OF bit can be set either because of a reset
+ * (PoR/Software reset) or because of an oscillator
+ * failure. Effectively, it indicates that the stored
+ * time is invalid. When we write the time, we clear
+ * this bit. If it stays set, then this indicates an
+ * oscillator failure.
+ */
+ if (priv->wrote_time)
+ dev_err(dev, "Oscillator failure\n");
+ else
+ dev_info(dev, "Time data invalid\n");
return -EINVAL;
}
}
@@ -207,6 +220,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct abx80x_priv *priv = i2c_get_clientdata(client);
unsigned char buf[8];
int err, flags;

@@ -240,6 +254,7 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
dev_err(&client->dev, "Unable to write oscillator status register\n");
return err;
}
+ priv->wrote_time = true;

return 0;
}
--
2.35.1.1320.gc452695387.dirty


2022-10-07 19:01:04

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH] rtc: abx80x: Don't warn about oscillator failure after PoR

Hi,

On 07/10/2022 12:37:12-0400, Sean Anderson wrote:
> According to the datasheet, the "oscillator failure" bit is set
>
> > ...on a power on reset, when both the system and battery voltages have
> > dropped below acceptable levels. It is also set if an Oscillator Failure
> > occurs....
>
> From testing, this bit is also set if a software reset is initiated.
>
> This bit has a confusing name; it really tells us whether the time data
> is valid. We clear it when writing the time. If it is still set, that
> means there is a persistent issue (such as an oscillator failure),
> instead of a transient one (such as power loss).
>
> Because there are several other reasons which might cause this bit
> to be set (including booting for the first time or a battery failure),
> do not warn about oscillator failures willy-nilly. This may cause system
> integrators to waste time looking into the wrong line of investigation.
>
> Signed-off-by: Sean Anderson <[email protected]>
> ---
>
> drivers/rtc/rtc-abx80x.c | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
> index 9b0138d07232..1eb752e4e39d 100644
> --- a/drivers/rtc/rtc-abx80x.c
> +++ b/drivers/rtc/rtc-abx80x.c
> @@ -115,6 +115,7 @@ struct abx80x_priv {
> struct rtc_device *rtc;
> struct i2c_client *client;
> struct watchdog_device wdog;
> + bool wrote_time;
> };
>
> static int abx80x_write_config_key(struct i2c_client *client, u8 key)
> @@ -167,6 +168,7 @@ static int abx80x_enable_trickle_charger(struct i2c_client *client,
> static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> {
> struct i2c_client *client = to_i2c_client(dev);
> + struct abx80x_priv *priv = i2c_get_clientdata(client);
> unsigned char buf[8];
> int err, flags, rc_mode = 0;
>
> @@ -181,7 +183,18 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> return flags;
>
> if (flags & ABX8XX_OSS_OF) {
> - dev_err(dev, "Oscillator failure, data is invalid.\n");

Simply remove the line.

> + /*
> + * The OF bit can be set either because of a reset
> + * (PoR/Software reset) or because of an oscillator
> + * failure. Effectively, it indicates that the stored
> + * time is invalid. When we write the time, we clear
> + * this bit. If it stays set, then this indicates an
> + * oscillator failure.
> + */
> + if (priv->wrote_time)
> + dev_err(dev, "Oscillator failure\n");
> + else
> + dev_info(dev, "Time data invalid\n");
> return -EINVAL;
> }
> }
> @@ -207,6 +220,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
> {
> struct i2c_client *client = to_i2c_client(dev);
> + struct abx80x_priv *priv = i2c_get_clientdata(client);
> unsigned char buf[8];
> int err, flags;
>
> @@ -240,6 +254,7 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
> dev_err(&client->dev, "Unable to write oscillator status register\n");
> return err;
> }
> + priv->wrote_time = true;
>
> return 0;
> }
> --
> 2.35.1.1320.gc452695387.dirty
>

--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2022-10-07 19:29:48

by Sean Anderson

[permalink] [raw]
Subject: Re: [PATCH] rtc: abx80x: Don't warn about oscillator failure after PoR



On 10/7/22 2:57 PM, Alexandre Belloni wrote:
> Hi,
>
> On 07/10/2022 12:37:12-0400, Sean Anderson wrote:
>> According to the datasheet, the "oscillator failure" bit is set
>>
>> > ...on a power on reset, when both the system and battery voltages have
>> > dropped below acceptable levels. It is also set if an Oscillator Failure
>> > occurs....
>>
>> From testing, this bit is also set if a software reset is initiated.
>>
>> This bit has a confusing name; it really tells us whether the time data
>> is valid. We clear it when writing the time. If it is still set, that
>> means there is a persistent issue (such as an oscillator failure),
>> instead of a transient one (such as power loss).
>>
>> Because there are several other reasons which might cause this bit
>> to be set (including booting for the first time or a battery failure),
>> do not warn about oscillator failures willy-nilly. This may cause system
>> integrators to waste time looking into the wrong line of investigation.
>>
>> Signed-off-by: Sean Anderson <[email protected]>
>> ---
>>
>> drivers/rtc/rtc-abx80x.c | 17 ++++++++++++++++-
>> 1 file changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
>> index 9b0138d07232..1eb752e4e39d 100644
>> --- a/drivers/rtc/rtc-abx80x.c
>> +++ b/drivers/rtc/rtc-abx80x.c
>> @@ -115,6 +115,7 @@ struct abx80x_priv {
>> struct rtc_device *rtc;
>> struct i2c_client *client;
>> struct watchdog_device wdog;
>> + bool wrote_time;
>> };
>>
>> static int abx80x_write_config_key(struct i2c_client *client, u8 key)
>> @@ -167,6 +168,7 @@ static int abx80x_enable_trickle_charger(struct i2c_client *client,
>> static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>> {
>> struct i2c_client *client = to_i2c_client(dev);
>> + struct abx80x_priv *priv = i2c_get_clientdata(client);
>> unsigned char buf[8];
>> int err, flags, rc_mode = 0;
>>
>> @@ -181,7 +183,18 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>> return flags;
>>
>> if (flags & ABX8XX_OSS_OF) {
>> - dev_err(dev, "Oscillator failure, data is invalid.\n");
>
> Simply remove the line.

I think it's important to warn the user if the oscillator actually fails
so they can e.g. replace the crystal. Additionally, this can help debug
failed batteries, since you will see "Time data invalid" in the boot log.

--Sean

>> + /*
>> + * The OF bit can be set either because of a reset
>> + * (PoR/Software reset) or because of an oscillator
>> + * failure. Effectively, it indicates that the stored
>> + * time is invalid. When we write the time, we clear
>> + * this bit. If it stays set, then this indicates an
>> + * oscillator failure.
>> + */
>> + if (priv->wrote_time)
>> + dev_err(dev, "Oscillator failure\n");
>> + else
>> + dev_info(dev, "Time data invalid\n");
>> return -EINVAL;
>> }
>> }
>> @@ -207,6 +220,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>> static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
>> {
>> struct i2c_client *client = to_i2c_client(dev);
>> + struct abx80x_priv *priv = i2c_get_clientdata(client);
>> unsigned char buf[8];
>> int err, flags;
>>
>> @@ -240,6 +254,7 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
>> dev_err(&client->dev, "Unable to write oscillator status register\n");
>> return err;
>> }
>> + priv->wrote_time = true;
>>
>> return 0;
>> }
>> --
>> 2.35.1.1320.gc452695387.dirty
>>
>

2022-10-26 21:34:39

by Sean Anderson

[permalink] [raw]
Subject: Re: [PATCH] rtc: abx80x: Don't warn about oscillator failure after PoR

Hi Alexandre,

On 10/7/22 15:05, Sean Anderson wrote:
>
>
> On 10/7/22 2:57 PM, Alexandre Belloni wrote:
>> Hi,
>>
>> On 07/10/2022 12:37:12-0400, Sean Anderson wrote:
>>> According to the datasheet, the "oscillator failure" bit is set
>>>
>>> > ...on a power on reset, when both the system and battery voltages have
>>> > dropped below acceptable levels. It is also set if an Oscillator Failure
>>> > occurs....
>>>
>>> From testing, this bit is also set if a software reset is initiated.
>>>
>>> This bit has a confusing name; it really tells us whether the time data
>>> is valid. We clear it when writing the time. If it is still set, that
>>> means there is a persistent issue (such as an oscillator failure),
>>> instead of a transient one (such as power loss).
>>>
>>> Because there are several other reasons which might cause this bit
>>> to be set (including booting for the first time or a battery failure),
>>> do not warn about oscillator failures willy-nilly. This may cause system
>>> integrators to waste time looking into the wrong line of investigation.
>>>
>>> Signed-off-by: Sean Anderson <[email protected]>
>>> ---
>>>
>>> drivers/rtc/rtc-abx80x.c | 17 ++++++++++++++++-
>>> 1 file changed, 16 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
>>> index 9b0138d07232..1eb752e4e39d 100644
>>> --- a/drivers/rtc/rtc-abx80x.c
>>> +++ b/drivers/rtc/rtc-abx80x.c
>>> @@ -115,6 +115,7 @@ struct abx80x_priv {
>>> struct rtc_device *rtc;
>>> struct i2c_client *client;
>>> struct watchdog_device wdog;
>>> + bool wrote_time;
>>> };
>>>
>>> static int abx80x_write_config_key(struct i2c_client *client, u8 key)
>>> @@ -167,6 +168,7 @@ static int abx80x_enable_trickle_charger(struct i2c_client *client,
>>> static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>>> {
>>> struct i2c_client *client = to_i2c_client(dev);
>>> + struct abx80x_priv *priv = i2c_get_clientdata(client);
>>> unsigned char buf[8];
>>> int err, flags, rc_mode = 0;
>>>
>>> @@ -181,7 +183,18 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>>> return flags;
>>>
>>> if (flags & ABX8XX_OSS_OF) {
>>> - dev_err(dev, "Oscillator failure, data is invalid.\n");
>>
>> Simply remove the line.
>
> I think it's important to warn the user if the oscillator actually fails
> so they can e.g. replace the crystal. Additionally, this can help debug
> failed batteries, since you will see "Time data invalid" in the boot log.

Have you considered my reply?

I'd also like to note that

drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-pcf*.c
drivers/rtc/rtc-rs5c*.c
drivers/rtc/rtc-sc27xx.c

all produce some kind of message if they detect a power loss or oscillator failure.

--Sean


>>> + /*
>>> + * The OF bit can be set either because of a reset
>>> + * (PoR/Software reset) or because of an oscillator
>>> + * failure. Effectively, it indicates that the stored
>>> + * time is invalid. When we write the time, we clear
>>> + * this bit. If it stays set, then this indicates an
>>> + * oscillator failure.
>>> + */
>>> + if (priv->wrote_time)
>>> + dev_err(dev, "Oscillator failure\n");
>>> + else
>>> + dev_info(dev, "Time data invalid\n");
>>> return -EINVAL;
>>> }
>>> }
>>> @@ -207,6 +220,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
>>> static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
>>> {
>>> struct i2c_client *client = to_i2c_client(dev);
>>> + struct abx80x_priv *priv = i2c_get_clientdata(client);
>>> unsigned char buf[8];
>>> int err, flags;
>>>
>>> @@ -240,6 +254,7 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
>>> dev_err(&client->dev, "Unable to write oscillator status register\n");
>>> return err;
>>> }
>>> + priv->wrote_time = true;
>>>
>>> return 0;
>>> }
>>> --
>>> 2.35.1.1320.gc452695387.dirty
>>>
>>