@@ -267,16 +267,19 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
int rc;
unsigned int ctrl_reg;
+ unsigned long irq_flags;
u8 value[NUM_8_BIT_RTC_REGS];
unsigned long secs;
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
+ spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+
rc = regmap_bulk_read(rtc_dd->regmap, regs->alarm_rw, value,
sizeof(value));
if (rc) {
dev_err(dev, "RTC alarm time read failed\n");
- return rc;
+ goto rtc_rw_fail;
}
secs = value[0] | (value[1] << 8) | (value[2] << 16) |
@@ -287,14 +290,30 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
if (rc) {
dev_err(dev, "Read from RTC alarm control register failed\n");
- return rc;
+ goto rtc_rw_fail;
+ }
+
+ if (ctrl_reg && (rtc_tm_to_ktime(alarm->time) >=
+ rtc_dd->rtc->aie_timer.node.expires)) {
+ ctrl_reg &= ~regs->alarm_en;
+ rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
+ if (rc) {
+ dev_err(dev, "Update RTC control register failed \n");
+ goto rtc_rw_fail;
+ }
}
alarm->enabled = !!(ctrl_reg & PM8xxx_RTC_ALARM_ENABLE);
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
dev_dbg(dev, "Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr\n",
&alarm->time, &alarm->time);
return 0;
+
+rtc_rw_fail:
+ spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+ return rc;
}
static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)