Jump to content

[WiP] axp209 mainline sysfs interface


Recommended Posts

AXP202/209 sysfs interface patch for axp20x MFD drvier in mainline kernel

 

 

I'll try to maintain this patch as long as axp20x power driver is not present in mainline kernel. Adding partial sysfs interface to MFD driver is not a proper way to implement things in mainline kernel; if you want, you can use this code and RFC power driver patch to write a proper driver and send it upstream.

 

 

➜  ~  % ls /sys/power/axp_pmu/{ac,vbus,battery,charger,pmu,control,ocv_curve}
/sys/power/axp_pmu/ocv_curve

/sys/power/axp_pmu/ac:
amperage  connected  used  voltage

/sys/power/axp_pmu/battery:
amperage  capacity  charge  charging  connected  power  ts_voltage  voltage

/sys/power/axp_pmu/charger:
amperage  cell_activation  charging  low_power

/sys/power/axp_pmu/control:
battery_rdc         disable_fuel_gauge    set_vbus_direct_mode
charge_rtc_battery  reset_charge_counter

/sys/power/axp_pmu/pmu:
overheat  temp  voltage

/sys/power/axp_pmu/vbus:
amperage  connected  strong  used  voltage
âžœ  ~  % 

Shortlog:

 

 

Implemented averaging of 3 samples, increased ADC sampling frequency from default 25Hz to 100Hz.

To simplify configuration and to make it platform-independent, device path (i.e. "/sys/devices/platform/soc@01c00000/1c2ac00.i2c/i2c-0/0-0034/") is symlinked to "/sys/power/axp_pmu".

Fixed broken battery detection.

Rearranged sysfs structure, moved attributes to subdirectories.

Added basic documentation.

Fixed coulomb counters.

Added backup (RTC) battery charge config reading/writing.

Added properties for Rdc and OCV curve

Added manual battery calibration program

Added load/save feature for battery calibration program

 

 

 

How to test:

Patches for next and dev branches are included in Armbian build framework, use standart procedures to build and install new kernel.

.. or you can download this prebuilt kernel for next branch.

Latest version of the patch, basic documentation and battery calibration utility are available on GitHub.

 

TODO list:

Find and fix bugs.

Check if can be converted into a separate kernel module, preferrably power supply class driver.

 

Limitations:

AXP202/AXP209 only for now.

Things are implemented according to datasheet and my understanding of it.

 

Default settings for main battery according to datasheet:

Target voltage: 4.2V

Charging current: 500mA/1200mA (?)

 

Defaut settings for RTC battery:

Charging: disabled by default.

Target voltage: 3.0V

Charging current: 200uA

 

Standart disclaimer:

Code looks simple enough, but i wouldn't recommend using it on production environment yet. Bugreports are welcome, but I'm not responsible for kernel panics, lost data and exploded PMUs.

 

 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 

 

Edited by zador.blood.stained
Link to comment
Share on other sites

That's great. I'll schedule some tests for the weekend (using a Lime2 since this seems to be the best board to test since AXP209 is involved everywhere power related) and hope I get a battery until.

 

I'll use then a daemon to read out the values to be fed into RPi-Monitor (smoothing/averaging read-outs which helps comparing) and report back. Thx!

Link to comment
Share on other sites

I'm currently playing with it (yesterday's version) just to realize paths are different and values, eg:

 

  • 3.4: /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/axp20-supplyer.28/power_supply/ac/voltage_now = 5139000
  • 4.4: /sys/devices/platform/soc@01c00000/1c2ac00.i2c/i2c-0/0-0034/acin_voltage = 5139

 

Is there a specific reason to use different multipliers (I'm fine with different paths and also the symlink approach)?

Link to comment
Share on other sites

About paths - I think that recreating old path is not worth the effort since sysfs tree structure is completely different, and path may differ for different boards.

 

About values - I looked through old driver code and internally it's using millivolts, milliamps and millidegrees celsuis for storing values. I didn't play with old kernel too much so I implemented these values. I'll check kernel documentation to check for "default" multiplier and add it if needed.

 

Edit:

Units
~~~~~
Quoting include/linux/power_supply.h:

  All voltages, currents, charges, energies, time and temperatures in µV,
  µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
  stated. It's driver's job to convert its raw values to units in which
  this class operates.

OK, Will change in a moment.

Link to comment
Share on other sites

About paths - I think that recreating old path is not worth the effort since sysfs tree structure is completely different, and path may differ for different boards.

 

True -- but now we also have to differentiate between different kernels too. What's easy when a startup script or a daemon does this job (which would be the case when I look at it only from the 'integrate RPi-Monitor into Armbian' perspective but makes it a bit hard if others will do some sort of monitoring since a simple kernel update invalidates all sysfs paths).

 

But since you're also fixing other stuff and we might end up with different read-outs also I'm fine with different paths. Acked-by me ;)

Link to comment
Share on other sites

True -- but now we also have to differentiate between different kernels too. What's easy when a startup script or a daemon does this job (which would be the case when I look at it only from the 'integrate RPi-Monitor into Armbian' perspective but makes it a bit hard if others will do some sort of monitoring since a simple kernel update invalidates all sysfs paths).

Not simple kernel update, but upgrade from legacy to mainline. And even if mainline kernel update or different board configuration changes sysfs paths, symlink in sysfs will stay in the same place.

 

Startup script for rpi-monitor for example can check kernel version using any possible method and then make a symlink for different configuration file if needed.

Just as an example (concept):

/etc/rpi-monitor
	armada-mainline.conf
	current.conf -> sunxi-mainline.conf
	sunxi-legacy.conf
	sunxi-mainline.conf

BTW, display units fixed. New kernel package and patch uploaded.

➜  axp_pmu  % cat acin_current
401000
➜  axp_pmu  % cat acin_voltage
4710000
Link to comment
Share on other sites

Not simple kernel update, but upgrade from legacy to mainline. And even if mainline kernel update or different board configuration changes sysfs paths, symlink in sysfs will stay in the same place.

 

Startup script for rpi-monitor for example can check kernel version using any possible method and then make a symlink for different configuration file if needed.

 

Yes, or use just a bunch of symlinks always linking from the actual data source to the location specified in the templates. This way the 'Lamobo R1 fed with DC-IN through battery connector' could also be dealt with:

 

If battery_voltage is very low then this is a sign AXP209 disabled the charger since available voltage is above 4.2V. In this case the start script could do a simple 'echo 5000000 > /var/run/armbianmonitor/battery_voltage' and normally a 'ln -s /sys/devices/platform/soc@01c00000/1c2ac00.i2c/i2c-0/0-0034/battery_voltage /var/run/armbianmonitor/battery_voltage' instead.

 

Since I'm also starting to add SNMP support I currently prefer this method since all datasources could be queried below /var/run/armbianmonitor/

Link to comment
Share on other sites

Battery reading works properly [tested on Olimex Lime]... but the bug present in legacy is here too ;)

 

/sys/power/axp_pmu/status_battery_connected 

 

is 1 even there is no battery connected.
 

Link to comment
Share on other sites

@Igor

I enabled battery status reading, please check latest version of the patch or kernel package. Now reads as "0" for me, this must be the shutdown code that overwrites register completely, disabling battery detection bit in it.

 

@tkaiser

symlinking sysfs values may work as long as it's not affected by "fs.protected_symlinks" kernel setting.

 

 

protected_symlinks:

A long-standing class of security issues is the symlink-based
time-of-check-time-of-use race, most commonly seen in world-writable
directories like /tmp. The common method of exploitation of this flaw
is to cross privilege boundaries when following a given symlink (i.e. a
root process follows a symlink belonging to another user). For a likely
incomplete list of hundreds of examples across the years, please see:
http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp

When set to "0", symlink following behavior is unrestricted.

When set to "1" symlinks are permitted to be followed only when outside
a sticky world-writable directory, or when the uid of the symlink and
follower match, or when the directory owner matches the symlink's owner.

This protection is based on the restrictions in Openwall and grsecurity.

 

 

 

Edit:

If battery_voltage is very low then this is a sign AXP209 disabled the charger since available voltage is above 4.2V. In this case the start script could do a simple 'echo 5000000 > /var/run/armbianmonitor/battery_voltage' and normally a 'ln -s /sys/devices/platform/soc@01c00000/1c2ac00.i2c/i2c-0/0-0034/battery_voltage /var/run/armbianmonitor/battery_voltage' instead.

I already exposed "Charging indicator" (status_battery_charge_in_progress) to sysfs in newer version, if you are talking about this.

Link to comment
Share on other sites

symlinking sysfs values may work as long as it's not affected by "fs.protected_symlinks" kernel setting.

 

Do you think we'll change that in Armbian's default settings any time soon?

 

It would be really convenient to link all data sources to a standard set of files/symlinks below /var/run/armbianmonitor since the template stuff gets easier and we could also use the data sources for SNMP (to be used with OpenNMS, PRTG and so on).

 

BTW: internal_temp should be multiplied by 100. And I think I'll drive into the city and get a battery for one of the A20 boards now.

Link to comment
Share on other sites

Do you think we'll change that in Armbian's default settings any time soon?

We can do whatever we want, and BTW this may not be turned on by default in old Debian/Ubuntu releases or kernels. This also means that upgrade (especially release upgrade from Trusty to Xenial) may bring new version of /etc/sysctl.conf with different settings. It needs extra checking if & when it's enabled by default ("sudo sysctl fs.protected_symlinks") and if it will even affect "armbianmonitor".

 

 

BTW: internal_temp should be multiplied by 100. 

Quote from "power_supply.h" says that temperature should be in

tenths of degree Celsius unless otherwise stated

so should it be?

 

I'll try to finish new version that also reads battery gauge level (%) and coulomb counter (mAh), it still needs some refactoring to be done.

 

 

Refactoring certainly was a good idea if compiler throws at you 206 lines of error messages after it's done  :ph34r:

 

 

Link to comment
Share on other sites

Quote from "power_supply.h" says that temperature should be in

tenths of degree Celsius unless otherwise stated

so should it be?

 

Strange. Everywhere else (/sys/devices/virtual/thermal/thermal_zoneX/temp, or axp209 stuff for 3.4 kernel) it's done differently and you have to divide the value you get by 1000 to get real degree Celsius. I thought doing it this way would be more consistent to all the other thermal read-outs here and there.

Link to comment
Share on other sites

I'm surprised, but new version actually works. Sorry for little inconvenience, but directory structure inside "/sys/power/axp_pmu" changed a little bit, now all attributes belong to their "subsystem" subdirectory.

 

From other thread

BTW: The current values I got seemed a bit off. But I'll have a closer look into it later and will get back to you in the thread where it belongs to.

They are a bit off compared to what? Values read from old kernel? Multimeter readings?

Link to comment
Share on other sites

They are a bit off compared to what? Values read from old kernel? Multimeter readings?

 

The latter. RPi-Monitor showed me values between 1.16W when idle and 1.84W when running iozone or sysbench (both too low). But since this might be my mistake I'll double check later. BTW: I stumbled accross this an hour ago: https://github.com/ssvb/linux-sunxi/commit/c0a2252427800aad66fafc27951579e58d84fbf2

Link to comment
Share on other sites

I thought about this solution (constantly collecting and averaging data in driver itself), I may implement it later if needed.

 

What kernel / patch version did you test?

 

Cubietruck, ondemand 720MHz - 960MHz.

 

Idle:

➜  ~  % echo $(( $(cat /sys/power/axp_pmu/ac/amperage) / 1000 * $(cat /sys/power/axp_pmu/ac/voltage) / 1000 ))
1330503

Samba file transfer (first core ~100% load, second core ~90% load):

➜  ~  % echo $(( $(cat /sys/power/axp_pmu/ac/amperage) / 1000 * $(cat /sys/power/axp_pmu/ac/voltage) / 1000 ))
2559715
Link to comment
Share on other sites

Olimex Lime2, no peripherals except network, idle at 528 MHz:

root@lime2:~# echo $(( $(cat /sys/power/axp_pmu/ac/amperage) / 1000 * $(cat /sys/power/axp_pmu/ac/voltage) / 1000 ))
1177605

When running sysbench on both cores with 100% @ 960 MHz:

root@lime2:~# echo $(( $(cat /sys/power/axp_pmu/ac/amperage) / 1000 * $(cat /sys/power/axp_pmu/ac/voltage) / 1000 ))
1977066

(Powermeter showed 1.6/1.7W when idle and 2.7W when running sysbench. I'm using your 4.4.0 kernel with latest sysfs stuff (linux-image-dev-sunxi_4.83_armhf.deb).

 

Also interesting: When I connect my SATA SSD the consumption doesn't increase when read-out through sysfs. Also when I connect an USB-Ethernet dongle (Powermeter reports an increase in 0.8W from 1.7W to 2.5W).

 

Time to search for the Cubietruck and have a look again ;)

Link to comment
Share on other sites

I'm looking at Olimex Lime 2 schematics, hardware revision E.

 

Also interesting: When I connect my SATA SSD the consumption doesn't increase when read-out through sysfs.

SATA +5v power bypasses PMU current sensor here, at least when powered from AC In.

 

Also when I connect an USB-Ethernet dongle

USB power bypasses PMU current sensor too.

Link to comment
Share on other sites

I'm looking at Olimex Lime 2 schematics, hardware revision E.

 

SATA +5v power bypasses PMU current sensor here, at least when powered from AC In.

 

USB power bypasses PMU current sensor too.

 

'Great' ;( Then this whole power monitoring thing is a bit futile... at least when used together with a Lime2 when powered through DC-IN.

 

At least on the Lamobo R1 (where no schematics are publicly available  :wacko: ) it should work as expected and the total consumption of all connected devices will be reported. Since this is the device suffering from power issues the most it should be useful. And then it's time to start with a new article in the linux-sunxi wiki explaining the different AXP209 equipped devices regarding internal monitoring capabilities.

Link to comment
Share on other sites

Really, AXP209 is designed to be used mostly in smartphones and tablets, where you typically don't have SATA HDDs with high spin-up currents and extra USB host ports, and where typically main power source is battery.

Datasheet says it can pass through itself up to 2.5A, and most hardware developers wouldn't want to try to push the PMU to its limits. Well, technically you could use on of two unused GPIO-ADC inputs combined with like 0.1 Ohm resistor near AC in to get "full" current readouts (which would be relatively cheap solution, compared, for example, with Hall effect current sensor), but I don't think any SBC developer cares about this.

 

Power monitoring data can still be useful since it shows power consumption of SoC, memory and other internal hardware.

Link to comment
Share on other sites

Power monitoring data can still be useful since it shows power consumption of SoC, memory and other internal hardware.

 

Of course! And it's valuable to detect potential undervoltage situations. But it needs some documentation to adjust the expectations of naive people (like me for example  :P ).

Link to comment
Share on other sites

OK, I'll go through the code for the last time, maybe will give shorter names to some parameters.

It would be helpful to get feedback on values from battery/consumption, battery/capacity and battery/percentage parameters, if they output anything useful and if values look plausible enough.

To get "capacity" you probably will need to reset counters first:

echo "1" > /sys/power/axp_pmu/control/reset_coulomb_counter 

And then perform discharge-charge (or charge-discharge) cycle.

 

After that it should be safe enough to put this patch into armbian's build script patches directory.

Link to comment
Share on other sites

It would be helpful to get feedback on values from battery/consumption, battery/capacity and battery/percentage parameters, if they output anything useful and if values look plausible enough.

 

I failed to buy a battery here in Munich last week and hope that the one I ordered arrives before I leave for Montpellier (visiting my daughter :) ) In other words: I want to eagerly test your code but won't be able to do so within the next few days. Please be patient if no-one else provides feedback :)

Link to comment
Share on other sites

Slightly offtopic, but I wonder, I have more 18650 Li-Ion cells from dead laptop batteries than I know what to do with  :)

If I find the right connector in local electronic components shop (don't want to desolder stock connector from cubie), I may be able to test it too sometimes in the future  :)

 

Edit:

I've found needed connector and standalone 18650 charger (just to find cell in a good condition before connecting it to cubie). But buying 18650 battery holder will be a pain in the butt  :(

Link to comment
Share on other sites

@zador

I'll try to give some feedback on those changes later today.

 

In one case I am using one such battery and it's working just fine. The other which I use is salvaged from some tablet. No official batteries here ;)

Link to comment
Share on other sites

One small issue.

 

Charging / not charging seems not working ... When I unplug the power on fully charged battery, percentage drops to 98% which is somehow o.k. ... and when I do some stress tests it is going slowly down to 9x%. OK. When I put power back, there is no indication for charging ... but I can read out that AC is plugged.

Link to comment
Share on other sites

There are 2 "Charging" properties, one is supposed to tell battery current direction (I put it in "battery/charging", other - actual charging status ("charger/charge_in_progress"). I'll check datasheet later, but since it appears to be translated from Chinese (and at least partially - not by human), there may be some misunderstanding.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines