From 2d891439623bb76d38b98202ca5f3eea3c01c5f0 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 5 Dec 2021 14:30:03 +0000 Subject: AXP PMU rewrite (again) I noticed a few mistakes in the old driver code and it was in need of an overhaul anyway... I decided to scale things back, simplify the code and remove most of the debug menus, netting a nice code size savings. One new feature is an advanced debug menu which is accessible by recompiling the code with AXP_EXTRA_DEBUG. It adds quite a bit of code size and isn't useful other than for development so it must be manually enabled by editing the source. Change-Id: I30e17c1194c14823decd726a574ed14451d4cb2d --- .../ingenic_x1000/erosqnative/button-erosqnative.c | 10 ++-- .../ingenic_x1000/erosqnative/power-erosqnative.c | 60 ++++++++++++---------- .../mips/ingenic_x1000/fiiom3k/button-fiiom3k.c | 8 +-- .../mips/ingenic_x1000/fiiom3k/power-fiiom3k.c | 59 +++++++++++---------- .../ingenic_x1000/shanlingq1/button-shanlingq1.c | 8 +-- .../ingenic_x1000/shanlingq1/power-shanlingq1.c | 49 +++++++++++------- 6 files changed, 110 insertions(+), 84 deletions(-) (limited to 'firmware/target') diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c index 1583db175a..64041795a3 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c @@ -24,7 +24,7 @@ #include "backlight.h" #include "powermgmt.h" #include "panic.h" -#include "axp-pmu.h" +#include "axp192.h" #include "gpio-x1000.h" #include "irq-x1000.h" #include "i2c-x1000.h" @@ -89,7 +89,7 @@ static int hp_detect_tmo_cb(struct timeout* tmo) static void hp_detect_init(void) { static struct timeout tmo; - static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; + static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1; static i2c_descriptor desc = { .slave_addr = AXP_PMU_ADDR, .bus_cond = I2C_START | I2C_STOP, @@ -105,11 +105,11 @@ static void hp_detect_init(void) /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1, * set them to inputs. */ - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */ - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */ + axp_set_gpio_function(0, AXP_GPIO_INPUT); /* HP detect */ + axp_set_gpio_function(1, AXP_GPIO_INPUT); /* LO detect */ /* Get an initial reading before startup */ - int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); + int r = axp_read(gpio_reg); if(r >= 0) { hp_detect_reg = r; diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c index a1a4d2c2b2..17cdb4d645 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c @@ -28,7 +28,7 @@ #ifdef HAVE_USB_CHARGING_ENABLE # include "usb_core.h" #endif -#include "axp-pmu.h" +#include "axp192.h" #include "i2c-x1000.h" const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = @@ -56,27 +56,30 @@ const unsigned short percent_to_volt_charge[11] = void power_init(void) { - /* Initialize driver */ - i2c_x1000_set_freq(2, I2C_FREQ_400K); - axp_init(); - - /* Set lowest sample rate */ - axp_adc_set_rate(AXP_ADC_RATE_25HZ); - - /* Ensure battery voltage ADC is enabled */ - int bits = axp_adc_get_enabled(); - bits |= (1 << ADC_BATTERY_VOLTAGE); - axp_adc_set_enabled(bits); - - /* Turn on all power outputs */ - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); - - /* Set the default charging current. This is the same as the - * OF's setting, although it's not strictly within the USB spec. */ - axp_set_charge_current(780); + /* Configure I2C bus */ + i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K); + + /* FIXME: Copy paste from M3K. Probably not necessary */ + axp_modify(AXP_REG_DCDCMODE, 0, 0xc0); + + /* Power on required supplies */ + axp_set_enabled_supplies( + (1 << AXP_SUPPLY_EXTEN) | + (1 << AXP_SUPPLY_DCDC1) | + (1 << AXP_SUPPLY_DCDC2) | + (1 << AXP_SUPPLY_DCDC3) | + (1 << AXP_SUPPLY_LDO2) | + (1 << AXP_SUPPLY_LDO3)); + + /* Enable required ADCs */ + axp_set_enabled_adcs( + (1 << AXP_ADC_BATTERY_VOLTAGE) | + (1 << AXP_ADC_CHARGE_CURRENT) | + (1 << AXP_ADC_DISCHARGE_CURRENT) | + (1 << AXP_ADC_VBUS_VOLTAGE) | + (1 << AXP_ADC_VBUS_CURRENT) | + (1 << AXP_ADC_INTERNAL_TEMP) | + (1 << AXP_ADC_APS_VOLTAGE)); /* Delay to give power outputs time to stabilize. * With the power thread delay, this can apparently go as low as 50, @@ -104,20 +107,25 @@ void power_off(void) bool charging_state(void) { - return axp_battery_status() == AXP_BATT_CHARGING; + return axp_is_charging(); +} + +unsigned int power_input_status(void) +{ + return axp_power_input_status(); } int _battery_voltage(void) { - return axp_adc_read(ADC_BATTERY_VOLTAGE); + return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE); } #if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE int _battery_current(void) { if(charging_state()) - return axp_adc_read(ADC_CHARGE_CURRENT); + return axp_read_adc(AXP_ADC_CHARGE_CURRENT); else - return axp_adc_read(ADC_DISCHARGE_CURRENT); + return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT); } #endif diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c index 24daf2ef69..0ef7bd2f64 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c @@ -24,7 +24,7 @@ #include "backlight.h" #include "powermgmt.h" #include "panic.h" -#include "axp-pmu.h" +#include "axp192.h" #include "ft6x06.h" #include "gpio-x1000.h" #include "irq-x1000.h" @@ -393,7 +393,7 @@ static int hp_detect_tmo_cb(struct timeout* tmo) static void hp_detect_init(void) { static struct timeout tmo; - static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; + static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1; static i2c_descriptor desc = { .slave_addr = AXP_PMU_ADDR, .bus_cond = I2C_START | I2C_STOP, @@ -408,10 +408,10 @@ static void hp_detect_init(void) }; /* Headphone detect is wired to AXP192 GPIO: set it to input state */ - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO2FUNCTION, 0x01); + axp_set_gpio_function(2, AXP_GPIO_INPUT); /* Get an initial reading before startup */ - int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); + int r = axp_read(gpio_reg); if(r >= 0) hp_detect_reg = r; diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c index 2d28ad0975..53451ffa6c 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c @@ -26,7 +26,7 @@ #ifdef HAVE_USB_CHARGING_ENABLE # include "usb_core.h" #endif -#include "axp-pmu.h" +#include "axp192.h" #include "i2c-x1000.h" const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = @@ -54,27 +54,29 @@ const unsigned short percent_to_volt_charge[11] = void power_init(void) { - /* Initialize driver */ - i2c_x1000_set_freq(2, I2C_FREQ_400K); - axp_init(); - - /* Set lowest sample rate */ - axp_adc_set_rate(AXP_ADC_RATE_25HZ); - - /* Ensure battery voltage ADC is enabled */ - int bits = axp_adc_get_enabled(); - bits |= (1 << ADC_BATTERY_VOLTAGE); - axp_adc_set_enabled(bits); - - /* Turn on all power outputs */ - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); - - /* Set the default charging current. This is the same as the - * OF's setting, although it's not strictly within the USB spec. */ - axp_set_charge_current(780); + /* Configure I2C bus */ + i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K); + + /* Set DCDC1 and DCDC2 to fixed PWM mode to match OF settings. */ + axp_modify(AXP_REG_DCDCMODE, 0, 0x0c); + + /* Power on required supplies */ + axp_set_enabled_supplies( + (1 << AXP_SUPPLY_DCDC1) | /* not sure (3.3 V) */ + (1 << AXP_SUPPLY_DCDC2) | /* not sure (1.4 V) */ + (1 << AXP_SUPPLY_DCDC3) | /* for CPU (1.8 V) */ + (1 << AXP_SUPPLY_LDO2) | /* LCD controller (3.3 V) */ + (1 << AXP_SUPPLY_LDO3)); /* SD bus (3.3 V) */ + + /* Enable required ADCs */ + axp_set_enabled_adcs( + (1 << AXP_ADC_BATTERY_VOLTAGE) | + (1 << AXP_ADC_CHARGE_CURRENT) | + (1 << AXP_ADC_DISCHARGE_CURRENT) | + (1 << AXP_ADC_VBUS_VOLTAGE) | + (1 << AXP_ADC_VBUS_CURRENT) | + (1 << AXP_ADC_INTERNAL_TEMP) | + (1 << AXP_ADC_APS_VOLTAGE)); /* Short delay to give power outputs time to stabilize */ mdelay(200); @@ -99,20 +101,25 @@ void power_off(void) bool charging_state(void) { - return axp_battery_status() == AXP_BATT_CHARGING; + return axp_is_charging(); +} + +unsigned int power_input_status(void) +{ + return axp_power_input_status(); } int _battery_voltage(void) { - return axp_adc_read(ADC_BATTERY_VOLTAGE); + return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE); } #if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE int _battery_current(void) { if(charging_state()) - return axp_adc_read(ADC_CHARGE_CURRENT); + return axp_read_adc(AXP_ADC_CHARGE_CURRENT); else - return axp_adc_read(ADC_DISCHARGE_CURRENT); + return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT); } #endif diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c index 13b0cdd078..1976dde793 100644 --- a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c +++ b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c @@ -23,7 +23,7 @@ #include "button.h" #include "touchscreen.h" #include "ft6x06.h" -#include "axp-pmu.h" +#include "axp192.h" #include "kernel.h" #include "backlight.h" #include "powermgmt.h" @@ -57,7 +57,7 @@ static void hp_detect_init(void) { /* TODO: replace this copy paste cruft with an API in axp-pmu */ static struct timeout tmo; - static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; + static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1; static i2c_descriptor desc = { .slave_addr = AXP_PMU_ADDR, .bus_cond = I2C_START | I2C_STOP, @@ -72,10 +72,10 @@ static void hp_detect_init(void) }; /* Headphone detect is wired to AXP192 GPIO: set it to input state */ - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); + axp_set_gpio_function(1, AXP_GPIO_INPUT); /* Get an initial reading before startup */ - int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); + int r = axp_read(gpio_reg); if(r >= 0) hp_detect_reg = r; diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c index 75f8031dd9..65d1bc163f 100644 --- a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c +++ b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c @@ -22,7 +22,7 @@ #include "power.h" #include "adc.h" #include "system.h" -#include "axp-pmu.h" +#include "axp192.h" #ifdef HAVE_CW2015 # include "cw2015.h" #endif @@ -73,24 +73,30 @@ const unsigned short percent_to_volt_charge[11] = void power_init(void) { i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K); - axp_init(); #ifdef HAVE_CW2015 cw2015_init(); #endif - /* Change supply voltage from the default of 1250 mV to 1200 mV, - * this matches the original firmware's settings. Didn't observe - * any obviously bad behavior at 1250 mV, but better to be safe. */ - axp_supply_set_voltage(AXP_SUPPLY_DCDC2, 1200); - - /* For now, just turn everything on... definitely the touchscreen - * is powered by one of the outputs */ - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_PWROUTPUTCTRL1, 0, 0x05, NULL); - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_PWROUTPUTCTRL2, 0, 0x0f, NULL); - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); + /* Set DCDC2 to 1.2 V to match OF settings. */ + axp_set_supply_voltage(AXP_SUPPLY_DCDC2, 1200); + + /* Power on required supplies */ + axp_set_enabled_supplies( + (1 << AXP_SUPPLY_DCDC1) | /* SD bus (3.3 V) */ + (1 << AXP_SUPPLY_DCDC2) | /* LCD (1.2 V) */ + (1 << AXP_SUPPLY_DCDC3) | /* CPU (1.8 V) */ + (1 << AXP_SUPPLY_LDO2) | /* Touchscreen (3.3 V) */ + (1 << AXP_SUPPLY_LDO3)); /* not sure (2.5 V) */ + + /* Enable required ADCs */ + axp_set_enabled_adcs( + (1 << AXP_ADC_BATTERY_VOLTAGE) | + (1 << AXP_ADC_CHARGE_CURRENT) | + (1 << AXP_ADC_DISCHARGE_CURRENT) | + (1 << AXP_ADC_VBUS_VOLTAGE) | + (1 << AXP_ADC_VBUS_CURRENT) | + (1 << AXP_ADC_INTERNAL_TEMP) | + (1 << AXP_ADC_APS_VOLTAGE)); /* Delay to give power output time to stabilize */ mdelay(20); @@ -111,23 +117,28 @@ void power_off(void) bool charging_state(void) { - return axp_battery_status() == AXP_BATT_CHARGING; + return axp_is_charging(); +} + +unsigned int power_input_status(void) +{ + return axp_power_input_status(); } int _battery_voltage(void) { /* CW2015 can also read battery voltage, but the AXP consistently * reads ~20-30 mV higher so I suspect it's the "real" voltage. */ - return axp_adc_read(ADC_BATTERY_VOLTAGE); + return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE); } #if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE int _battery_current(void) { if(charging_state()) - return axp_adc_read(ADC_CHARGE_CURRENT); + return axp_read_adc(AXP_ADC_CHARGE_CURRENT); else - return axp_adc_read(ADC_DISCHARGE_CURRENT); + return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT); } #endif -- cgit v1.2.3