The Power-Supply Subsystem - Sebastian Reichel, Collabora [Open Source Summit EU 2018]

The power supply subsystem manages batteries, their gauges and their chargers.

Sebastian maintains the power-supply subsystem since 2014.

You can see this subsystem in /sys/call/power_supply. It exposes information about the batteries, how much power they have, and if they are charging. In addition to the sysfs interface, it also is pushed into udev. E.g. if a power supply is plugged in, an event is emitted.

Capacity can be exposed in different ways (e.g. % or uAh); in general, what is exposed to userspace is just what the device really supports, but in some cases there is also a conversion done.

Smart batteries are batteries that include a fuel gauge. The power supply system is mostly concerned with the fuel guage. However, in embedded systems, this is sometimes done with multiple chips, so the driver becomes a bit complicated.

A battery driver creates a power_supply_desc structure with a list of properties, which are the things exposed through sysfs and events. A function to query the property has to be added, that should check the type of property queried. The values returned have to be in standard units (e.g. uAh) so there is usually a conversion to be done. Some properties have some more complicated interpretation, e.g. battery health. Some properties may be writable, mainly to set alarm threshold (e.g. temperature threshold).

Sometimes there is no existing property that works for something exposed by the battery. For these, a custom sysfs attribute can be created. These are registered with an attribute group in teh power supply configuration. Except that it’s not been merged yet, most likely for 4.21.

Chargers are modeled separately from the battery. When registering the battery, the chargers connected to it are enumerated. The framework will call a callback when a power supply has changed, the battery driver can then forward this to a userspace event.

Recently, a structure was added to keep the battery characteristics (which don’t change).

Another recent addition is discharge curves. This was traditionally done in userspace because there you do floating point - but then in-kernel consumers are not possible. The curves also describe the temperature-dependency of the discharge model.

USB chargers may have different modes. This was not modeled, the charger type was just ‘USB’. Therefore, a new usb_type was added to reflect the USB charger mode. It can even be writable to switch the charge mode.

If a battery has multiple fuel gauges, this would be exposed as two devices so two separate batteries. Currently there is no solution for that.

Charging may require tight monitoring. For x86 the firmware does it so no worries, but on embedded this is different. There is a charger-manager driver from Samsung that does this. Ideally this should be migrated to the power supply core.

IIO may be used to get the temperature of a battery. In theory it should be possible to get other values through IIO as well, but it’s currently not done. In such an architecture the power supply driver is a consumer of the IIO driver.