IOT RTC rv-3028 driver is written for 5.13 and Torizon is 5.5

We have a low power RTC (a RV-3028) and supercap on my new board.

RV-3028-C7 - Micro Crystal

Following this approach, which is absolutely fine.

https://developer.toradex.com/knowledge-base/building-external-kernel-modules-with-torizon

To provision it we have a driver to add to Torizon

rv3028 (1).zip (1.4 MB)

The issue is that this driver has features that appear in a later version of the kernel

Specifically, the identifier RTC_FEATURE_ALARM has been added in kernel 5.13. That
means that the source code we have is too new for the current Torizon
kernel.

make: Entering directory ‘/workdir/rv3028-mod’
make -C /storage/linux M=/workdir/rv3028-mod
make[1]: Entering directory ‘/storage/linux’
AR /workdir/rv3028-mod/built-in.a
CC [M] /workdir/rv3028-mod/rtc-rv3028.o
/workdir/rv3028-mod/rtc-rv3028.c: In function ‘rv3028_ioctl’:
/workdir/rv3028-mod/rtc-rv3028.c:526:42: error: ‘RTC_VL_DATA_INVALID’
undeclared (first use in this function)
526 | status = status & RV3028_STATUS_PORF ? RTC_VL_DATA_INVALID : 0;
| ^~~~~~~~~~~~~~~~~~~
/workdir/rv3028-mod/rtc-rv3028.c:526:42: note: each undeclared
identifier is reported only once for each function it appears in
/workdir/rv3028-mod/rtc-rv3028.c: In function ‘rv3028_probe’:
/workdir/rv3028-mod/rtc-rv3028.c:844:13: error: ‘RTC_FEATURE_ALARM’
undeclared (first use in this function)
844 | clear_bit(RTC_FEATURE_ALARM, rv3028->rtc->features);
| ^~~~~~~~~~~~~~~~~
/workdir/rv3028-mod/rtc-rv3028.c:844:43: error: ‘struct rtc_device’
has no member named ‘features’
844 | clear_bit(RTC_FEATURE_ALARM, rv3028->rtc->features);
| ^~
/workdir/rv3028-mod/rtc-rv3028.c:884:8: error: implicit declaration of
function ‘devm_rtc_register_device’; did you mean
‘rtc_register_device’? [-Werror=implicit-function-declaration]
884 | ret = devm_rtc_register_device(rv3028->rtc);
| ^~~~~~~~~~~~~~~~~~~~~~~~
| rtc_register_device
/workdir/rv3028-mod/rtc-rv3028.c:889:2: error: implicit declaration of
function ‘devm_rtc_nvmem_register’; did you mean
‘devm_nvmem_register’? [-Werror=implicit-function-declaration]
889 | devm_rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
| ^~~~~~~~~~~~~~~~~~~~~~~
| devm_nvmem_register
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:262:
/workdir/rv3028-mod/rtc-rv3028.o] Error 1
make[1]: *** [Makefile:1734: /workdir/rv3028-mod] Error 2
make[1]: Leaving directory ‘/storage/linux’
make: *** [Makefile:6: all] Error 2
make: Leaving directory ‘/workdir/rv3028-mod’
Traceback (most recent call last):
File “/builder/tcbuilder/backend/kernel.py”, line 64, in build_module
subprocess.run(f"""PATH=$PATH:{toolchain} KERNEL_SRC={linux_src}
KDIR={linux_src}
File “/usr/lib/python3.9/subprocess.py”, line 528, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command
‘PATH=$PATH:/storage/toolchain/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
KERNEL_SRC=/storage/linux KDIR=/storage/linux
CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 make
-C /workdir/rv3028-mod’ returned non-zero exit status 2.

Error: Error building kernel module(s)!

Can you recommend what we do now? We don’t actually use the “wake up” processor event feature, so do we try to re-write the driver; dump the very smart RTC chip and the design we have; or is there a possibility of a newer Torizon on the horizon ?

Thanks

Fat Linux.

Greetings @FatLinux,

Sometime this year we plan to release a 6.0 of our BSP and TorizonCore software. Tentatively speaking the plan is that in this 6.0 the kernel version will then be 5.15.

With that said, the most straightforward option would be to just wait. However, this depends on your use-case and requirements of course. Also you’ll need some kind of work-around in the short-term.

Best Regards,
Jeremias

Hi,

Thank you for getting back to me.

I wish I could wait until next year, I have been taking a roasting for a few months now for being late (other stuff!).

So the device tree is like this:

torizon@Thinkcentrei9:~/torizoncore/custom_overlays$ cat re*
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*

  • Copyright 2020-2021 Toradex
    */

// Enable the parallel RGB interface on Colibri iMX8X

/dts-v1/;
/plugin/;

/ {
compatible = “toradex,colibri-imx8x”;
};

&i2c1 {
status = “okay”;

    rtc_i2c: rv3028@52 {
            compatible = "microcrystal,rv3028";
            reg = <0x52>;
            status = "okay";
            trickle-resistor-ohms = <11000>;
    };

};

So the trickle resistor is on, and I measured the supercap with a probe and I get 3.1V which is nice.

I can then boot up the Imx8 module and

root@colibri-imx8x-07021201:~# dmesg | grep rtc2
[ 7.603848] rtc-rv3028 17-0052: registered as rtc2

I can set the clock

root@colibri-imx8x-07021201:~# hwclock -w -f /dev/rtc2

I check it …

root@colibri-imx8x-07021201:~# hwclock -r -f /dev/rtc2 --verbose
hwclock from util-linux 2.35.1
System Time: 1649452925.107593
Using the rtc interface to the clock.
Last drift adjustment done at 1649452817 seconds after 1969
Last calibration done at 1649452817 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick…
…got clock tick
Time read from Hardware Clock: 2022/04/08 21:22:06
Hw clock time : 2022/04/08 21:22:06 = 1649452926 seconds since 1969
Time since last adjustment is 109 seconds
Calculated Hardware Clock drift is 0.000000 seconds
2022-04-08 21:22:05.103527+00:00

root@colibri-imx8x-07021201:~# shutdown now

And then pull the socket, I then put a meter on the supercap and it reads 3.2V.

Boot up again.

colibri-imx8x-07021201:~$ sudo su -
Password:
root@colibri-imx8x-07021201:~# hwclock -r -f /dev/rtc2 --verbose
hwclock from util-linux 2.35.1
System Time: 1649453129.848951
Using the rtc interface to the clock.
Last drift adjustment done at 1649452817 seconds after 1969
Last calibration done at 1649452817 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick…
ioctl(3, RTC_UIE_ON, 0): Invalid argument
Waiting in loop for time from /dev/rtc2 to change
hwclock: ioctl(RTC_RD_TIME) to /dev/rtc2 to read the time failed: Invalid argument
…synchronization failed

root@colibri-imx8x-07021201:~# dmesg | grep rtc2
[ 6.947201] rtc-rv3028 17-0052: registered as rtc2

So the rtc backup is on, the trickle charger is on, but the power switch over is not working I think and the time is being lost. I will pursue Micro Crystal Switzerland for some help next week, maybe we get lucky and if so I will post the solution on here!

Meanwhile, any ideas are gladly appreciated.

Regards

Fat Linux

Hi,

What we need is a kernel patch for Torizon if you want to use the RV-3028 RTC module (which to be fair is a new product, but 45nA consumption and low ppm).

The kernel is rtc-rv3028.c

When supplied by Micro Crystal Switzerland the module has the battery trickle charge switched off. This is easily rectified in the device tree with a single line: you say the resistance to put in place to specify the trickle and it works.

However, there is a second part to this. The RV-3028 is shipped with the automatic VBACKUP switch over set to “off”. So the battery or cap backup charges but won’t power the module.

The onboard EEPROM has a register 0x37 which as 8 bits, bits 2 and 3 are both 0 when the module is supplied, but the smooth voltage threshold switchover option needs both these to be 1.

So patch for rtc-rv3028.c I think will be needed to write a pair of 1’s to the register 0x37, probably at the point where and when the trickle charge bits are being set. Finger crossed.

So are you now just attempting to patch or backport the driver to make it work for the older kernel that TorizonCore is running?

I didn’t reply to this because I made some practical evaluations (i.e. I built a rig to test that the supercap was charging as predicted, and to compare the two different switch over techniques.

I got some contradictions to the documentation and have written to the manufacturer to get some confirmations. At the moment the RTC is definitely being powered (so it keeps the time), but I haven’t finished my code to probe the registers to know which bits are enabled on x37. The docs definitely say these devices are shipped with these two bits off.

Will keep you posted.

Fat Linux.

Thank you for keeping us posted.

Hi Jeremias,
I didn’t get a reply from Micro Crystal. How far does version Torizon 5.6 get to with regard to kernel versions? We are just updating the time every time the battery is changed which is OK.

This is what we get when we boot up.

colibri-imx8x-07021198:~$ dmesg | grep “rtc”
[ 1.783486] imx-sc-rtc scu:rtc: registered as rtc1
[ 2.025443] rtc-ds1307: probe of 17-0068 failed with error -5
[ 2.050936] imx-drm display-subsystem: bound imx-dpu-crtc.0 (ops dpu_crtc_ops)
[ 2.051871] imx-drm display-subsystem: bound imx-dpu-crtc.1 (ops dpu_crtc_ops)
[ 2.273795] hctosys: unable to open rtc device (rtc0)
[ 6.855734] rtc-rv3028 17-0052: registered as rtc0
colibri-imx8x-07021198:~$ sudo hwclock -r -f /dev/rtc0 --verbose
Password:
hwclock from util-linux 2.35.1
System Time: 423.065600
Using the rtc interface to the clock.
Last drift adjustment done at 1656319588 seconds after 1969
Last calibration done at 1656319588 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick…
…got clock tick
Time read from Hardware Clock: 2022/06/28 02:56:19
Hw clock time : 2022/06/28 02:56:19 = 1656384979 seconds since 1969
Time since last adjustment is 65391 seconds
Calculated Hardware Clock drift is 0.000000 seconds
2022-06-28 03:56:18.237319+01:00
colibri-imx8x-07021198:~$

Cheers

FatLinux

How far does version Torizon 5.6 get to with regard to kernel versions?

We don’t majorly change the Linux Kernel version in our images unless we also change the major version of our BSP. Therefore TorizonCore 5.6 is still based on Linux kernel version 5.4. After 5.6 we plan to have one more 5.X version, 5.7, before we move to BSP 6.X where we will upgrade the kernel version to 5.15 I believe.

Best Regards,
Jeremias

Hi,

Could Toradex do some NRE work and make a patch for me ?

Cheers

Richard

Hi @FatLinux !

Toradex usually doesn’t execute development services. But we do have a network of partners that can perform development services.

Here is the link to our list of partners.

And I would like to ask you to get in touch with your account manager, as he can effectively help you to pick the best partner for your needs.

Best regards,

Hi,

Thanks for your help. We are going to do it in-house instead. It’s a
few hours.

Hi @FatLinux !

Thanks for the feedback.

Best regards,

RE: Cheeky workaround for the RV-3028

Postscript:

I forgot to post this bit of information.

For the time being, the RV3028 values can be manually poked into the EEPROM. It only needs doing once, and it takes 30 seconds.

Set the date on the module (On my board I only have one RTC, the RV3028 and no internet clock)

sudo date --set=“20221107 0436”

Get yourself Debian with root access to the hardware

docker run -it --privileged torizon/debian:$CT_TAG_DEBIAN /bin/bash

Check the rtc hardware is there

apt update && apt install i2c-tools
root@1bb8c$46bb0e:/# i2cdetect -y -r 17
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: – – – – – 0d – –
10: – – – – – – – – – – – – – – – –
20: – – – – – – – – – – – – – – – –
30: – – – – – – – – – – – – – – – –
40: – – – – – – – – – – – – – – – –
50: – – UU – – – – – – – – – – – – –
60: – – – – – – – – UU – – – – – – –
70: – – – – – – – –

The RV3028 is on 0x52 and it is right there and ready. So refer to your manual to get the settings you want, but I need the trickle charge on, backup switchover on, and backup to switch over when the main power is off = 0x3d.

poke this value into the eeprom

i2cset -f -y -a 17 0x52 0x37 0x3d

and sync the time

sudo hwclock -w -f /dev/rtc0

You should (provided the battery backup is charged up, or in my case the supercap) now have a RV3028 that will keep time.

cheers

Fat Linux

1 Like