rtc: pm8xxx: Fix issue in RTC write path
In order to set time in rtc, need to disable rtc hw before writing into rtc registers. Also fixes disabling of alarm while setting rtc time. Signed-off-by: Mohit Aggarwal <maggarwa@codeaurora.org> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
parent
e22e2d941c
commit
83220bf38b
1 changed files with 39 additions and 12 deletions
|
@ -74,16 +74,18 @@ struct pm8xxx_rtc {
|
|||
/*
|
||||
* Steps to write the RTC registers.
|
||||
* 1. Disable alarm if enabled.
|
||||
* 2. Write 0x00 to LSB.
|
||||
* 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
|
||||
* 4. Enable alarm if disabled in step 1.
|
||||
* 2. Disable rtc if enabled.
|
||||
* 3. Write 0x00 to LSB.
|
||||
* 4. Write Byte[1], Byte[2], Byte[3] then Byte[0].
|
||||
* 5. Enable rtc if disabled in step 2.
|
||||
* 6. Enable alarm if disabled in step 1.
|
||||
*/
|
||||
static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
int rc, i;
|
||||
unsigned long secs, irq_flags;
|
||||
u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0;
|
||||
unsigned int ctrl_reg;
|
||||
u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0;
|
||||
unsigned int ctrl_reg, rtc_ctrl_reg;
|
||||
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
|
||||
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
|
||||
|
||||
|
@ -92,23 +94,38 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
|
||||
rtc_tm_to_time(tm, &secs);
|
||||
|
||||
dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
|
||||
|
||||
for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
|
||||
value[i] = secs & 0xFF;
|
||||
secs >>= 8;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
|
||||
|
||||
spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
|
||||
|
||||
rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg);
|
||||
rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
|
||||
if (rc)
|
||||
goto rtc_rw_fail;
|
||||
|
||||
if (ctrl_reg & regs->alarm_en) {
|
||||
alarm_enabled = 1;
|
||||
ctrl_reg &= ~regs->alarm_en;
|
||||
rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
|
||||
rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
|
||||
if (rc) {
|
||||
dev_err(dev, "Write to RTC Alarm control register failed\n");
|
||||
goto rtc_rw_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable RTC H/w before writing on RTC register */
|
||||
rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg);
|
||||
if (rc)
|
||||
goto rtc_rw_fail;
|
||||
|
||||
if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) {
|
||||
rtc_disabled = 1;
|
||||
rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE;
|
||||
rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
|
||||
if (rc) {
|
||||
dev_err(dev, "Write to RTC control register failed\n");
|
||||
goto rtc_rw_fail;
|
||||
|
@ -137,15 +154,25 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
goto rtc_rw_fail;
|
||||
}
|
||||
|
||||
if (alarm_enabled) {
|
||||
ctrl_reg |= regs->alarm_en;
|
||||
rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
|
||||
/* Enable RTC H/w after writing on RTC register */
|
||||
if (rtc_disabled) {
|
||||
rtc_ctrl_reg |= PM8xxx_RTC_ENABLE;
|
||||
rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
|
||||
if (rc) {
|
||||
dev_err(dev, "Write to RTC control register failed\n");
|
||||
goto rtc_rw_fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (alarm_enabled) {
|
||||
ctrl_reg |= regs->alarm_en;
|
||||
rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
|
||||
if (rc) {
|
||||
dev_err(dev, "Write to RTC Alarm control register failed\n");
|
||||
goto rtc_rw_fail;
|
||||
}
|
||||
}
|
||||
|
||||
rtc_rw_fail:
|
||||
spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
|
||||
|
||||
|
|
Loading…
Reference in a new issue