Commit 6406d96e authored by Steve Twiss's avatar Steve Twiss Committed by Alexandre Belloni

rtc: da9053: fix access ordering error during RTC interrupt at system power on

This fix alters the ordering of the IRQ and device registrations in the RTC
driver probe function. This change will apply to the RTC driver that supports
both DA9052 and DA9053 PMICs.

A problem could occur with the existing RTC driver if:

A system is started from a cold boot using the PMIC RTC IRQ to initiate a
power on operation. For instance, if an RTC alarm is used to start a
platform from power off.
The existing driver IRQ is requested before the device has been properly
registered.

i.e.
ret = da9052_request_irq()
comes before
rtc->rtc = devm_rtc_device_register();

In this case, an interrupt exists before the device has been registered and
the IRQ handler can be called immediately: this can happen be before the
memory for rtc->rtc has been allocated. The IRQ handler da9052_rtc_irq()
contains the function call:

rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);

which in turn tries to access the unavailable rtc->rtc.

The fix is to reorder the functions inside the RTC probe. The IRQ is
requested after the RTC device resource has been registered so that
da9052_request_irq() is the last thing to happen.
Signed-off-by: default avatarSteve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent 5919fb97
...@@ -302,6 +302,13 @@ static int da9052_rtc_probe(struct platform_device *pdev) ...@@ -302,6 +302,13 @@ static int da9052_rtc_probe(struct platform_device *pdev)
if (ret != 0) if (ret != 0)
rtc_err(rtc, "Failed to disable TICKS: %d\n", ret); rtc_err(rtc, "Failed to disable TICKS: %d\n", ret);
device_init_wakeup(&pdev->dev, true);
rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&da9052_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc))
return PTR_ERR(rtc->rtc);
ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
da9052_rtc_irq, rtc); da9052_rtc_irq, rtc);
if (ret != 0) { if (ret != 0) {
...@@ -309,11 +316,7 @@ static int da9052_rtc_probe(struct platform_device *pdev) ...@@ -309,11 +316,7 @@ static int da9052_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
device_init_wakeup(&pdev->dev, true); return 0;
rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&da9052_rtc_ops, THIS_MODULE);
return PTR_ERR_OR_ZERO(rtc->rtc);
} }
static struct platform_driver da9052_rtc_driver = { static struct platform_driver da9052_rtc_driver = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment