Will iMX6 SNVS_LP alarm enabled wake up PMIC to turn on even in power down state?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Will iMX6 SNVS_LP alarm enabled wake up PMIC to turn on even in power down state?

4,210 Views
raymondwang
Senior Contributor I

Dear All,

    my board design is based on SabreSD . There is a strange issue that board will auto turn on automatically even whole system is turned off (battery always mount).

I have double check the snvs_lp part which is alarm source to generate wake up to linux/android kernel.

   My kernel is 3.0.35, android release is android_jb_4.2.2_1.1.0. Does anyone ever encounter issue like that?

Labels (4)
0 Kudos
26 Replies

1,961 Views
PeterChan
NXP Employee
NXP Employee

The answer is "Yes" if the alarm in the SNVS_LP domain is enabled. You need to clear the LPTA_EN bit at SNVS_LPCR to disable the alarm. Please refer to "Figure 57-4. SNVS_LP secure real time counter" and "Figure 60-2. Chip reset scheme under external PMIC control" in reference manual for the detail.

1,961 Views
SKWoon
NXP Employee
NXP Employee

Hi Peter PeterChan

My customer (JiHua Zhao jh.zhao belongs to the same customer) is trying your suggestion to clear the LPTA_EN bit at SNVS_LPCR to disable the alarm, but he reported it is not working yet. He is not sure whether the value is over written again when  the unit goes to sleep mode & is currently trying to debug it.  If you (or any of your colleague) knows the exact place to disable the bit in Andriod BSP, please let them know. Thanks.

0 Kudos

1,961 Views
PeterChan
NXP Employee
NXP Employee

You may add a shutdown function to the SNVS platform device driver as below to clear the LPTA_EN bit when power down the system. By the way, did your customer set any alarm for wake up? May I have the steps to reproduce this problem in Android?

diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c

index 41470e9..97db666 100644

--- a/drivers/rtc/rtc-snvs.c

+++ b/drivers/rtc/rtc-snvs.c

@@ -685,6 +685,21 @@ static int snvs_rtc_resume(struct platform_device *pdev)

        return 0;

}

+void snvs_rtc_shutdown(struct platform_device *pdev)

+{

+      struct rtc_drv_data *pdata = platform_get_drvdata(pdev);

+      void __iomem *ioaddr = pdata->ioaddr;

+      unsigned long lock_flags = 0;

+      u32 lp_cr;

+

+      spin_lock_irqsave(&rtc_lock, lock_flags);

+      lp_cr = __raw_readl(ioaddr + SNVS_LPCR);

+      lp_cr &= ~SNVS_LPCR_LPTA_EN;

+      __raw_writel(lp_cr, ioaddr + SNVS_LPCR);

+      rtc_write_sync_lp(ioaddr);

+      spin_unlock_irqrestore(&rtc_lock, lock_flags);

+}

+

/*!

  * Contains pointers to the power management callback functions.

  */

@@ -696,6 +711,7 @@ static struct platform_driver snvs_rtc_driver = {

        .remove = __exit_p(snvs_rtc_remove),

        .suspend = snvs_rtc_suspend,

        .resume = snvs_rtc_resume,

+      .shutdown = snvs_rtc_shutdown,

};

0 Kudos

1,961 Views
PKZ
Contributor III

Hi Peter Chan,

I tried adding the "snvs_rtc_shutdown" function it works when the device is shutdown through android, i.e. the power button is press & hold -> shutdown dialog appears on the screen -> shutdown was confirmed -> the unit is shutdown.

But when I tried to shutdown by long pressing of power button (without acknowledging the shutdown dialog on the screen), the issue is still triggered since "snvs_rtc_shutdown" is not executed in such case.

When i disabled it in initialization (in 'snvs_rtc_probe' and I didn't enable it in 'snvs_rtc_alarm_irq_enable' (I changed the code to disable regardless of the value passed to it), the issue did not occur. I also noticed that the alarm setting did not change when the unit went to sleep mode and woke up. The 'alarm_IRQ' was always showing 'no' (disabled). For example, i disconnected the battery and all power source to reset the RTC. When the unit was powered on, it was showing  as below.

root@pp_rt7_6dq:/ # cat /proc/driver/rtc

rtc_time        : 08:17:35

rtc_date        : 2014-10-21

alrm_time       : 00:00:00

alrm_date       : 1970-01-01

alarm_IRQ       : no

alrm_pending    : no

update IRQ enabled      : no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

alarm_IRQ       : no

The 'rtc_time' and 'rtc_date' were sync with network  time as WiFi was enabled but the 'alrm_time' and 'alrm_date' did not change even after the sleep & wake up of several times for several min.

I have not tested thoroughly yet and wondering if there will be any impact on system level the alarm is disabled permanently.

Regards,

Paramod

0 Kudos

1,961 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

The Android framework always interacts with the kernel device "/dev/alarm" for all alarm operations. The alarm device driver source code can be found at kernel_imx/drivers/rtc/alarm.c. The alarm update function rtc_set_alarm() is only called when the driver enters suspend. Thus the SNVS alarm is only updated when the system enters suspend. For the rest of time, SNVS alarm is not used. So, I think it is safe to clear LPTA_EN at kernel init and shutdown.

Regards,

Peter

0 Kudos

1,961 Views
PKZ
Contributor III

Hi Peter Chan,

If I disable the alarm (clear LPTA_EN) only in init and shutdown, the issue is still triggerred if I do hard shutdown (by long pressing the power button) unless the alarm is disabled even when the unit goes to suspend (sleep) mode as mentioned in my previous post. But if the alarm is disabled all the time, it will not comply the Android system.

Regards,

Paramod

0 Kudos

1,961 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

If the SNVS_LPCR_LPTA_EN is clear in snvs_rtc_resume() and snvs_rtc_shutdown() such that SNVS alarm is only enable when suspend, will you see any side effect in Android?

Thanks,

Peter

0 Kudos

1,961 Views
PKZ
Contributor III

Hi Peter Chan,

In fact, the alarm is supposed to be disabled when the system resumes. I see the codes in alarm_resume() that the alarm is being disabled. I tried adding the print message in both alarm_resume() and snvs_rtc_resume() but non of the messages i see in the log. It seems that they are not being executed. May be that is the reason the alarm_IRQ is enabled all the time.

  alarm.enabled = 0;

  printk("alarm_resume: setting alarm, enabled = %d\n", alarm.enabled);

  rtc_set_alarm(alarm_rtc_dev, &alarm);

However, there is still a chance that the alarm can trigger the self power on if the device is shutdown by long pressing the power button which by-passes all the shutdown process/codes. I cannot think of any work around for this. But lets focus on the issue of "the alarm not being  disabled when the system resumes", first.

Regards,

Paramod

0 Kudos

1,961 Views
PeterChan
NXP Employee
NXP Employee

Taking a look into the rtc_set_alarm() function, you will see that it will not disable the alarm when alarm->enabled=0. Thus the LPTA_EN bit is left ON.

A dirty workaround to handle the long power button press shutdown case is to force rtc_set_alarm() to disable alarm when alarm->enabled=0.

0 Kudos

1,961 Views
PKZ
Contributor III

Hi Peter Chan,

Thanks for the reply. The problem is that it seems "alarm_resume()" is not being executed as I don't see my debug message in alarm_resume() whenever the unit resumes. I can see my messages in alarm_suspend(). So, even I change the code, it may not be executed. I will try and let you know though. On your side, will you be able to add some print message in alarm_resume() and see it is being executed?

Regards,

Paramod

0 Kudos

1,963 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

Yes, I can see my debug message in alarm_resume(). You need to add "no_console_suspend" to kernel command line to enable debug console when suspend/resume.

The previous workaround to disable alarm when resume does not work and here is the revised one. Now, the LPTA_EN bit is always clear when resume.

Best Regards,

Peter

0 Kudos

1,963 Views
PKZ
Contributor III

Hi Peter,

I can see the message from alarm_resume() now.

I applied the patch and the alarm seems to disabled all the time even in suspend mode. (alarm_IRQ is 'no' all the time). Also attached the log from one of the unit (#unit 1)

Another strange thing i noticed is that after unit is erased and program with new images, when the unit goes to sleep, the alarm time is being set to year 2036 (please see the log msg below for details). It does not change on subsequent sleep/resume.

And this is consistent across 3 boards I tested.

#unit 1

root@pp_rt7_6dq:/ # cat /proc/driver/rtc                                    

rtc-snvs: snvs_rtc_proc

rtc_time        : 00:02:04

rtc_date        : 1970-01-02

alrm_time      : 06:28:16

alrm_date      : 2036-02-06

alarm_IRQ      : no

alrm_pending    : no

update IRQ enabled      : no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

alarm_IRQ      : no

#unit 2

C:\Program Files (x86)\Android\android-studio\sdk\platform-tools>adb shell

shell@pp_rt7_6dq:/ $ cat /proc/dr      r

shell@pp_rt7_6dq:/ $ cat /proc/driver/rtc

rtc_time        : 02:01:55

rtc_date        : 2014-10-24

alrm_time      : 06:28:16

alrm_date      : 2036-02-06

alarm_IRQ      : no

alrm_pending    : no

update IRQ enabled      : no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

alarm_IRQ      : no

#unit 3

C:\Program Files (x86)\Android\android-studio\sdk\platform-tools>adb shell

shell@pp_rt7_6dq:/ $

shell@pp_rt7_6dq:/ $

shell@pp_rt7_6dq:/ $

shell@pp_rt7_6dq:/ $ cat /proc/driver/rtc

cat /proc/driver/rtc

rtc_time        : 00:46:22

rtc_date        : 1970-01-02

alrm_time      : 06:28:16

alrm_date      : 2036-02-06

alarm_IRQ      : no

alrm_pending    : no

update IRQ enabled      : no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

alarm_IRQ      : no

shell@pp_rt7_6dq:/ $ cat /proc/driver/rtc

cat /proc/driver/rtc

Regards,

Paramod

0 Kudos

1,963 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

I am sorry, it is my bug again. It should not update the rtc->aie_timer for disable alarm since its time is invalid. Here is the updated patch.

Apart from the weird alarm description at "/proc/drvier/rtc", do you observe other problems after the patch?


Regards,

Peter

0 Kudos

1,963 Views
PKZ
Contributor III

Hi Peter,

With previous patch (android_disable_alarm_at_resume.patch.zip), alarm_IRQ was always disabled!

With new patch (android_disable_alarm_at_resume_20141024_1.patch.zip), one alarm_IRQ show alarm is enabled all the time and the other one shows, disabled all the time.

root@pp_rt7_6dq:/ # cat /proc/driver/rtc                                      

rtc-snvs: snvs_rtc_proc

rtc_time        : 05:13:46

rtc_date        : 1970-01-02

alrm_time       : 06:23:35

alrm_date       : 1970-01-02

alarm_IRQ       : yes

alrm_pending    : no

update IRQ enabled      : no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

alarm_IRQ       : no

After tracing the source, the first one is reading 'rtc->aie_timer.enabled' in rtc_read_alarm() called by rtc_proc_show() as below. the second one is the actual register bit reflection from snvs_rtc_proc(). I thought, when the device is in sleep mode, the bit should be enabled (so alarm_IRQ: yes) and when the device wakes up, it should be disabled (alarm_IRQ; no).

Another thing I am wondering about is that how/who does the alarm time changes, is it the driver chages that value or is it the RTC has some issue and the time gets changed?

static int rtc_proc_show(struct seq_file *seq, void *offset)

{

.

.

.

err = rtc_read_alarm(rtc, &alrm);

  if (err == 0) {

  seq_printf(seq, "alrm_time\t: ");

  if ((unsigned int)alrm.time.tm_hour <= 24)

  seq_printf(seq, "%02d:", alrm.time.tm_hour);

  else

  seq_printf(seq, "**:");

  if ((unsigned int)alrm.time.tm_min <= 59)

  seq_printf(seq, "%02d:", alrm.time.tm_min);

  else

  seq_printf(seq, "**:");

  if ((unsigned int)alrm.time.tm_sec <= 59)

  seq_printf(seq, "%02d\n", alrm.time.tm_sec);

  else

  seq_printf(seq, "**\n");

  seq_printf(seq, "alrm_date\t: ");

  if ((unsigned int)alrm.time.tm_year <= 200)

  seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);

  else

  seq_printf(seq, "****-");

  if ((unsigned int)alrm.time.tm_mon <= 11)

  seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);

  else

  seq_printf(seq, "**-");

  if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31)

  seq_printf(seq, "%02d\n", alrm.time.tm_mday);

  else

  seq_printf(seq, "**\n");

seq_printf(seq, "alarm_IRQ\t: %s\n",

  alrm.enabled ? "yes" : "no");

  seq_printf(seq, "alrm_pending\t: %s\n",

  alrm.pending ? "yes" : "no");

  seq_printf(seq, "update IRQ enabled\t: %s\n",

  (rtc->uie_rtctimer.enabled) ? "yes" : "no");

  seq_printf(seq, "periodic IRQ enabled\t: %s\n",

  (rtc->pie_enabled) ? "yes" : "no");

  seq_printf(seq, "periodic IRQ frequency\t: %d\n",

  rtc->irq_freq);

  seq_printf(seq, "max user IRQ frequency\t: %d\n",

  rtc->max_user_freq);

  }

  seq_printf(seq, "24hr\t\t: yes\n");

  if (ops->proc)

ops->proc(rtc->dev.parent, seq);

}

Regards,

Paramod

0 Kudos

1,963 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

I am sorry for my late response.

Yes, when this change, the SNVS_LP alarm is only enable when the device is in sleep mode. When the device is active, SNVS_LP alarm is disable and "cat /proc/driver/rtc" shows "alarm_IRQ:  no".


The alarm time is updated in alarm_suspend() when the device entering sleep mode. The function reads the ANDROID_ALARM_RTC_WAKEUP/ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP alarm queues and set the alarm when needs.

Regards,

Peter

0 Kudos

1,963 Views
PKZ
Contributor III

Hi Peter,

You have mentioned as below (and I was expecting the same) but the results are different!

"Yes, when this change, the SNVS_LP alarm is only enable when the device is in sleep mode. When the device is active, SNVS_LP alarm is disable and "cat /proc/driver/rtc" shows "alarm_IRQ:  no"."


But the results are as below:

one "alarm_IRQ" show alarm is enabled all the time and the other one shows, disabled all the time. No change during suspend/wake up state, always the same status. Not as expected, the alarm should be disable when it is running and enabled in sleep mode.

Regards,

Paramod

0 Kudos

1,962 Views
PeterChan
NXP Employee
NXP Employee

Hi Paramod,

=> "one "alarm_IRQ" show alarm is enabled all the time and the other one shows, disabled all the time."

I am sorry that this bug is caused by the rtc->aie_timer didn't get update when we disable an alarm. Please discard all my previous changes and use the attached patch.

Thanks,

Peter


0 Kudos

1,962 Views
PKZ
Contributor III

Hi Peter,

With the latest patch, both alarm_IRQ show disabled on my device (alarm_IRQ       : no) all the time. What do you get on your Sabre board?

Suspend mode --> alarm_IRQ       : no

Normal mode --> alarm_IRQ       : no

I am not sure if this will have any impact on android system.

Regards,

Paramod.

0 Kudos

1,962 Views
PeterChan
NXP Employee
NXP Employee

I got the same output.

The following code appears In alarm_resume()


    memset(&alarm, 0, sizeof(alarm));

    alarm.enabled = 0;

    rtc_set_alarm(alarm_rtc_dev, &alarm);

and I presume the kernel wants to disable this alarm when resume.

When suspend, alarm_suspend() will enable the alarm with the nearest wake up time in its queue.

0 Kudos

1,960 Views
kyke
Contributor I

Are you using a watchdog? Check if the imx2_wdt.c to see the watchdog is built-it in and enable. I had the same problem running Android in one board based on the IMX6 board, after shutdown it always reset and turn on again. The problem was the watchdog was enable on init but it wasn't stop on the shutdown.

Maybe it's not the problem you have, since I hadn't take a look to your board. But your problems seems very similar to the one I had. If so, just add a call to imx2_wdt_stop() on the imx2_wdt_shutdown method, or disable from start setting 0 the enable bit. From the comments on the driver, it can't be disable once is enable, so don't try to disable on shutdown... it will not work.

Path to driver: kernel_root_folder/drivers/watchdog/imx2_wdt.c

I hope I had been useful, sorry If it's not the same problem.

regards,

Enrique.

0 Kudos