linux-kernelarmlinux-device-driverembedded-linuxreal-time-clock

Linux RTC PCF85063A issue after suspend/resume


I am trying to use the PCF85063A RTC device on a Toradex Colibry i.MX7D processor.

Used Setup:

For this, I created an own DTS file. Here’s the relevant DTS change:

&i2c4 {
  status = "okay";

  /* PCF85063A real time clock on carrier board */
  pcf_rtc: pcf85063a@51 {
    compatible = "nxp,pcf85063a";
    reg = <0x51>;
    interrupt-parent = <&gpio1>;
    interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
    wakeup-source;
  };
};

I enabled the driver in the kernel configuration, recompiled the kernel and modules and deployed them.

CONFIG_RTC_DRV_PCF85063=y

The output of dmesg after booting the system is as follows, which looks good to me at first glance:

~$ dmesg | grep rtc
[    1.071396] rtc-pcf85063 3-0051: wake irq already initialized
[    1.293186] rtc rtc0: failed to enable irq wake
[    1.303787] rtc-pcf85063 3-0051: registered as rtc0
[    1.309405] snvs_rtc 30370000.snvs:snvs-rtc-lp: registered as rtc1
[    1.757462] rtc-pcf85063 3-0051: setting system clock to 2022-11-28T15:33:09 UTC (1669649589)

But one block within dmesg output makes me think that something is wrong initialized:

[    1.056406] ------------[ cut here ]------------                                                                                 
[    1.061047] WARNING: CPU: 0 PID: 1 at drivers/base/power/wakeirq.c:30 dev_pm_attach_wake_irq.constprop.0+0xd0/0xd4               
[    1.071396] rtc-pcf85063 3-0051: wake irq already initialized                                                                    
[    1.077140] Modules linked in:                                                                                                   
[    1.080203] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.4.161-5.6.0-devel+git.0f0011824921 #1                                    
[    1.088726] Hardware name: Freescale i.MX7 Dual (Device Tree)                                                                    
[    1.094495] [<8010eaf8>] (unwind_backtrace) from [<8010bb1c>] (show_stack+0x10/0x14)                                             
[    1.102248] [<8010bb1c>] (show_stack) from [<80914d84>] (dump_stack+0x90/0xa4)                                                   
[    1.109480] [<80914d84>] (dump_stack) from [<8090c38c>] (__warn+0xbc/0xd8)                                                       
[    1.116363] [<8090c38c>] (__warn) from [<8090c42c>] (warn_slowpath_fmt+0x84/0x98)                                                
[    1.123856] [<8090c42c>] (warn_slowpath_fmt) from [<8058b538>] (dev_pm_attach_wake_irq.constprop.0+0xd0/0xd4)                    
[    1.133780] [<8058b538>] (dev_pm_attach_wake_irq.constprop.0) from [<8058b688>] (dev_pm_set_wake_irq+0x40/0x70)                  
[    1.143879] [<8058b688>] (dev_pm_set_wake_irq) from [<8065d670>] (pcf85063_probe+0x204/0x2f4)                                    
[    1.152414] [<8065d670>] (pcf85063_probe) from [<8065ed90>] (i2c_device_probe+0xac/0x2c4)                                        
[    1.160601] [<8065ed90>] (i2c_device_probe) from [<8057e950>] (really_probe+0x24c/0x488)                                         
[    1.168701] [<8057e950>] (really_probe) from [<8057ed54>] (driver_probe_device+0x78/0x1c4)                                       
[    1.176974] [<8057ed54>] (driver_probe_device) from [<8057f100>] (device_driver_attach+0x58/0x60)                                
[    1.185854] [<8057f100>] (device_driver_attach) from [<8057f1bc>] (__driver_attach+0xb4/0x154)                                   
[    1.194473] [<8057f1bc>] (__driver_attach) from [<8057cad8>] (bus_for_each_dev+0x64/0x90)                                        
[    1.202659] [<8057cad8>] (bus_for_each_dev) from [<8057db18>] (bus_add_driver+0x16c/0x208)                                       
[    1.210931] [<8057db18>] (bus_add_driver) from [<8057fa34>] (driver_register+0x74/0x108)                                         
[    1.219029] [<8057fa34>] (driver_register) from [<8065f68c>] (i2c_register_driver+0x3c/0xac)                                     
[    1.227474] [<8065f68c>] (i2c_register_driver) from [<80102670>] (do_one_initcall+0x44/0x194)
[    1.236009] [<80102670>] (do_one_initcall) from [<80e00e64>] (kernel_init_freeable+0x148/0x1e4)
[    1.244716] [<80e00e64>] (kernel_init_freeable) from [<80914f2c>] (kernel_init+0x8/0x110)
[    1.252900] [<80914f2c>] (kernel_init) from [<801010e8>] (ret_from_fork+0x14/0x2c)
[    1.260469] Exception stack(0xb0093fb0 to 0xb0093ff8)
[    1.265525] 3fa0:                                     00000000 00000000 00000000 00000000
[    1.273707] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    1.281888] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[    1.288511] ---[ end trace 2ff9b5ad99dcb9b6 ]---
[    1.293186] rtc rtc0: failed to enable irq wake
[    1.303787] rtc-pcf85063 3-0051: registered as rtc0
[    1.309405] snvs_rtc 30370000.snvs:snvs-rtc-lp: registered as rtc1
[    1.315738] i2c /dev entries driver

Then, when using the RTC device several times, everything looks good.

~$ echo +10 > /sys/class/rtc/rtc0/wakealarm

I can see, that changes to the alarm are reflected in the corresponding registers (it works as expected).

~$ i2cdump -f -y -r 0x0-0xf 3 0x51 b
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 40 36 15 28 01 11 22 40 36 15 28 80    ....@6?(??"@6?(?

I can repeat this commands as much as I like… …but when I enter the suspend mode, the behavior changes!

~$ echo +10 > /sys/class/rtc/rtc0/wakealarm
~$ systemctl suspend

After the 10s, the system resumes. But now, I am no more able to activate a new alarm:

~$ echo +10 > /sys/class/rtc/rtc0/wakealarm
-sh: echo: write error: Permission denied

And dumping i2c device looks very strange…

~$ i2cdump -f -y -r 0x0-0xf 3 0x51 b
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX

…and the output of dmesg is as follows (there seems to be an exception with the RTC driver):

--- snip ---
[  287.991068] OOM killer enabled.
[  287.994212] Restarting tasks ... 
[  288.018896] usbmisc_imx 30b10200.usbmisc: vbus is error [  288.027546] usbmisc_imx 30b10200.usbmisc: Error occurs during detection: -22 [  288.040850] done.
[  288.045136] PM: suspend exit
[  288.188113] irq 66: nobody cared (try booting with the "irqpoll" option)
[  288.194832] CPU: 0 PID: 1 Comm: systemd Tainted: G        W  O      5.4.161-5.6.0-devel+git.0f0011824921 #1
[  288.204571] Hardware name: Freescale i.MX7 Dual (Device Tree) [  288.210341] [<8010eaf8>] (unwind_backtrace) from [<8010bb1c>] (show_stack+0x10/0x14) [  288.218092] [<8010bb1c>] (show_stack) from [<80914d84>] (dump_stack+0x90/0xa4) [  288.225320] [<80914d84>] (dump_stack) from [<8090ca54>] (__report_bad_irq+0x3c/0xc0) [  288.233071] [<8090ca54>] (__report_bad_irq) from [<8016ea20>] (note_interrupt+0x264/0x2b0) [  288.241341] [<8016ea20>] (note_interrupt) from [<8016b728>] (handle_irq_event_percpu+0x58/0x64)
[  288.250045] [<8016b728>] (handle_irq_event_percpu) from [<8016b778>] (handle_irq_event+0x44/0x68) [  288.258921] [<8016b778>] (handle_irq_event) from [<8016f468>] (handle_level_irq+0xb4/0x140) [  288.267278] [<8016f468>] (handle_level_irq) from [<8016a868>] (generic_handle_irq+0x24/0x34) [  288.275723] [<8016a868>] (generic_handle_irq) from [<80518614>] (mxc_gpio_irq_handler+0x48/0x164) [  288.284603] [<80518614>] (mxc_gpio_irq_handler) from [<80519214>] (mx3_gpio_irq_handler+0x60/0xac) [  288.293567] [<80519214>] (mx3_gpio_irq_handler) from [<8016a868>] (generic_handle_irq+0x24/0x34) [  288.302355] [<8016a868>] (generic_handle_irq) from [<8016ae6c>] (__handle_domain_irq+0x5c/0xb0) [  288.311058] [<8016ae6c>] (__handle_domain_irq) from [<80506fbc>] (gic_handle_irq+0x4c/0x90) [  288.319413] [<80506fbc>] (gic_handle_irq) from [<80101e10>] (__irq_usr+0x50/0x80) [  288.326895] Exception stack(0xb0093fb0 to 0xb0093ff8)
[  288.331950] 3fa0:                                     00832870 76f699cc 0000006f 0000006f
[  288.340131] 3fc0: 00832848 008191c8 80000000 fffffffa 007ff6d8 007ff6d8 7ed5aa4c 76f699cc [  288.348310] 3fe0: 76fb6d6c 7ed5a9f0 76f1b4ad 76ce70a0 600f0030 ffffffff [  288.354922] handlers:
[  288.357200] [<e0ffacc5>] irq_default_primary_handler threaded [<c40163d5>] pcf85063_rtc_handle_irq [  288.366168] Disabling IRQ #66 [  288.434623] systemd-journald[171]: Successfully sent stream file descriptor to service manager.
--- snip ---

Can anyone help me to get the external RTC running also after a suspend/resume change? Any help would be greatly appreciated.

Cheers

Update: I am aware that both the internal (snvs_rtc) and external (PCF85063) RTCs are used. It would be enough to use only the external RTC, but I have not managed to disable it. When it is disabled, the system no longer boots and this last dmesg message appears:

[  OK  ] Mounted /var/volatile.
         Starting Load/Save Random Seed...
[    6.396724] systemd-journald[173]: Successfully sent stream file descriptor to service manager.
[  OK  ] Started udev Kernel Device Manager.
[  OK  ] Started Load/Save Random Seed.

I have disabled it with following code in the DTS:

&snvs_rtc {
  status = "disabled";
};

Solution

  • This part from dmesg you claim is good is actually not:

    [    1.071396] rtc-pcf85063 3-0051: wake irq already initialized
    [    1.293186] rtc rtc0: failed to enable irq wake
    

    Which is the warning splat you get in the full dmesg. Are you sure about the RTC interrupt being connected on gpio1 1? It seems this GPIO is already used as a wakeup interrupt by another driver.

    Note that the wakeup-source; property is not needed when you have an interrupt defined.