diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c index bbaf09cb09f..058bc47b857 100644 --- a/arch/arm/mach-msm/board-msm8960.c +++ b/arch/arm/mach-msm/board-msm8960.c @@ -3755,6 +3755,7 @@ static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata __devinitdata = { static struct pm8xxx_rtc_platform_data pm8xxx_rtc_pdata __devinitdata = { .rtc_write_enable = false, + .rtc_alarm_powerup = false, }; static struct pm8xxx_pwrkey_platform_data pm8xxx_pwrkey_pdata = { diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 0bdb89eb8b1..e53374ec5fb 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -30,6 +30,8 @@ /* RTC_CTRL register bit fields */ #define PM8xxx_RTC_ENABLE BIT(7) #define PM8xxx_RTC_ALARM_ENABLE BIT(1) +#define PM8xxx_RTC_ABORT_ENABLE BIT(0) + #define PM8xxx_RTC_ALARM_CLEAR BIT(0) #define NUM_8_BIT_RTC_REGS 0x4 @@ -461,6 +463,14 @@ static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) } } + /* Enable abort enable feature */ + ctrl_reg |= PM8xxx_RTC_ABORT_ENABLE; + rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); + if (rc < 0) { + dev_err(&pdev->dev, "PM8xxx write failed!\n"); + goto fail_rtc_enable; + } + rtc_dd->ctrl_reg = ctrl_reg; if (rtc_write_enable == true) pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time; @@ -539,9 +549,48 @@ static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) return 0; } +static void pm8xxx_rtc_shutdown(struct platform_device *pdev) +{ + u8 value[4] = {0, 0, 0, 0}; + u8 reg; + int rc; + unsigned long irq_flags; + bool rtc_alarm_powerup = false; + struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); + struct pm8xxx_rtc_platform_data *pdata = pdev->dev.platform_data; + + if (pdata != NULL) + rtc_alarm_powerup = pdata->rtc_alarm_powerup; + + if (!rtc_alarm_powerup) { + + spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); + dev_dbg(&pdev->dev, "Disabling alarm interrupts\n"); + + /* Disable RTC alarms */ + reg = rtc_dd->ctrl_reg; + reg &= ~PM8xxx_RTC_ALARM_ENABLE; + rc = pm8xxx_write_wrapper(rtc_dd, ®, rtc_dd->rtc_base, 1); + if (rc < 0) { + dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n"); + goto fail_alarm_disable; + } + + /* Clear Alarm register */ + rc = pm8xxx_write_wrapper(rtc_dd, value, + rtc_dd->alarm_rw_base, NUM_8_BIT_RTC_REGS); + if (rc < 0) + dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n"); + +fail_alarm_disable: + spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); + } +} + static struct platform_driver pm8xxx_rtc_driver = { .probe = pm8xxx_rtc_probe, .remove = __devexit_p(pm8xxx_rtc_remove), + .shutdown = pm8xxx_rtc_shutdown, .driver = { .name = PM8XXX_RTC_DEV_NAME, .owner = THIS_MODULE, diff --git a/include/linux/mfd/pm8xxx/rtc.h b/include/linux/mfd/pm8xxx/rtc.h index 14f1983eaec..bb3f98a54c1 100644 --- a/include/linux/mfd/pm8xxx/rtc.h +++ b/include/linux/mfd/pm8xxx/rtc.h @@ -20,6 +20,7 @@ */ struct pm8xxx_rtc_platform_data { bool rtc_write_enable; + bool rtc_alarm_powerup; }; #endif /* __RTC_PM8XXX_H__ */