From c62c323ebc71da33bf653624e45becee096906c3 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 9 Jan 2022 18:55:28 +0000 Subject: [PATCH] axp-pmu: adc refactor Remove the battery power ADC since it's not used right now, and seems to fluctuate too rapidly to be of much use. Change-Id: If115e4e3ce14d4c18ce899f5a889f7f99ab66489 --- firmware/drivers/axp-pmu.c | 146 ++++-------------- firmware/export/axp-pmu.h | 4 +- .../erosqnative/power-erosqnative.c | 13 +- .../ingenic_x1000/fiiom3k/power-fiiom3k.c | 13 +- .../shanlingq1/power-shanlingq1.c | 13 ++ 5 files changed, 60 insertions(+), 129 deletions(-) diff --git a/firmware/drivers/axp-pmu.c b/firmware/drivers/axp-pmu.c index ed284ee9c2..d59fbb2e3f 100644 --- a/firmware/drivers/axp-pmu.c +++ b/firmware/drivers/axp-pmu.c @@ -36,6 +36,8 @@ struct axp_adc_info { uint8_t reg; uint8_t en_reg; uint8_t en_bit; + int8_t num; + int8_t den; }; struct axp_supply_info { @@ -49,17 +51,16 @@ struct axp_supply_info { }; static const struct axp_adc_info axp_adc_info[NUM_ADC_CHANNELS] = { - {0x56, AXP_REG_ADCENABLE1, 5}, /* ACIN_VOLTAGE */ - {0x58, AXP_REG_ADCENABLE1, 4}, /* ACIN_CURRENT */ - {0x5a, AXP_REG_ADCENABLE1, 3}, /* VBUS_VOLTAGE */ - {0x5c, AXP_REG_ADCENABLE1, 2}, /* VBUS_CURRENT */ - {0x5e, AXP_REG_ADCENABLE2, 7}, /* INTERNAL_TEMP */ - {0x62, AXP_REG_ADCENABLE1, 1}, /* TS_INPUT */ - {0x78, AXP_REG_ADCENABLE1, 7}, /* BATTERY_VOLTAGE */ - {0x7a, AXP_REG_ADCENABLE1, 6}, /* CHARGE_CURRENT */ - {0x7c, AXP_REG_ADCENABLE1, 6}, /* DISCHARGE_CURRENT */ - {0x7e, AXP_REG_ADCENABLE1, 1}, /* APS_VOLTAGE */ - {0x70, 0xff, 0}, /* BATTERY_POWER */ + [ADC_ACIN_VOLTAGE] = {0x56, AXP_REG_ADCENABLE1, 1 << 5, 17, 10}, + [ADC_ACIN_CURRENT] = {0x58, AXP_REG_ADCENABLE1, 1 << 4, 5, 8}, + [ADC_VBUS_VOLTAGE] = {0x5a, AXP_REG_ADCENABLE1, 1 << 3, 17, 10}, + [ADC_VBUS_CURRENT] = {0x5c, AXP_REG_ADCENABLE1, 1 << 2, 3, 8}, + [ADC_INTERNAL_TEMP] = {0x5e, AXP_REG_ADCENABLE2, 1 << 7, 0, 0}, + [ADC_TS_INPUT] = {0x62, AXP_REG_ADCENABLE1, 1 << 1, 4, 5}, + [ADC_BATTERY_VOLTAGE] = {0x78, AXP_REG_ADCENABLE1, 1 << 7, 11, 10}, + [ADC_CHARGE_CURRENT] = {0x7a, AXP_REG_ADCENABLE1, 1 << 6, 1, 2}, + [ADC_DISCHARGE_CURRENT] = {0x7c, AXP_REG_ADCENABLE1, 1 << 6, 1, 2}, + [ADC_APS_VOLTAGE] = {0x7e, AXP_REG_ADCENABLE1, 1 << 1, 7, 5}, }; static const struct axp_supply_info axp_supply_info[AXP_NUM_SUPPLIES] = { @@ -126,46 +127,8 @@ static const struct axp_supply_info axp_supply_info[AXP_NUM_SUPPLIES] = { #endif }; -static struct axp_driver { - int adc_enable; -} axp; - -static void axp_init_enabled_adcs(void) -{ - axp.adc_enable = 0; - - /* Read enabled ADCs from the hardware */ - uint8_t regs[2]; - int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, - AXP_REG_ADCENABLE1, 2, ®s[0]); - if(rc != I2C_STATUS_OK) - return; - - /* Parse registers to set ADC enable bits */ - const struct axp_adc_info* info = axp_adc_info; - for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { - if(info[i].en_reg == 0xff) - continue; - - if(regs[info[i].en_reg - AXP_REG_ADCENABLE1] & info[i].en_bit) - axp.adc_enable |= 1 << i; - } - - /* Handle battery power ADC */ - if((axp.adc_enable & (1 << ADC_BATTERY_VOLTAGE)) && - (axp.adc_enable & (1 << ADC_DISCHARGE_CURRENT))) { - axp.adc_enable |= (1 << ADC_BATTERY_POWER); - } -} - void axp_init(void) { - axp_init_enabled_adcs(); - - /* We need discharge current ADC to reliably poll for a full battery */ - int bits = axp.adc_enable; - bits |= (1 << ADC_DISCHARGE_CURRENT); - axp_adc_set_enabled(bits); } void axp_supply_set_voltage(int supply, int voltage) @@ -294,22 +257,15 @@ int axp_adc_read(int adc) int axp_adc_read_raw(int adc) { - /* Don't give a reading if the ADC is not enabled */ - if((axp.adc_enable & (1 << adc)) == 0) - return INT_MIN; - /* Read the ADC */ - uint8_t buf[3]; - int count = (adc == ADC_BATTERY_POWER) ? 3 : 2; + uint8_t buf[2]; uint8_t reg = axp_adc_info[adc].reg; - int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, reg, count, &buf[0]); + int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, reg, 2, &buf[0]); if(rc != I2C_STATUS_OK) return INT_MIN; /* Parse the value */ - if(adc == ADC_BATTERY_POWER) - return (buf[0] << 16) | (buf[1] << 8) | buf[2]; - else if(adc == ADC_CHARGE_CURRENT || adc == ADC_DISCHARGE_CURRENT) + if(adc == ADC_CHARGE_CURRENT || adc == ADC_DISCHARGE_CURRENT) return (buf[0] << 5) | (buf[1] & 0x1f); else return (buf[0] << 4) | (buf[1] & 0xf); @@ -317,79 +273,33 @@ int axp_adc_read_raw(int adc) int axp_adc_conv_raw(int adc, int value) { - switch(adc) { - case ADC_ACIN_VOLTAGE: - case ADC_VBUS_VOLTAGE: - /* 0 mV ... 6.9615 mV, step 1.7 mV */ - return value * 17 / 10; - case ADC_ACIN_CURRENT: - /* 0 mA ... 2.5594 A, step 0.625 mA */ - return value * 5 / 8; - case ADC_VBUS_CURRENT: - /* 0 mA ... 1.5356 A, step 0.375 mA */ - return value * 3 / 8; - case ADC_INTERNAL_TEMP: - /* -144.7 C ... 264.8 C, step 0.1 C */ + if(adc == ADC_INTERNAL_TEMP) return value - 1447; - case ADC_TS_INPUT: - /* 0 mV ... 3.276 V, step 0.8 mV */ - return value * 4 / 5; - case ADC_BATTERY_VOLTAGE: - /* 0 mV ... 4.5045 V, step 1.1 mV */ - return value * 11 / 10; - case ADC_CHARGE_CURRENT: - case ADC_DISCHARGE_CURRENT: - /* 0 mA to 4.095 A, step 0.5 mA */ - return value / 2; - case ADC_APS_VOLTAGE: - /* 0 mV to 5.733 V, step 1.4 mV */ - return value * 7 / 5; - case ADC_BATTERY_POWER: - /* 0 uW to 23.6404 W, step 0.55 uW */ - return value * 11 / 20; - default: - /* Shouldn't happen */ - return INT_MIN; - } -} - -int axp_adc_get_enabled(void) -{ - return axp.adc_enable; + else + return axp_adc_info[adc].num * value / axp_adc_info[adc].den; } void axp_adc_set_enabled(int adc_bits) { - /* Ignore no-op */ - if(adc_bits == axp.adc_enable) - return; + uint8_t xfer[3]; + xfer[0] = 0; + xfer[1] = AXP_REG_ADCENABLE2; + xfer[2] = 0; /* Compute the new register values */ const struct axp_adc_info* info = axp_adc_info; - uint8_t regs[2] = {0, 0}; for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { - if(info[i].en_reg == 0xff) + if(!(adc_bits & (1 << i))) continue; - if(adc_bits & (1 << i)) - regs[info[i].en_reg - 0x82] |= 1 << info[i].en_bit; - } - - /* These ADCs share an enable bit */ - if(adc_bits & ((1 << ADC_CHARGE_CURRENT)|(1 << ADC_DISCHARGE_CURRENT))) { - adc_bits |= (1 << ADC_CHARGE_CURRENT); - adc_bits |= (1 << ADC_DISCHARGE_CURRENT); - } - - /* Enable required bits for battery power ADC */ - if(adc_bits & (1 << ADC_BATTERY_POWER)) { - regs[0] |= 1 << info[ADC_DISCHARGE_CURRENT].en_bit; - regs[0] |= 1 << info[ADC_BATTERY_VOLTAGE].en_bit; + if(info[i].en_reg == AXP_REG_ADCENABLE1) + xfer[0] |= info[i].en_bit; + else + xfer[2] |= info[i].en_bit; } /* Update the configuration */ - i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP_REG_ADCENABLE1, 2, ®s[0]); - axp.adc_enable = adc_bits; + i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP_REG_ADCENABLE1, 3, &xfer[0]); } int axp_adc_get_rate(void) diff --git a/firmware/export/axp-pmu.h b/firmware/export/axp-pmu.h index 553410ced8..24c992dea3 100644 --- a/firmware/export/axp-pmu.h +++ b/firmware/export/axp-pmu.h @@ -37,8 +37,7 @@ #define ADC_CHARGE_CURRENT 7 #define ADC_DISCHARGE_CURRENT 8 #define ADC_APS_VOLTAGE 9 -#define ADC_BATTERY_POWER 10 -#define NUM_ADC_CHANNELS 11 +#define NUM_ADC_CHANNELS 10 /* ADC sampling rates */ #define AXP_ADC_RATE_25HZ 0 @@ -123,7 +122,6 @@ extern int axp_input_status(void); extern int axp_adc_read(int adc); extern int axp_adc_read_raw(int adc); extern int axp_adc_conv_raw(int adc, int value); -extern int axp_adc_get_enabled(void); extern void axp_adc_set_enabled(int adc_bits); extern int axp_adc_get_rate(void); extern void axp_adc_set_rate(int rate); diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c index a1a4d2c2b2..183a6164f6 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c @@ -63,10 +63,15 @@ void power_init(void) /* 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); + /* Enable required ADCs */ + axp_adc_set_enabled( + (1 << ADC_BATTERY_VOLTAGE) | + (1 << ADC_CHARGE_CURRENT) | + (1 << ADC_DISCHARGE_CURRENT) | + (1 << ADC_VBUS_VOLTAGE) | + (1 << ADC_VBUS_CURRENT) | + (1 << ADC_INTERNAL_TEMP) | + (1 << ADC_APS_VOLTAGE)); /* Turn on all power outputs */ i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c index 2d28ad0975..840be36a75 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c @@ -61,10 +61,15 @@ void power_init(void) /* 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); + /* Enable required ADCs */ + axp_adc_set_enabled( + (1 << ADC_BATTERY_VOLTAGE) | + (1 << ADC_CHARGE_CURRENT) | + (1 << ADC_DISCHARGE_CURRENT) | + (1 << ADC_VBUS_VOLTAGE) | + (1 << ADC_VBUS_CURRENT) | + (1 << ADC_INTERNAL_TEMP) | + (1 << ADC_APS_VOLTAGE)); /* Turn on all power outputs */ i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c index 75f8031dd9..59a2262f25 100644 --- a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c +++ b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c @@ -78,6 +78,19 @@ void power_init(void) cw2015_init(); #endif + /* Set lowest sample rate */ + axp_adc_set_rate(AXP_ADC_RATE_25HZ); + + /* Enable required ADCs */ + axp_adc_set_enabled( + (1 << ADC_BATTERY_VOLTAGE) | + (1 << ADC_CHARGE_CURRENT) | + (1 << ADC_DISCHARGE_CURRENT) | + (1 << ADC_VBUS_VOLTAGE) | + (1 << ADC_VBUS_CURRENT) | + (1 << ADC_INTERNAL_TEMP) | + (1 << ADC_APS_VOLTAGE)); + /* 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. */