Setting battery thresholds on a coreboot X220

After installing coreboot on your Thinkpad (X220) you’ll quickly realise that tp_smapi, which you were using for setting battery thresholds, doesn’t work.

Under “ThinkPad Battery Features” tlp will tell you:

tp-smapi = inactive (unsupported hardware)

And acpi_call doesn’t work either.

The proprietary BIOS of Thinkpad laptops include an interface called SMAPI which allows setting these thresholds, and other cool things. Unfortunately, coreboot doesn’t include this. If you’re an X200 user you might be in luck as the patch for supporting tpacpi-bat is currently in code review.

But what about the X220?

For us there’s a workaround too, though not as clean. We can manually control the RAM of the embedded controller, the chip that handles the battery and charging, and many other things. For that you need ectool, which is included in coreboot’s git repository, in coreboot/util/ectool. Simply use make to compile it.

The bits of the EC’s RAM we need to modify are explained in this ticket on the coreboot issue tracker. I advice you to read the full thread before applying this to your system. It also explains under what conditions this trick might work on other Thinkpad models.

For the X220 it boils down to this:

Byte 0x03 allows for configuring if we’re setting the start or stop threshold. Specifically, bit 2 (=4) of byte 0x03. If we’re setting the stop thresholds (percentage at which the battery should stop charging), we set this bit to true:

# ectool -w 0x3 -z 0x44

We can then specify the threshold. Simply note the percentage you’ll like, and set bit 7 to true, by adding 128. 80% becomes:

80+128 = 208 = 0xD0

Set this threshold by writing it to byte 0x24 of the EC’s RAM:

# ectool -w 0x24 -z 0xD0

For setting the start threshold (percentage at which the battery should start charging), do the same but set bit 2 of byte 0x03 to false:

# ectool -w 0x3 -z 0x40
# ectool -w 0x24 -z 0xB2

This sets the start threshold to 50%.

I currently run this in a script that runs at boot. It’s not required though, since the EC will remain active when the battery is plugged in and has charge, even when the laptop is “off”.


#!/bin/bash
# set-battery-thresholds.sh

# Stop charing at 80%.

ectool -w 0x3 -z 0x44
ectool -w 0x24 -z 0xd0

# Start charging at 50%.
ectool -w 0x3 -z 0x40
ectool -w 0x24 -z 0xb2

Systemd service file:


[Unit]
Description=Set battery thresholds

[Service]
Type=simple
ExecStart=/data/bin/set-battery-thresholds

[Install]
WantedBy=multi-user.target

While we’re at it, here’s a table containing the values to write to byte 0x24 for different percentages:

Percentage 0x24 value
10 0x8a
15 0x8f
20 0x94
25 0x99
30 0x9e
35 0xa3
40 0xa8
45 0xad
50 0xb2
55 0xb7
60 0xbc
65 0xc1
70 0xc6
75 0xcb
80 0xd0
85 0xd5
90 0xda
95 0xdf
100 0xe4

Thanks to the awesome coreboot developers and other contributors, especially those participating in the ticket I used as a base when writing this blog post.