zador.blood.stained Posted January 14, 2016 Posted January 14, 2016 (edited) 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 February 22, 2016 by zador.blood.stained 1
tkaiser Posted January 14, 2016 Posted January 14, 2016 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!
tkaiser Posted January 15, 2016 Posted January 15, 2016 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)?
zador.blood.stained Posted January 15, 2016 Author Posted January 15, 2016 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.
tkaiser Posted January 15, 2016 Posted January 15, 2016 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
zador.blood.stained Posted January 15, 2016 Author Posted January 15, 2016 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
tkaiser Posted January 15, 2016 Posted January 15, 2016 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/
Igor Posted January 15, 2016 Posted January 15, 2016 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.
zador.blood.stained Posted January 15, 2016 Author Posted January 15, 2016 @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.
Igor Posted January 15, 2016 Posted January 15, 2016 Yep, it works properly. Now we only need a patch for legacy and we can rely on this parameter
tkaiser Posted January 16, 2016 Posted January 16, 2016 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.
zador.blood.stained Posted January 16, 2016 Author Posted January 16, 2016 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
tkaiser Posted January 16, 2016 Posted January 16, 2016 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.
zador.blood.stained Posted January 16, 2016 Author Posted January 16, 2016 It's probably related to different device class ("power supply" vs "sensor" or "hwmon"). I'll add multiplier in the next version for the sake of consistency. 1
tkaiser Posted January 16, 2016 Posted January 16, 2016 I'll add multiplier in the next version for the sake of consistency. Thx, I just had a look into the way thermal values are dealt with SNMP. Also the same: http://www.net-snmp.org/wiki/index.php/Net-SNMP_and_lm-sensors_on_Ubuntu_10.04#Additional_SNMP_Commands (containing a nice bug interpreting negative values ;-)
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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?
tkaiser Posted January 17, 2016 Posted January 17, 2016 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 1
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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
tkaiser Posted January 17, 2016 Posted January 17, 2016 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
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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.
tkaiser Posted January 17, 2016 Posted January 17, 2016 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 ) 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.
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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.
tkaiser Posted January 17, 2016 Posted January 17, 2016 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 ).
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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.
tkaiser Posted January 17, 2016 Posted January 17, 2016 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
zador.blood.stained Posted January 17, 2016 Author Posted January 17, 2016 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
Igor Posted January 18, 2016 Posted January 18, 2016 @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
Igor Posted January 19, 2016 Posted January 19, 2016 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. 1
zador.blood.stained Posted January 19, 2016 Author Posted January 19, 2016 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.
Igor Posted January 19, 2016 Posted January 19, 2016 OK Leave as is, it's working good enough. I'll put patch inside and we can get back later if there will be some other / more serious issues.
Recommended Posts