rtc: pm8xxx: Fix issue in RTC write path
[ Upstream commit 83220bf38b77a830f8e62ab1a0d0408304f9b966 ] 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> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d131045273
commit
b0a7e39e8a
@ -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…
x
Reference in New Issue
Block a user