LPC SPI Firmware and Driver Prototype

For adventurous folks who wish to build the kernel, a module, and flash the LPC firmware, there is now a prototype kernel driver that will return the battery voltage, current, percentage, and charging state as known by the LPC.

the firmware and module (reform2-lpc-driver):

the device tree changes are visible in a merge request for the kernel:

The LPC firmware has only been tested on my device, but I am confident that it will not lock up and crash the LPC, it does a fake kinda spi that is non-blocking.

The driver can be massively improved to create proper entries for standard hardware devices so that existing desktop utilities find the battery automatically. As-is though, adding an entry so that sway-waybar can show the battery state is quick.


This is awesome, thank you very much. I will review and try this out as soon as possible.

no problem!
I’ve added power_supply driver class support based on the properties currently available in the lpc. existing power apps now recognize the battery and its state, after the lpc calibrates itself through a full charge cycle.

An interface to poll the cell voltage and lpc charge state is also present, though unused in the power_supply sys class.

  native-path:          8xlifepo4
  power supply:         yes
  has history:          yes
  has statistics:       yes
    present:             yes
    rechargeable:        yes
    state:               fully-charged
    warning-level:       none
    energy:              48.9942 Wh
    energy-empty:        0 Wh
// -- obv incorrect, result of battery not being calibrated yet
    energy-full:         79.9064 Wh 
    energy-full-design:  51.6258 Wh
    energy-rate:         5.39929 W
    voltage:             27.219 V
    charge-cycles:       N/A
    percentage:          100%
    capacity:            100%
    technology:          lithium-iron-phosphate
    icon-name:          'battery-full-charged-symbolic'

I’m testing this now in my personal Reform. I have built and flashed the LPC firmware, and built the LPC module on Reform itself, which worked fine. I can also load the module.

What is the expected behavior when LPC is still in “???%” mode? When running powerstat, it says Device is not discharging, cannot measure power usage. The battery info on the OLED says 0.247A discharge at the moment, though.

Edit: /sys/class/power_supply is empty for me. Where can I find the info that you pasted above?

Edit: Ah, I’m silly, probably need to update DTS as well

Yeah, the both the LPC and DTS need to be updated.

The lpc firmware sends its guess as to what the percentage is when its uncalibrated over spi. I couldn’t find any battery state that matched “calibrating” in the kernel power supply driver class.

Further confusing matters is that different battery applets poll different properties. The Sway one ignores the percentage capacity property entirely (and does not have code to even read it), preferring to calculate amp hours instead.

I haven’t delved into what KDE or Gnome do, perhaps they respect that property over monitoring mAh consumption.

1 Like

Looks good so far, I’ve merged the DTB changes into reform-debian-packages already, so installing a new reform kernel image package on a sysimage V3 Reform will already pull those in.

Testing here with KDE’s powerdevil and gnome-power-statistics. Will also put it in waybar, and test for a few days!

Observation: Discharge and Charge events are correctly recognized (plugging/unplugging power), but the system needs almost a minute to realize that this happened. Maybe a very long polling interval?

The driver does no polling or caching. Any access of the device node does an immediate query to the lpc. Sway battery indicator defaults to a minute pool interval iirc, I recall having to change that for its indicator.

1 Like

Can anyone walk me through the steps needed to test it out? Would love to try!

The kernel changes are checked in, so any kernel you update to from the reform repo or latest system image pipeline will have the necessary kernel changes.

As for the LPC firmware, you will need to clone and build it from here:

sudo apt install make build-essential binutils-arm-none-eabi gcc-arm-none-eabi
cd reform2-lpc-fw
# make sure the reform2-lpc-fw\tools utilities are built
cd tools/lpcrc
cd ../..
# build the new firmware
make -j 4

You will need a separate device to flash the firmware as doing so turns off the power to the Reform.
See: https://mntre.com/reform2/handbook/parts.html#flashing-the-firmware

Ideally use a linux box, otherwise in windows, you can use Cygwin and find the correct partition with cat /proc/partitions

With the new LPC firmware flashed, you can now build and install the new kernel driver found in the same repo https://source.mnt.re/NanoCodeBug/reform-lpc-fw-spi/-/tree/master for now, under reform2-lpc-driver

# install the kernel headers for your build
cd reform2-lpc-driver
sudo make install
# test the driver
make read

It should print some stats about the battery, including cell voltages. Unfortunately, because you’ve reset your LPC, the max charge will no longer be known and you will have to wait for a charge/discharge cycle to get accurate reporting.

KDE has a battery applet built-in, Waybar w/ Sway supports a battery field.
In ~/.config/waybar/config add "battery" to the location you desire in the "modules-right" array. As well as this node:

"battery": {
    "bat": "8xlifepo4",
    "interval": 30,
    "format": "BAT {}%"

You are a wizard! This is incredible work. After edits to the Swaybar it shows up…don’t forget your closing brackets, friends!!

Can confirm it pops right up in Gnome (without any alterations) and gives an estimate as well as an icon in the upper right. The only thing I noticed is that it is slow to update compared to checking the OLED.


One thing that just came up…I let gnome go to sleep while I was shopping for groceries. When I came back, Reform didn’t wake up (sad trombone). Once I restarted, I hopped into Sway and noticed a ~5% difference between what was reported on the OLED (lower) vs what the driver reported on-screen (higher). I put Reform back on the charger and the gap closed, until both figures hit 100.

I’m guessing the battery drain while asleep wasn’t reported to the driver, so it lost track and picked up where it left off?

EDIT: While discharging, the gap returned with Sway. Restarted and logged in to Gnome instead…and it’s perfectly in sync.

1 Like

from what i’ve seen, waybar and kde (and maybe also gnome) all use a different method for calculating remaining percentage.

The LPC firmware looks at current draw per sample period and does a linear calculation of current usage against min/max for creating the percentage. This is reported as the “capacity” property in the driver.

Waybar ignores the capacity percentage property in favor of the amperage properties and calculates its own percentage out of the hardcoded ideal capacity. You can manually add an entry to waybar that reads the capacity property instead, it will always match the oled value then.

I believe KDE and Gnome try more complicated algorithms to create non-linear charge and discharge profiles, but I haven’t delved into their algorithms. They also have slower battery status update loops.


FYI I just upgraded my os and battery status has disappeared from both sway and GNOME. I’ll have to try to install it again to see if it comes back or if some dependency has broken in the upgrade. Will check back in at some point.

Module/kernel version mismatch perhaps? Also, we really need to release this thing and put it in the official image. Mea culpa.

No problem! I was able to build the driver again, reinstall, and eventually it came back to waybar without having to edit the config file again.

Same deal as bnys: I upgraded to Linux 5.19, just had to reinstall the LPC driver and I got my battery readout back.

For non-adventurous folks, there is now this merge request against the reform-tools package which builds a reform2-lpc-dkms package that automatically builds and installs the lpc kernel module upon installation without you having to do anything by using the dkms system.

@nanocodebug could you supply a copyright header for reform2-lpc.c?


I just did a full-upgrade and the battery status disappeared in sway. Do I need to readd to the config file? Thanks, josch!!

Could you check whether you have the reform2_lpc module loaded?