Optimize AXP2101 PMU

This commit is contained in:
916BGAI
2024-09-04 11:38:11 +08:00
parent cde77bdacb
commit d116757f47
5 changed files with 214 additions and 110 deletions

View File

@@ -0,0 +1,31 @@
#!/bin/sh
if ! command -v i2cget &> /dev/null
then
echo "i2cdetect not find, please install i2c-tools"
exit 1
fi
pmu_version=$(i2cget -y 4 0x34 0x03)
pmu_version=$((pmu_version & 0xCF))
chip_id_1=$(printf "%d" 0x47)
chip_id_2=$(printf "%d" 0x4a)
if [ "$pmu_version" -eq "$chip_id_1" ] || [ "$pmu_version" -eq "$chip_id_2" ]; then
case "$1" in
start)
exec /usr/bin/axp2101
echo "Starting PMU: OK\n"
;;
stop)
runlevel=$(cat /run/runlevel | awk '{ print $1 }')
if [ "$runlevel" = "0" ]; then
printf "Stopping PMU\n"
value=$(i2cget -y 4 0x34 0x10)
value=$((value | 0x01))
i2cset -y 4 0x34 0x10 $value
fi
;;
esac
fi

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
panel_value=$(grep '^panel=' /boot/uEnv.txt | cut -d '=' -f 2)
if [ "$panel_value" = "MaixCam_Pro" ]
then
echo "init axp2101 pmu"
exec /usr/bin/axp2101
fi
exit 0
fi

View File

@@ -330,12 +330,12 @@ public:
return getRegisterBit(XPOWERS_AXP2101_STATUS2, 3) == 0 && isVbusGood();
}
xpowers_chg_status_t getChargerStatus(void)
uint8_t getChargerStatus(void)
{
int val = readRegister(XPOWERS_AXP2101_STATUS2);
if (val == -1)return XPOWERS_AXP2101_CHG_STOP_STATE;
val &= 0x07;
return (xpowers_chg_status_t)val;
return (uint8_t)val;
}
/*
@@ -472,12 +472,12 @@ public:
}
// Linear Charger Vsys voltage dpm
void setLinearChargerVsysDpm(xpower_chg_dpm_t opt)
void setLinearChargerVsysDpm(uint8_t opt)
{
int val = readRegister(XPOWERS_AXP2101_MIN_SYS_VOL_CTRL);
if (val == -1)return;
val &= 0x8F;
writeRegister(XPOWERS_AXP2101_MIN_SYS_VOL_CTRL, val | (opt << 4));
writeRegister(XPOWERS_AXP2101_MIN_SYS_VOL_CTRL, opt);
}
uint8_t getLinearChargerVsysDpm(void)
@@ -490,12 +490,12 @@ public:
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
void setVbusVoltageLimit(xpower_vbus_vol_limit_t opt)
bool setVbusVoltageLimit(uint8_t opt)
{
int val = readRegister(XPOWERS_AXP2101_INPUT_VOL_LIMIT_CTRL);
if (val == -1)return;
if (val == -1)return false;
val &= 0xF0;
writeRegister(XPOWERS_AXP2101_INPUT_VOL_LIMIT_CTRL, val | (opt & 0x0F));
return 0 == writeRegister(XPOWERS_AXP2101_INPUT_VOL_LIMIT_CTRL, val | (opt & 0x0F));
}
uint8_t getVbusVoltageLimit(void)
@@ -2357,8 +2357,8 @@ public:
int val;
switch (mode) {
case XPOWERS_CHG_LED_OFF:
// clrRegisterBit(XPOWERS_AXP2101_CHGLED_SET_CTRL, 0);
// break;
clrRegisterBit(XPOWERS_AXP2101_CHGLED_SET_CTRL, 0);
break;
case XPOWERS_CHG_LED_BLINK_1HZ:
case XPOWERS_CHG_LED_BLINK_4HZ:
case XPOWERS_CHG_LED_ON:
@@ -2399,7 +2399,7 @@ public:
* @param opt: 25 * opt
* @retval None
*/
void setPrechargeCurr(xpowers_prechg_t opt)
void setPrechargeCurr(uint8_t opt)
{
int val = readRegister(XPOWERS_AXP2101_IPRECHG_SET);
if (val == -1)return;
@@ -2443,7 +2443,7 @@ public:
* @note Charging termination of current limit
* @retval
*/
void setChargerTerminationCurr(xpowers_axp2101_chg_iterm_t opt)
void setChargerTerminationCurr(uint8_t opt)
{
int val = readRegister(XPOWERS_AXP2101_ITERM_CHG_SET_CTRL);
if (val == -1)return;

View File

@@ -300,6 +300,23 @@ public:
*/
virtual bool isChannelAvailable(uint8_t channel);
virtual void setPrechargeCurr(uint8_t opt) = 0;
virtual void disableChargerTerminationLimit(void) = 0;
virtual bool setVbusVoltageLimit(uint8_t opt) = 0;
virtual uint8_t getVbusVoltageLimit(void) = 0;
virtual bool isStandby(void) = 0;
virtual bool isVbusGood(void) = 0;
virtual uint8_t getChargerStatus(void) = 0;
virtual void enableCellbatteryCharge(void) = 0;
virtual void enableGauge(void) = 0;
virtual void disableGauge(void) = 0;
virtual void setLinearChargerVsysDpm(uint8_t opt) = 0;
virtual void disablePwronShutPMIC(void) = 0;
virtual void fuelGaugeControl(bool writeROM, bool enable) = 0;
virtual void printIntRegister() = 0;
//battery
/**
@@ -421,7 +438,6 @@ public:
*/
virtual uint64_t getIrqStatus() = 0;
/**
* @brief Clear interrupt controller state.
*/
@@ -597,8 +613,9 @@ public:
* parameters in "XPowersParams.hpp"
*/
virtual void setChargingLedMode(uint8_t mode) = 0;
virtual void setChargerTerminationCurr(uint8_t opt) = 0;
virtual void disableDieOverTempDetect(void) = 0;
virtual void resetGauge(void) = 0;
// PMU PEKEY settings
/**

View File

@@ -1,5 +1,4 @@
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
@@ -8,6 +7,8 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include <poll.h>
#include <iostream>
#include <string>
#include "XPowersLib.h"
#define I2C_BUS (4)
@@ -26,7 +27,7 @@ static int open_i2c_bus(int bus)
snprintf(filename, 19, "/dev/i2c-%d", bus);
int file = open(filename, O_RDWR);
if (file < 0) {
perror("Failed to open the i2c bus");
perror("PMU: Failed to open the i2c bus");
}
return file;
}
@@ -34,7 +35,7 @@ static int open_i2c_bus(int bus)
static int set_i2c_slave(int file, int addr)
{
if (ioctl(file, I2C_SLAVE, addr) < 0) {
perror("Failed to acquire bus access and/or talk to slave");
perror("PMU: Failed to acquire bus access and/or talk to slave");
return -1;
}
return 0;
@@ -42,39 +43,128 @@ static int set_i2c_slave(int file, int addr)
int main(int argc, char* argv[])
{
printf("Init axp2101 pmu\n");
bool log_enabled = false;
printf("PMU: Init axp2101 pmu\n");
i2c_dev = open_i2c_bus(I2C_BUS);
if (i2c_dev < 0) {
printf("open i2c bus error\n");
printf("PMU: Open i2c bus error\n");
return -1;
} else {
printf("open i2c bus success\n");
printf("PMU: Open i2c bus success\n");
}
if (set_i2c_slave(i2c_dev, AXP2101_SLAVE_ADDRESS) < 0) {
close(i2c_dev);
printf("set i2c slave error\n");
printf("PMU: Set i2c slave error\n");
return 1;
} else {
printf("set i2c slave success\n");
printf("PMU: Set i2c slave success\n");
}
if (!PMU) {
if (ioctl(i2c_dev, I2C_SLAVE, AXP2101_SLAVE_ADDRESS) < 0) {
printf("Failed to access bus.\n");
printf("PMU: Failed to access bus.\n");
exit(1);
}
PMU = new XPowersAXP2101(AXP2101_SLAVE_ADDRESS, linux_i2c_read_callback, linux_i2c_write_callback);
if (!PMU->init()) {
printf("Warning: Failed to find AXP2101 power management\n");
printf("PMU: Failed to find AXP2101 power management\n");
delete PMU;
PMU = NULL;
} else {
printf("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
printf("PMU: AXP2101 PMU init succeeded, using AXP2101 PMU\n");
}
}
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--log" || arg == "-l") {
log_enabled = true;
break;
}
}
if (log_enabled) {
std::cout << "=======================================================================\n";
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
std::cout << "DC1 : " << (PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DCDC1) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
std::cout << "DC2 : " << (PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DCDC2) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
std::cout << "DC3 : " << (PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DCDC3) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
std::cout << "DC4 : " << (PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DCDC4) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DCDC5)) {
std::cout << "DC5 : " << (PMU->isPowerChannelEnable(XPOWERS_DCDC5) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DCDC5) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
std::cout << "ALDO1: " << (PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_ALDO1) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
std::cout << "ALDO2: " << (PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_ALDO2) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
std::cout << "ALDO3: " << (PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_ALDO3) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
std::cout << "ALDO4: " << (PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_ALDO4) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
std::cout << "BLDO1: " << (PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_BLDO1) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
std::cout << "BLDO2: " << (PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_BLDO2) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DLDO1)) {
std::cout << "DLDO1: " << (PMU->isPowerChannelEnable(XPOWERS_DLDO1) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DLDO1) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_DLDO2)) {
std::cout << "DLDO2: " << (PMU->isPowerChannelEnable(XPOWERS_DLDO2) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_DLDO2) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_CPULDO)) {
std::cout << "CPUSLDO: " << (PMU->isPowerChannelEnable(XPOWERS_CPULDO) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_CPULDO) << " mV \n";
}
if (PMU->isChannelAvailable(XPOWERS_VBACKUP)) {
std::cout << "VBACKUP: " << (PMU->isPowerChannelEnable(XPOWERS_VBACKUP) ? "+" : "-")
<< " Voltage:" << PMU->getPowerChannelVoltage(XPOWERS_VBACKUP) << " mV \n";
}
std::cout << "=======================================================================\n";
printPMU();
if (PMU != nullptr) {
delete PMU;
PMU = NULL;
}
return 0;
}
PMU->setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_3V88);
PMU->setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_2000MA);
PMU->setSysPowerDownVoltage(2600);
// DCDC1 --> VDD3V3_SYS
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC1);
@@ -87,12 +177,11 @@ int main(int argc, char* argv[])
PMU->enablePowerOutput(XPOWERS_DCDC3);
// DCDC4 --> VDD1V35_DRAM
PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 1340);
PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 1400);
PMU->enablePowerOutput(XPOWERS_DCDC4);
// DCDC5 --> DCDC5_FB
PMU->setPowerChannelVoltage(XPOWERS_DCDC5, 1200);
PMU->enablePowerOutput(XPOWERS_DCDC5);
// DCDC5 --> Disable
PMU->disablePowerOutput(XPOWERS_DCDC5);
// ALDO1 --> VDD1V8_SYS
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 1800);
@@ -118,71 +207,34 @@ int main(int argc, char* argv[])
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3100);
PMU->enablePowerOutput(XPOWERS_VBACKUP);
printf("=======He================================================================\n");
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
printf("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
printf("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
printf("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
printf("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC5)) {
printf("DC5 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC5) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC5));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
printf("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
printf("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
printf("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
printf("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
printf("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
printf("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
printf("DLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DLDO1));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
printf("DLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DLDO2));
}
if (PMU->isChannelAvailable(XPOWERS_CPULDO)) {
printf("CPUSLDO: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_CPULDO) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_CPULDO));
}
if (PMU->isChannelAvailable(XPOWERS_VBACKUP)) {
printf("VBACKUP: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_VBACKUP) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_VBACKUP));
}
printf("=======================================================================\n");
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
PMU->clearIrqStatus();
PMU->setLinearChargerVsysDpm(XPOWERS_AXP2101_VSYS_VOL_4V8);
PMU->setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA);
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_1000MA);
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
PMU->setSysPowerDownVoltage(2600);
PMU->setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_1500MA);
PMU->disableChargerTerminationLimit();
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
PMU->enableCellbatteryCharge();
// Set the time of pressing the button to turn off
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
// Set the button power-on press time
PMU->setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
PMU->disableTSPinMeasure();
PMU->enableBattDetection();
PMU->enableVbusVoltageMeasure();
PMU->enableBattVoltageMeasure();
PMU->enableSystemVoltageMeasure();
PMU->enableBattDetection();
// printPMU();
PMU -> fuelGaugeControl(true, true);
if (PMU != nullptr) {
delete PMU;
PMU = NULL;
}
return 0;
}
@@ -221,21 +273,38 @@ static int linux_i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *d
return 0;
}
void printPMU()
{
printf("isCharging:%s\n", PMU->isCharging() ? "YES" : "NO");
printf("isDischarge:%s\n", PMU->isDischarge() ? "YES" : "NO");
printf("isVbusIn:%s\n", PMU->isVbusIn() ? "YES" : "NO");
printf("getBattVoltage:%u mV\n", PMU->getBattVoltage());
printf("getVbusVoltage:%u mV\n", PMU->getVbusVoltage());
printf("getSystemVoltage:%u mV\n", PMU->getSystemVoltage());
void printPMU() {
std::cout << "---------------------------------------------------------------------------------------------------------\n";
std::cout << "CHARG DISC STBY VBUSIN VGOOD VBAT VBUS VSYS Percentage CHG_STATUS\n";
std::cout << "(bool) (bool) (bool) (bool) (bool) (mV) (mV) (mV) (%%) (str) \n";
std::cout << "---------------------------------------------------------------------------------------------------------\n";
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (PMU->isBatteryConnect()) {
printf("getBatteryPercent:%d%%", PMU->getBatteryPercent());
std::cout << (PMU->isCharging() ? "YES" : "NO ") << "\t";
std::cout << (PMU->isDischarge() ? "YES" : "NO ") << "\t";
std::cout << (PMU->isStandby() ? "YES" : "NO ") << "\t";
std::cout << (PMU->isVbusIn() ? "YES" : "NO ") << "\t";
std::cout << (PMU->isVbusGood() ? "YES" : "NO ") << "\t";
std::cout << PMU->getBattVoltage() << "\t";
std::cout << PMU->getVbusVoltage() << "\t";
std::cout << PMU->getSystemVoltage() << "\t";
std::cout << PMU->getBatteryPercent() << "%\t";
uint8_t charge_status = PMU->getChargerStatus();
if (charge_status == XPOWERS_AXP2101_CHG_TRI_STATE) {
std::cout << "tri_charge";
} else if (charge_status == XPOWERS_AXP2101_CHG_PRE_STATE) {
std::cout << "pre_charge";
} else if (charge_status == XPOWERS_AXP2101_CHG_CC_STATE) {
std::cout << "constant charge(CC)";
} else if (charge_status == XPOWERS_AXP2101_CHG_CV_STATE) {
std::cout << "constant voltage(CV)";
} else if (charge_status == XPOWERS_AXP2101_CHG_DONE_STATE) {
std::cout << "charge done";
} else if (charge_status == XPOWERS_AXP2101_CHG_STOP_STATE) {
std::cout << "not charging";
}
printf("\n");
std::cout << "\n";
}