PaddleStroke Posted July 4, 2019 Posted July 4, 2019 I found relatively little information concerning AXP209 support on mainline. My targets : - set the battery as 4.35V instead of 4.2V. Datasheet say it's set in REG 33H. Defaut value for register : 0xCX, X being the charge current. if 1200mAh then default value is 0xC9. To change from 4.2 to 4.35V, use EXh (so E9h if you'r using 1200mA) 11001001 to 11101001.)- Remove boot when AC plugged in and boot only when PEK is pressed. Datasheet say it's possible is not clear about how to do it. It may be reg40 bit6. I could not test yet as REG40 strangely reads 0x00 with i2cget.- Set GPIO0 and GPIO1 as ADC. GPIO0 function is REG 90H (see page 40 datasheet). GPIO1 function is REG 92H. Defaut value for both registers : 0x07 (=0000 0111 bin) where bit 0-2 (111) are the function. We need replace with 100 bin for ADC function so 04h Also need to enable GPIO ADC in REG 83H bit 2-3 too ! Default value 80H 1000 0000 replace with 8C 1000 1100. First look : There are several topics about AXP209 management. However there are different different things and some look deprecated... - Some people have been changing the REG values directly with i2Cset. - A Sysfs interface have been developped. But it's not clear whether it's deprecated or not. - Apparantly there are "proper drivers" that have been added. But no mention of them anywhere. Nor how to use them to change things or get battery% or anything. In this topic for example : Where @zador.blood.stained you say : Quote Main purpose of this patch is creating a sysfs interface to get information from AXP202/209 PMU until proper power driver is implemented in mainline kernel. At the time it was created it was the simplest way to get data from the PMIC or change some settings without using userspace tools like i2cget/i2cset or a custom code based on i2c libraries. Newer kernels have received proper drivers - starting with 4.12 there is even a battery driver and an ADC IIO driver, but this patch still can be useful i.e. to enable/disable RTC battery changing on some boards. Are you talking about this patch ? (Which is the one from your github? https://github.com/zador-blood-stained/axp209-sysfs-interface ) If so this patch is deprecated right? If yes then where are the proper drivers you are talking about and how to use them to get current battery voltage, capacity%...? Thanks
PaddleStroke Posted July 14, 2019 Author Posted July 14, 2019 I have been trying to do my own scrip to read/write directly reg values with i2C. But changing parameters with i2Cset are overwriten after reboot, probably by the current driver... i2cset -y -f 0 0x34 0x33 0xE9 This should change to 4.36V. This setting get reseted to 0xC9 but only when the unit boot on AC connection. Booting on PEK press does not reset it. Very strange. i2cset -y -f 0 0x34 0x83 0x8C This setting does not get reset! i2cset -y -f 0 0x34 0x90 0x04 i2cset -y -f 0 0x34 0x92 0x04 Those two should set the GPIO 0 and 1 functions as ADC. Those don't work they keep reseting to 0x02 after any reboot (AC plugged in boot or PEK press boot)... i2cget -y -f 0 0x34 0x40 This REG 40 should be a list of IRQ enabled. Someone suggested bit 6 to be the boot when AC plugged-in parameter. But very strangely the reg40 reads 0x00 instead of normal default value of 0xD8... Same for other IRQ REGs 41 and 42. So this means the AXP209 driver is messing things up for us..!
PaddleStroke Posted July 16, 2019 Author Posted July 16, 2019 I found several files about AXP on the torvalds github. Note: Megeous github (torvalds fork which is used for Armbian build if I am not mistaken) files are slightly different... So the main driver seems to be this one: https://github.com/torvalds/linux/blob/master/drivers/mfd/axp20x.c https://github.com/torvalds/linux/blob/master/include/linux/mfd/axp20x.h https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/mfd/axp20x.txt Then there are several complementary-drivers : https://github.com/torvalds/linux/blob/master/drivers/input/misc/axp20x-pek.c https://github.com/torvalds/linux/blob/master/drivers/mfd/axp20x-i2c.c https://github.com/torvalds/linux/blob/master/drivers/regulator/axp20x-regulator.c https://github.com/torvalds/linux/blob/master/drivers/iio/adc/axp20x_adc.c https://github.com/torvalds/linux/blob/master/drivers/power/supply/axp20x_battery.c https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt https://github.com/torvalds/linux/blob/master/drivers/pinctrl/pinctrl-axp209.c https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/gpio/gpio-axp209.txt Not 100% sure if these last c and txt files are related as there is no gpio-axp209.c nor pinctrl-axp209.txt so I think it's just naming issue. Then on top of that you have a armbian patch of the main axp20X.c : https://github.com/armbian/build/blob/master/patch/kernel/sunxi-next/general-axp20x-sysfs-interface.patch Or this one seems related but not sure it's included: https://github.com/QSchulz/linux/commit/aa13f8990a2482e951f72d5c70c2f4cedf2684c6#diff-dfdc0dfa3d0d84a7e9a84c9baa75b869
PaddleStroke Posted July 17, 2019 Author Posted July 17, 2019 I found a problem with either armbian patch for AXP20X.c driver or with i2Cset too. Running : sudo i2cset -y -f 0 0x34 0x33 0xe9 #0x33 is AXP20X_CHRG_CTRL1. Value read with i2cget before is 0xc9 sudo i2cset -y -f 0 0x34 0x90 0x04 #0x90 is AXP20X_GPIO0_CTRL. Value read with i2cget before is is 0x02 sudo i2cset -y -f 0 0x34 0x92 0x04 #0x92 is AXP20X_GPIO1_CTRL. Value read with i2cget before is is 0x02 Change the register values correctly. Then on reboot we have : sudo i2cget -y -f 0 0x34 0x33 0xe9 sudo i2cget -y -f 0 0x34 0x90 0x02 sudo i2cget -y -f 0 0x34 0x92 0x02 0x90 and 0x92 reseted (0x33 reset only when booting when AC-plugged in power. Not when PEK pressed...). I check Dmesg and find one difference compared to normal boot without modifications: axp20x-i2c 0-0034: Battery detection is disabled, enabling So I check the armbian patch of AXP20X.c and find this error message in this part of the code : + /* Enable battery detection */ + ret = regmap_read(axp->regmap, AXP20X_OFF_CTRL, &res); + if (ret == 0) { + if ((res & 0x40) != 0x40) { + dev_info(axp->dev, "Battery detection is disabled, enabling"); + ret = regmap_update_bits(axp->regmap, AXP20X_OFF_CTRL, 0x40, 0x40); + if (ret) + dev_warn(axp->dev, "Unable to enable battery detection: %d", ret); + } + } else + dev_warn(axp->dev, "Unable to read register AXP20X_OFF_CTRL: %d", ret); interestingly the error is triggered after reading AXP20X_OFF_CTRL ( Reg 0x32)... Which is not one that I have been modifying?? I am not sure to understand what is going on there: - Either the i2Cset/I2Cget tool is not working properly. - Either something is wrong in the patch. But it looks correct as it uses AXP20X_OFF_CTRL which is 0x32 and change only bit 6 to 1. - Either something is wrong with regmap?
PaddleStroke Posted July 17, 2019 Author Posted July 17, 2019 After few more test I can say that reg 33 (the one for max voltage) get reset when you boot on AC connection. Not when you boot on PEK pressed. Why? No ideas yet. Dmesg don't give any hint.
PaddleStroke Posted July 18, 2019 Author Posted July 18, 2019 GPIO-AXP209.c Ok there's a page in bindings about this driver : https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/gpio/gpio-axp209.txt There's even a armbian patch about this driver binding text : https://github.com/armbian/build/blob/master/patch/kernel/sunxi-next/0104-dt-bindings-gpio-gpio-axp209-add-AXP803-GPIO-binding.patch but the driver itself cannot be found on github... maybe it's name changed to this one : https://github.com/torvalds/linux/blob/master/drivers/pinctrl/pinctrl-axp209.c if so why is there still a gpio-axp209.txt and a patch for this.
PaddleStroke Posted July 18, 2019 Author Posted July 18, 2019 I found the reason why IRQ REG show 00 and why GPIO keep reseting... It's the u-boot driver for AXP209: https://gitlab.denx.de/u-boot/u-boot/blob/master/drivers/power/axp209.c https://gitlab.denx.de/u-boot/u-boot/blob/master/include/axp209.h This files is giving me 2/3 of my troubles : /* Mask all interrupts */ for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) { rc = pmic_bus_write(i, 0); if (rc) return rc; } This is why REG 40 is 00... /* * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting * from android these are sometimes on. */ rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT); if (rc) return rc; rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT); if (rc) return rc; rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT); if (rc) return rc; Reset the 3 GPIO status... Only the battery voltage error does not come from this. I think it probably comes from : https://github.com/torvalds/linux/blob/master/drivers/power/supply/axp20x_battery.c However I am not sure how the driver is getting executed. What is the calling sequence of it.
PaddleStroke Posted July 18, 2019 Author Posted July 18, 2019 Also the uboot driver has a problem I think : int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF); /* infinite loop during shutdown */ while (1) {} /* not reached */ return 0; } #define AXP209_POWEROFF BIT(7) AXP209_SHUTDOWN = 0x32 So actually on every power off, uboot write BIT(7) to REG 32. Now I understand why at boot the kernel AXP20x driver triggers to set battery detection ON as it's also on REG32. It does not use mask to write only bit 7, so I guess it writes 1000 0000 to the REG... I think it should use "pmic_bus_setbits" instead of "pmic_bus_write" what do you think? If someone can confirm this.
Tido Posted July 18, 2019 Posted July 18, 2019 @PaddleStroke , thank you for updating the original post so we understand your intention. Based on your findings, does it make sense to add some of it here: http://linux-sunxi.org/AXP209 ?
PaddleStroke Posted July 18, 2019 Author Posted July 18, 2019 Yes you are right. I'll finish to understand everything before adding anything though. Btw do you know how to make a bug report to u-boot?
Tido Posted July 18, 2019 Posted July 18, 2019 51 minutes ago, PaddleStroke said: to make a bug report to u-boot? I guess others are far superior to answer that, but what about this: Note: This could also be used as a Bug Tracking System, but there are no bugs in U-Boot, just Features™, right? https://www.denx.de/wiki/U-Boot/PatchTracking
martinayotte Posted July 18, 2019 Posted July 18, 2019 1 hour ago, PaddleStroke said: Btw do you know how to make a bug report to u-boot? There is also a ML for U-Boot, could be interesting to see what others devs will say about the issue you've found ...
PaddleStroke Posted July 18, 2019 Author Posted July 18, 2019 I tried to write to u-boot-patches@bugs.denx.de but got a automatic reply saying address is NOK.
martinayotte Posted July 18, 2019 Posted July 18, 2019 10 minutes ago, PaddleStroke said: I tried to write to u-boot-patches@bugs.denx.de but got a automatic reply saying address is NOK. You need to subscribe here : https://lists.denx.de/listinfo/u-boot Then, you can post here : u-boot@lists.denx.de
jernej Posted July 18, 2019 Posted July 18, 2019 1 hour ago, PaddleStroke said: Btw do you know how to make a bug report to u-boot? Proper way is to send e-mail directly to all parties involved - author of that piece of the code, patch committer (these two can be found in signed-off tags), maintainer(s) of that subsystem and U-Boot mailing list ("scripts/get_maintainer.pl drivers/power/axp209.c" for last two). While you can send patches to U-Boot ML (the one that Martin mentioned), you should register. Otherwise it will be moderated and delayed.
PaddleStroke Posted July 19, 2019 Author Posted July 19, 2019 Regarding the uboot error I discussed before. Actually the kernel driver is doing exactly the same thing : https://github.com/torvalds/linux/blob/master/drivers/mfd/axp20x.c static void axp20x_power_off(void) { if (axp20x_pm_power_off->variant == AXP288_ID) return; regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); /* Give capacitors etc. time to drain to avoid kernel panic msg. */ msleep(500); } AXP20X_OFF = bit(7) So it does the same thing. On shutdown it writes bit(7) on reg32. The problem is when you boot after on PEK press, the AXP regs are not reset. So the reg32 is not set back to default value but keep instead bit(7). Which makes that battery detection is disabled. Should be replaced by static void axp20x_power_off(void) { if (axp20x_pm_power_off->variant == AXP288_ID) return; regmap_update_bits(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, AXP20X_OFF, AXP20X_OFF); /* Give capacitors etc. time to drain to avoid kernel panic msg. */ msleep(500); } What do you think?
Recommended Posts