RTC Subsystem, Recent Changes and Where it is Heading - Alexandre Belloni, Bootlin [Open Source Summit EU 2019]

Alexandre is maintainer for RTC since 4.1.

linux-rtc is using patchwork. Alexandre reduced the backlog from about 3000 to about 20 patches. Mailing list is pretty liverly with 100-300 mails per month. Number of commits is typically about 50 per release cycle, with spikes when there are big changes in infrastructure.

RTC has many drivers. Since 4.0, roughly 40 new drivers were added, and many other ones were made compatible with new IPs. Unfortunately, even though an RTC is a really simple device, every vendor thinks they can do it better than others.

An RTC consists of a crystal (either inside or outside of the package), usually 32kHz and a counter. Due to ageing, temperature and process variation, the crystal doesn’t always run at the same speed. Therefore the RTC has a register to insert correction pulses. A sysfs interface has been added for this recently, offset. Unit is in parts per billion. This is called digital trimming by some vendors.

There is also analog trimming to tune the crystal. This works by changing the capacitative load connected to the crystal. The required value depends on the type of crystal. Therefore, there is a device tree property for this.

Some RTCs have a small amount of RAM. Since the RTC is always on, this is non-volatile. Therefore, this memory is exposed in the nvmem framework. Drivers can register it through rtc_nvmem_register. It can be called multiple times, e.g. if there is both RAM and EEPROM. Some drivers already had an nvram sysfs file for this. This is still supported but issues a deprecation warning.

devm_rtc_device_register was difficult to use race-free, because it combined allocation and registration. This is needed mainly for interrupts, because the interrupt should be registered in the device structure. Therefore there are now two separate calls for allocation and for registration. Also, it is no longer possible to allocate rtc devices without devm.

A similar race condition existed for sysfs attributes. The attributes appear on registration, but at that point the callbacks weren’t registered yet. Now registration only happens after everything is initialized so the sysfs attributed appear only at the end. Custom attributes are created with sysfs_add_group so they will also appear atomically on registration.

Drivers can now declare the supported time range of the RTC device. This allows the kernel to check if the time sent by userspace is really supported, before attempting to write it. Only continuous time is supported. This is important for RTC devices that don’t support the non-leap year on the century transition.

The available range also makes it possible to fix the RTC end of time issue by adding an offset. All times in RTC are unsigned, so there is no Y2038 problem. Instead, there’s a problem in Y2100 (due to leap year) or Y2106 (32-bit unsigned overflow). Dates before 2000 still need to be supported for Android. The offset is registered with the start-year device tree property. It should be possible to update this dynamically from userspace as well.

A new printk format %ptR printk format was added for printing a tm struct (broken down time). Also added tracepoints for the various actions. time_t overflow is properly handled in rtc_hctosys for 32-bit platforms. There’s an rtc-range tool (in a separate repo) that checks a set of cut-off dates to verify continuity of the RTC range.

Some RTC’s can register timestamps, typically on a GPIO transition. The subsystem now has support for reading out those timestamps. However this is open coded in each driver. It is exposed through timestampX sysfs files. This needs to be improved, but it’s not that urgent.

There is support for trickle charging the RTC battery. The RTC chip manages that, but it needs to be configured properly according to the type of battery.

A lot of cleanups have been done.

  • Unnecessary/duplicate checks have been removed.
  • Unused rtc_class_ops members have been removed.
  • Remaining ones have been const-ified if possible.
  • Unused rtc_control and rtc_ireq_register APIs have been removed.
  • All driver source files now start with rtc_ and all core files don’t.

A future feature is voltage drop detection. The current ABI is not working well for more advanced RTCs. There may be a monitor for only the AUX supply (powering RTC) or for both MAIN and AUX supply. There also be multiple states, e.g. that temperature compensation is lost if the battery is too low. In this case we don’t loose the time but it’s less precise. Alexandre wants to add a new ioctl to manage that. The exact structure still has to be decided, to make sure it supports all RTCs.

Backup switch mode is where software can select when the power source is switched. For example, you may want to disable backup switch entirely if the main power supply is also a relatively small battery, because the switch itself consumes power as well. Then you can switch based on availability of VDD or on a specific VDD level. It will be implemented through a device tree property. It’s a matter of finding out what kind of things devices make available. It should not be hardcoded in the driver, because the bootloader may already have configured it correctly. Hardcoding it may break a platform that is already well-configured.

Alarm handling is now often done by modifying the rtc_ops struct when the probe detects there is no alarms support. This stops constification. Alarms with only minute (instead of second) granularity are now open-coded in the drivers. It is difficult to detect if an alarm is capable of waking up the system. This is currently all open-coded in drivers.

Some RTCs can raise multiple interrupts and can configure which alarm goes to which interrupt. This can be used to route one interrupt to the CPU and another to the PMIC. This is not supported at the moment.

Many RTCs have similarities in how they are implemented. For example, they will often have BCD encoded broken down time. This can be factored out, particularly in combination with regmap.

The RTC subsystem is also used for timers that are not actually capable of storing system time, but that can be used as alarms.