最近發現 , 我的 system 會無緣無故 wake up 起來 , 經過詳細比對 , 發現 ......
是 RTC (IRQ 51) 叫它醒來的...
找了一下 RTC 的 Driver , 發現 suspend / resume 有些小邏輯錯誤.
如果有設定 Alarm IRQ , 才需要將這個 IRQ 設定為 wake up source IRQ .
如果沒有設定, 那就不用理會 是否為 wake up source .
這樣確保 不會無緣無故由 RTC wake up 起來 .
Patch file 內容如下:
Index: drivers/rtc/rtc-snvs.c
===================================================================
--- drivers/rtc/rtc-snvs.c (revision 51)
+++ drivers/rtc/rtc-snvs.c (working copy)
@@ -400,13 +400,18 @@
else
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
- if (lp_cr & SNVS_LPCR_ALL_INT_EN) {
- if (!pdata->irq_enable) {
+ if (lp_cr & SNVS_LPCR_ALL_INT_EN)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
- } else {
- if (pdata->irq_enable) {
+ }
+ else
+ {
+ if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -449,8 +454,10 @@
spin_lock_irqsave(&rtc_lock, lock_flags);
- if (enable) {
- if (!pdata->irq_enable) {
+ if (enable)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
@@ -457,7 +464,9 @@
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
__raw_writel(lp_cr, ioaddr + SNVS_LPCR);
- } else {
+ }
+ else
+ {
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
if (((lp_cr & SNVS_LPCR_ALL_INT_EN) == 0)
@@ -491,7 +500,8 @@
u64 time_47bit;
int retVal;
- switch (cmd) {
+ switch (cmd)
+ {
case RTC_READ_TIME_47BIT:
time_47bit = (((u64) (__raw_readl(ioaddr + SNVS_LPSRTCMR) &
((0x1 << CNTR_TO_SECS_SH) - 1)) << 32) |
@@ -586,12 +596,16 @@
__raw_writel(0xFFFFFFFF, ioaddr + SNVS_LPSR);
udelay(100);
- if (pdata->irq >= 0) {
+ if (pdata->irq >= 0)
+ {
if (request_irq(pdata->irq, snvs_rtc_interrupt, IRQF_SHARED,
- pdev->name, pdev) < 0) {
+ pdev->name, pdev) < 0)
+ {
dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = -1;
- } else {
+ }
+ else
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -599,7 +613,8 @@
rtc = rtc_device_register(pdev->name, &pdev->dev,
&snvs_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
+ if (IS_ERR(rtc))
+ {
ret = PTR_ERR(rtc);
goto err_out;
}
@@ -652,13 +667,19 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
- enable_irq_wake(pdata->irq);
- } else {
+ DEBUG_MSG(">>>>");
+
+//==== Disable irq.
if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(pdata->irq);
}
+ DEBUG_MSG("<<<<");
+
return 0;
}
@@ -675,13 +696,17 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
+ DEBUG_MSG(">>>>");
+
+ if (pdata->irq_enable)
+ {
+ if (device_may_wakeup(&pdev->dev))
disable_irq_wake(pdata->irq);
- } else {
- if (pdata->irq_enable)
+
enable_irq(pdata->irq);
}
+ DEBUG_MSG("<<<<");
return 0;
}
@@ -689,7 +714,8 @@
* Contains pointers to the power management callback functions.
*/
static struct platform_driver snvs_rtc_driver = {
- .driver = {
+ .driver =
+ {
.name = "snvs_rtc",
},
.probe = snvs_rtc_probe,
沒有留言:
張貼留言