diff options
author | Dana Conrad <dconrad@fastmail.com> | 2024-12-30 03:16:20 +0000 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2025-01-01 20:49:07 -0500 |
commit | f2dd48912045f09a44df7d6b058624d3a1d3d676 (patch) | |
tree | 2d195507e125ff58816820b2166a4f38683e299a | |
parent | d038aa47fef0238f4a4c24d0f533982fa0944f98 (diff) | |
download | rockbox-f2dd489120.tar.gz rockbox-f2dd489120.zip |
FS#13535: AXP2101: ADC / reporting improvements
Improve ADC behavior, add correct conversion
for die temperature, add readout of EGauge to debug screen.
Add delay to give ADC time to get a good reading. Initial reading
may still be 1-3% optimistic, which is probably ok.
EGauge appears to be pretty good, but no great need to convert
to using it either.
Change-Id: Iab9d50e2427f656ad0875f9a623b03545fc69881
-rw-r--r-- | firmware/drivers/axp-2101.c | 45 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c | 11 |
2 files changed, 36 insertions, 20 deletions
diff --git a/firmware/drivers/axp-2101.c b/firmware/drivers/axp-2101.c index 74a302f1b7..b2187d3274 100644 --- a/firmware/drivers/axp-2101.c +++ b/firmware/drivers/axp-2101.c @@ -57,17 +57,16 @@ struct axp_supply_info { }; static const struct axp_adc_info axp_adc_info[AXP2101_NUM_ADC_CHANNELS] = { - // TODO: Datasheet ADC conversion table doesn't seem to make any sense... - // 0x000 0x001 0x002 ... 0xFFF + // 0x000 0x001 0x002 ... 0x1FFF // 0mV 1mV 2mV ... 8.192V [AXP2101_ADC_VBAT_VOLTAGE] = {AXP2101_REG_ADC_VBAT_H, AXP2101_REG_ADCCHNENABLE, 1 << 0, 1, 1}, // 0mV 1mV 2mV ... 8.192V [AXP2101_ADC_VBUS_VOLTAGE] = {AXP2101_REG_ADC_VBUS_H, AXP2101_REG_ADCCHNENABLE, 1 << 2, 1, 1}, // 0mV 1mV 2mV ... 8.192V [AXP2101_ADC_VSYS_VOLTAGE] = {AXP2101_REG_ADC_VSYS_H, AXP2101_REG_ADCCHNENABLE, 1 << 3, 1, 1}, - // 0mV 0.5mV 1mV ... 4.096V - [AXP2101_ADC_TS_VOLTAGE] = {AXP2101_REG_ADC_TS_H, AXP2101_REG_ADCCHNENABLE, 1 << 1, 1, 1}, - // 0mV 0.1mV 2mV ... 0.8192V + // 0mV 0.5mV 0.1mV ... 4.096V + [AXP2101_ADC_TS_VOLTAGE] = {AXP2101_REG_ADC_TS_H, AXP2101_REG_ADCCHNENABLE, 1 << 1, 1, 2}, + // see axp2101_adc_conv_raw() for conversion [AXP2101_ADC_DIE_TEMPERATURE] = {AXP2101_REG_ADC_TDIE_H, AXP2101_REG_ADCCHNENABLE, 1 << 4, 1, 1}, }; @@ -309,7 +308,7 @@ void axp2101_supply_set_voltage(int supply, int voltage) if(voltage > 0 && info->step_mV != 0) { if(voltage < info->min_mV) return; - + int regval; // there's probably a more elegant way to do this... @@ -446,11 +445,20 @@ int axp2101_adc_read_raw(int adc) return INT_MIN; /* Parse the value */ - return ((buf[0] & 0x3f) << 8) | (buf[1] & 0xff); + return ((int)(buf[0] & 0x3f) << 8) | (buf[1] & 0xff); } int axp2101_adc_conv_raw(int adc, int value) { + if (adc == AXP2101_ADC_DIE_TEMPERATURE) + return 22 + ((7274 - value) / 20); + + // seems to be a signed 14-bit value, but + // let's clamp it to zero. Seems to give sane results + // on v_bus and v_ts channels + if (value & 0x2000) + return 0; + return axp_adc_info[adc].num * value / axp_adc_info[adc].den; } @@ -472,12 +480,12 @@ void axp2101_adc_set_enabled(int adc_bits) i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_ADCCHNENABLE, 1, &xfer[0]); } -// TODO: See if we can figure out "optimum" battery chemistry-type settings -// like constant-current charging, charge curves... that stuff is all configurable -// as far as I can tell! Probably important to at least figure out if the defaults -// are clearly wrong or not! - -// TODO: what are DATA_BUFFER 0-3 for???? +int axp2101_egauge_read(void) +{ + uint8_t buf; + i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_BATT_PERCENTAGE, 1, &buf); + return (int)buf; +} // there are many current settings: // Reg 16: Input current limit control @@ -534,6 +542,7 @@ enum { AXP_DEBUG_BATTERY_STATUS, AXP_DEBUG_INPUT_STATUS, AXP_DEBUG_CHARGE_CURRENT, + AXP_DEBUG_EGAUGE_VALUE, AXP_DEBUG_FIRST_ADC, AXP_DEBUG_FIRST_SUPPLY = AXP_DEBUG_FIRST_ADC + AXP2101_NUM_ADC_CHANNELS, AXP_DEBUG_NUM_ENTRIES = AXP_DEBUG_FIRST_SUPPLY + AXP2101_NUM_SUPPLIES, @@ -555,11 +564,11 @@ static const char* axp2101_debug_menu_get_name(int item, void* data, (void)data; static const char* const adc_names[] = { - "V_bat", "V_bus", "V_sys", "V_ts", "V_die", + "V_bat", "V_bus", "V_sys", "V_ts", "T_die", }; static const char* const adc_units[] = { - "mV", "mV", "mV", "mV", "C*100", + "mV", "mV", "mV", "mV", "C", }; static const char* const supply_names[] = { @@ -625,6 +634,12 @@ static const char* axp2101_debug_menu_get_name(int item, void* data, return buf; } break; + case AXP_DEBUG_EGAUGE_VALUE: { + int percent = axp2101_egauge_read(); + snprintf(buf, buflen, "EGauge percent: %d", percent); + return buf; + } break; + default: return "---"; } diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c index 5dad78392e..0f9eb3fcd0 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c @@ -97,10 +97,6 @@ void power_init(void) } // These match the OF as far as I can discern - // TODO: These values are set in EFUSE apparently, could - // do a "check then set if necessary"... - // Also if we had a fresh device we could verify what - // the OF sets. axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC1, 3300); axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC2, 1200); axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC3, 2800); @@ -123,6 +119,12 @@ void power_init(void) /* Set the default charging current. This is the same as the * OF's setting, although it's not strictly within the USB spec. */ axp2101_set_charge_current(780); + + /* delay to allow ADC to get a good sample - + * may give bogus (high) readings otherwise. */ +#ifndef BOOTLOADER + mdelay(150); +#endif } else { axp_init(); /* Set lowest sample rate */ @@ -138,7 +140,6 @@ void power_init(void) (1 << ADC_INTERNAL_TEMP) | (1 << ADC_APS_VOLTAGE)); - /* TODO: Set Output Voltages! */ i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, |