diff options
Diffstat (limited to 'drivers/rtc/rtc-sc27xx.c')
-rw-r--r-- | drivers/rtc/rtc-sc27xx.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index deea5c3726ad..b4eb3b3c6c2c 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -129,19 +129,6 @@ static int sprd_rtc_clear_alarm_ints(struct sprd_rtc *rtc) SPRD_RTC_ALM_INT_MASK); } -static int sprd_rtc_disable_ints(struct sprd_rtc *rtc) -{ - int ret; - - ret = regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN, - SPRD_RTC_INT_MASK, 0); - if (ret) - return ret; - - return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR, - SPRD_RTC_INT_MASK); -} - static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) { int ret; @@ -172,7 +159,8 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) return ret; } - return 0; + return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR, + SPRD_RTC_SPG_UPD_EN); } static int sprd_rtc_get_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type, @@ -427,10 +415,14 @@ static int sprd_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) u32 val; /* - * If aie_timer is enabled, we should get the normal alarm time. + * Before RTC device is registered, it will check to see if there is an + * alarm already set in RTC hardware, and we always read the normal + * alarm at this time. + * + * Or if aie_timer is enabled, we should get the normal alarm time. * Otherwise we should get auxiliary alarm time. */ - if (rtc->rtc && rtc->rtc->aie_timer.enabled == 0) + if (rtc->rtc && rtc->rtc->registered && rtc->rtc->aie_timer.enabled == 0) return sprd_rtc_read_aux_alarm(dev, alrm); ret = sprd_rtc_get_secs(rtc, SPRD_RTC_ALARM, &secs); @@ -575,6 +567,32 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc) return 0; } +static int sprd_rtc_check_alarm_int(struct sprd_rtc *rtc) +{ + u32 val; + int ret; + + ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val); + if (ret) + return ret; + + /* + * The SPRD_RTC_INT_EN register is not put in always-power-on region + * supplied by VDDRTC, so we should check if we need enable the alarm + * interrupt when system booting. + * + * If we have set SPRD_RTC_POWEROFF_ALM_FLAG which is saved in + * always-power-on region, that means we have set one alarm last time, + * so we should enable the alarm interrupt to help RTC core to see if + * there is an alarm already set in RTC hardware. + */ + if (!(val & SPRD_RTC_POWEROFF_ALM_FLAG)) + return 0; + + return regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN, + SPRD_RTC_ALARM_EN, SPRD_RTC_ALARM_EN); +} + static int sprd_rtc_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -608,10 +626,10 @@ static int sprd_rtc_probe(struct platform_device *pdev) rtc->dev = &pdev->dev; platform_set_drvdata(pdev, rtc); - /* clear all RTC interrupts and disable all RTC interrupts */ - ret = sprd_rtc_disable_ints(rtc); + /* check if we need set the alarm interrupt */ + ret = sprd_rtc_check_alarm_int(rtc); if (ret) { - dev_err(&pdev->dev, "failed to disable RTC interrupts\n"); + dev_err(&pdev->dev, "failed to check RTC alarm interrupt\n"); return ret; } @@ -631,16 +649,18 @@ static int sprd_rtc_probe(struct platform_device *pdev) return ret; } + device_init_wakeup(&pdev->dev, 1); + rtc->rtc->ops = &sprd_rtc_ops; rtc->rtc->range_min = 0; rtc->rtc->range_max = 5662310399LL; ret = rtc_register_device(rtc->rtc); if (ret) { dev_err(&pdev->dev, "failed to register rtc device\n"); + device_init_wakeup(&pdev->dev, 0); return ret; } - device_init_wakeup(&pdev->dev, 1); return 0; } |