mirror of
https://github.com/torvalds/linux.git
synced 2024-12-23 19:31:53 +00:00
rtc: rv3028: factorize EERD bit handling
Both rv3028_eeprom_write and rv3028_eeprom_read enable EERD before sending commands to the EEPROM and restore it afterwards. Factorize this code. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Link: https://lore.kernel.org/r/20201009153101.721149-3-alexandre.belloni@bootlin.com
This commit is contained in:
parent
c1efae1432
commit
de0ad60e79
@ -171,6 +171,44 @@ static const struct attribute_group rv3028_attr_group = {
|
||||
.attrs = rv3028_attrs,
|
||||
};
|
||||
|
||||
static int rv3028_exit_eerd(struct rv3028_data *rv3028, u32 eerd)
|
||||
{
|
||||
if (eerd)
|
||||
return 0;
|
||||
|
||||
return regmap_update_bits(rv3028->regmap, RV3028_CTRL1, RV3028_CTRL1_EERD, 0);
|
||||
}
|
||||
|
||||
static int rv3028_enter_eerd(struct rv3028_data *rv3028, u32 *eerd)
|
||||
{
|
||||
u32 ctrl1, status;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rv3028->regmap, RV3028_CTRL1, &ctrl1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*eerd = ctrl1 & RV3028_CTRL1_EERD;
|
||||
if (*eerd)
|
||||
return 0;
|
||||
|
||||
ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
|
||||
RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
|
||||
!(status & RV3028_STATUS_EEBUSY),
|
||||
RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
|
||||
if (ret) {
|
||||
rv3028_exit_eerd(rv3028, *eerd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct rv3028_data *rv3028 = dev_id;
|
||||
@ -451,49 +489,36 @@ static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
|
||||
static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
u32 status, ctrl1;
|
||||
int i, ret, err;
|
||||
struct rv3028_data *rv3028 = priv;
|
||||
u32 status, eerd;
|
||||
int i, ret;
|
||||
u8 *buf = val;
|
||||
|
||||
ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
|
||||
ret = rv3028_enter_eerd(rv3028, &eerd);
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_DATA, buf[i]);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_write(priv, RV3028_EEPROM_CMD,
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD,
|
||||
RV3028_EEPROM_CMD_WRITE);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
|
||||
|
||||
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
|
||||
ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
|
||||
!(status & RV3028_STATUS_EEBUSY),
|
||||
RV3028_EEBUSY_POLL,
|
||||
RV3028_EEBUSY_TIMEOUT);
|
||||
@ -502,13 +527,7 @@ static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
|
||||
}
|
||||
|
||||
restore_eerd:
|
||||
if (!(ctrl1 & RV3028_CTRL1_EERD))
|
||||
{
|
||||
err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
|
||||
0);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
}
|
||||
rv3028_exit_eerd(rv3028, eerd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -516,63 +535,44 @@ restore_eerd:
|
||||
static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
u32 status, ctrl1, data;
|
||||
int i, ret, err;
|
||||
struct rv3028_data *rv3028 = priv;
|
||||
u32 status, eerd, data;
|
||||
int i, ret;
|
||||
u8 *buf = val;
|
||||
|
||||
ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
|
||||
ret = rv3028_enter_eerd(rv3028, &eerd);
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_write(priv, RV3028_EEPROM_CMD,
|
||||
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD,
|
||||
RV3028_EEPROM_CMD_READ);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
|
||||
ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
|
||||
!(status & RV3028_STATUS_EEBUSY),
|
||||
RV3028_EEBUSY_POLL,
|
||||
RV3028_EEBUSY_TIMEOUT);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
|
||||
ret = regmap_read(priv, RV3028_EEPROM_DATA, &data);
|
||||
ret = regmap_read(rv3028->regmap, RV3028_EEPROM_DATA, &data);
|
||||
if (ret)
|
||||
goto restore_eerd;
|
||||
buf[i] = data;
|
||||
}
|
||||
|
||||
restore_eerd:
|
||||
if (!(ctrl1 & RV3028_CTRL1_EERD))
|
||||
{
|
||||
err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
|
||||
0);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
}
|
||||
rv3028_exit_eerd(rv3028, eerd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -834,7 +834,7 @@ static int rv3028_probe(struct i2c_client *client)
|
||||
|
||||
nvmem_cfg.priv = rv3028->regmap;
|
||||
rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
|
||||
eeprom_cfg.priv = rv3028->regmap;
|
||||
eeprom_cfg.priv = rv3028;
|
||||
rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
|
||||
|
||||
rv3028->rtc->max_user_freq = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user