From 010b506d6b215673f188ed5cdc4e35419e3ea715 Mon Sep 17 00:00:00 2001 From: Einar Vading Date: Fri, 14 Aug 2020 22:14:41 +0200 Subject: [PATCH] rtc: rv3028: Refresh RAM on EEPROM write The active RV3028 settings are in RAM so after modifying the settings in EEPROM the RAM should be refreshed so that they take effect. Signed-off-by: Einar Vading --- drivers/rtc/rtc-rv3028.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -66,6 +66,7 @@ #define RV3028_EVT_CTRL_TSR BIT(2) +#define RV3028_EEPROM_CMD_REFRESH 0x12 #define RV3028_EEPROM_CMD_WRITE 0x21 #define RV3028_EEPROM_CMD_READ 0x22 @@ -583,6 +584,58 @@ restore_eerd: return ret; } +static int rv3028_ram_refresh(void *priv) +{ + u32 status, ctrl1; + int ret, err; + + ret = regmap_read(priv, RV3028_CTRL1, &ctrl1); + if (ret) + return ret; + + if (!(ctrl1 & RV3028_CTRL1_EERD)) { + ret = regmap_update_bits(priv, RV3028_CTRL1, + RV3028_CTRL1_EERD, RV3028_CTRL1_EERD); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status, + !(status & RV3028_STATUS_EEBUSY), + RV3028_EEBUSY_POLL, + RV3028_EEBUSY_TIMEOUT); + if (ret) + goto restore_eerd; + } + + ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0); + if (ret) + goto restore_eerd; + + ret = regmap_write(priv, RV3028_EEPROM_CMD, + RV3028_EEPROM_CMD_REFRESH); + if (ret) + goto restore_eerd; + + usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT); + + ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status, + !(status & RV3028_STATUS_EEBUSY), + RV3028_EEBUSY_POLL, + RV3028_EEBUSY_TIMEOUT); + if (ret) + goto restore_eerd; + +restore_eerd: + if (!(ctrl1 & RV3028_CTRL1_EERD)) { + err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD, + 0); + if (err && !ret) + ret = err; + } + + return ret; +} + static struct rtc_class_ops rv3028_rtc_ops = { .read_time = rv3028_get_time, .set_time = rv3028_set_time, @@ -723,6 +776,9 @@ static int rv3028_probe(struct i2c_clien ret = rv3028_eeprom_write( (void *)(rv3028->regmap), RV3028_BACKUP, (void *)&backup, 1); + + if (!ret) + ret = rv3028_ram_refresh((void *)(rv3028->regmap)); } }