Some ways to improve Pinephone safety
This is a follow up on some issues from the previous article. On surface,
solutions to some of the previously presented issues can seem simple. Toggle a
few registers in PMIC, and we're mostly done. Trouble is that safety mechanisms
are barely ever triggered, by definition. Safety events occur rarely. That means
that the mechanisms are not regularly tested, and it is not known that
Also it's not clear which code's responsibility fixing the issues should
be. Bootloader, or kernel, or userspace? Finally, there are a bunch of devils in
the details, that complicate the upstreamability of any solution. And having
fixes upstream is necessary to make sure they reach the most users.
Nevertheless, at least enabling some pre-existing PMIC functionality blindly
is better than nothing, so that's precisely what I decided to do in
p-boot. It's the easiest place to start resolving these issues for me
personally, and for other p-boot users.
I fixed two issues:
- I enabled the battery temperature monitoring and charging regulation based
on temperature thresholds defined in the Pinephone battery specification.
- I enabled emergency shutdown when crossing the critical temperature
I didn't measure the 3kOhm NTC used in Pinephone battery and third party
batteries I bought. I just used a table from some random 3kOhm NTC spec on The
Internet, that seemed like it could match. Hopefully it's close enough.
Trouble with the second fix is that it's a hard power cut-off, so data loss
may occur when PMIC overheats. There are three fixed temperature levels in
AXP803. On level 1 the charging is limited, on level 2 the interrupt is sent
to SoC, on level 3 the PMIC shuts down if configured to do so (by default it
keeps running, and this is what my p-boot fix changes). Ideally, the crossing of
level 2 would be handled by Linux to make it safely shut down the system, and
level 3 forced power cut-off would never happen. Arguably, if charging was
source of the heating, crossing level 1 will lead to resolving the issue, so
the next level will not be reached.
Suggested fixes elsewhere
These fixes will reach a very limited audience. It would be nice to have
these fixes in U-Boot too, but that's not possible at the moment, because
U-Boot doesn't have access to PMIC.
Other places to put the fix is to ATF or Linux kernel. That can reach more
people faster, but there would have to be some generic mechanism to make the fix
upstreamable, otherwise it will not reach people using the mainline Linux kernel
or mainline ATF.
There are some ways to approach this:
- Use battery description in DT from ATF to set up
thresholds in PMIC (ATF has access to PMIC).
- Use battery description in DT from Linux's battery charger driver for
AXP803 to set up thresholds in PMIC and stop disabling temperature
- Use charger
manager in Linux, but that looks like it's a completely software solution,
that will be inferior to PMIC handling the regulation. And it seems it would not
work in system suspend, anyway, because Linux is not running then.
- Detect Pinephone compatible string in either ATF or Linux and set up the
thresholds to ad-hoc values for 3kOhm NTC. (easiest, unlikely to be acceptable
First, the most generic solution would be to have a description of the
battery in DT describing the Pinephone. Sadly, the current
bindings don't include battery temperature limits.
Also converting from temperature to NTC resistance (which is necessary to
determine the code word from ADC for the limits used by the temperature monitor
logic in PMIC) is not straightforward. It is usually defined in NTC datasheet as
a table. Do I have NTC datasheet? No. I bought the batteries online from some
mobile phone service shop.
There are also equations that approximate the temperature – resistance
relationship for the NTC, which could be used instead of a fixed table, if one
knows the relevant coefficients. These can be calculated after measuring the
NTC's resistance at a few temperature points when we lack the datasheet.
So generic solution may look like this:
- DT contains battery temperature limits from the battery spec
- DT contains NTC coefficients (perhaps also on the battery node)
- some routine would use all this info from DT to calculate code words used by
AXP803 ADC and program them to PMIC (either in ATF, or Linux)
Kernel also has support for NTC devices, so maybe NTC can be described
outside of the battery node (even though it's part of the battery).
This may all fail to be upstreamed on one thing: the battery is user
swappable, so it's arguably not part of the Pinephone, and describing it inside
the pinephone DT will not be appropriate.
I don't have any plans implementing any of the above, atm. Maybe with the
exception of adding a 4th approach to the fix to my Linux kernel (the easiest
one ;)). I'd like to work on my multi-boot image. So these are mostly pointers
for somebody else who'd like to tackle this.
Fast charging is not necesary in many situations, so having it as a default
is not great. User should be able to decide if he wants to trade off slower,
safer charging and battery longetivity over speed. This tradeoff can be realized
in many ways.
All this is already controllable from userspace via sysfs. Ideally there
would be some charging monitoring daemon that would take into account
users's wishes and select proper strategy for charging, based on preference for
battery longetivity or speed.
There are several trade offs the deamon would be able to handle:
- 0.2C charging all the way (slow, but safer)
- 0.5C charging to 40% and 0.2C charging to 100% (middle ground)
- 0.5C charging all the way to 100%
All this is decision making that doesn't belong to the kernel.
Similar daemon could monitor power usage of the phone and try to limit it to
safer levels, or warn the user if that's not possible.