| From 9c51cd614b147a69e4c9fbd175070a0b30a156e0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 11 Jun 2025 11:14:16 -0700 |
| Subject: rtc: ds1307: handle oscillator stop flag (OSF) for ds1341 |
| |
| From: Meagan Lloyd <meaganlloyd@linux.microsoft.com> |
| |
| [ Upstream commit 523923cfd5d622b8f4ba893fdaf29fa6adeb8c3e ] |
| |
| In using CONFIG_RTC_HCTOSYS, rtc_hctosys() will sync the RTC time to the |
| kernel time as long as rtc_read_time() succeeds. In some power loss |
| situations, our supercapacitor-backed DS1342 RTC comes up with either an |
| unpredictable future time or the default 01/01/00 from the datasheet. |
| The oscillator stop flag (OSF) is set in these scenarios due to the |
| power loss and can be used to determine the validity of the RTC data. |
| |
| This change expands the oscillator stop flag (OSF) handling that has |
| already been implemented for some chips to the ds1341 chip (DS1341 and |
| DS1342 share a datasheet). This handling manages the validity of the RTC |
| data in .read_time and .set_time based on the OSF. |
| |
| Signed-off-by: Meagan Lloyd <meaganlloyd@linux.microsoft.com> |
| Reviewed-by: Tyler Hicks <code@tyhicks.com> |
| Acked-by: Rodolfo Giometti <giometti@enneenne.com> |
| Link: https://lore.kernel.org/r/1749665656-30108-3-git-send-email-meaganlloyd@linux.microsoft.com |
| Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/rtc/rtc-ds1307.c | 11 +++++++++++ |
| 1 file changed, 11 insertions(+) |
| |
| diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c |
| index e14981383c01..ae115c3fcf19 100644 |
| --- a/drivers/rtc/rtc-ds1307.c |
| +++ b/drivers/rtc/rtc-ds1307.c |
| @@ -274,6 +274,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) |
| if (tmp & DS1340_BIT_OSF) |
| return -EINVAL; |
| break; |
| + case ds_1341: |
| + ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp); |
| + if (ret) |
| + return ret; |
| + if (tmp & DS1337_BIT_OSF) |
| + return -EINVAL; |
| + break; |
| case ds_1388: |
| ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp); |
| if (ret) |
| @@ -372,6 +379,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) |
| regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, |
| DS1340_BIT_OSF, 0); |
| break; |
| + case ds_1341: |
| + regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS, |
| + DS1337_BIT_OSF, 0); |
| + break; |
| case ds_1388: |
| regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG, |
| DS1388_BIT_OSF, 0); |
| -- |
| 2.39.5 |
| |