1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Dana Conrad 2024-12-30 03:16:20 +00:00 committed by Solomon Peachy
parent d038aa47fe
commit f2dd489120
2 changed files with 36 additions and 20 deletions

View file

@ -57,17 +57,16 @@ struct axp_supply_info {
}; };
static const struct axp_adc_info axp_adc_info[AXP2101_NUM_ADC_CHANNELS] = { 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 ... 0x1FFF
// 0x000 0x001 0x002 ... 0xFFF
// 0mV 1mV 2mV ... 8.192V // 0mV 1mV 2mV ... 8.192V
[AXP2101_ADC_VBAT_VOLTAGE] = {AXP2101_REG_ADC_VBAT_H, AXP2101_REG_ADCCHNENABLE, 1 << 0, 1, 1}, [AXP2101_ADC_VBAT_VOLTAGE] = {AXP2101_REG_ADC_VBAT_H, AXP2101_REG_ADCCHNENABLE, 1 << 0, 1, 1},
// 0mV 1mV 2mV ... 8.192V // 0mV 1mV 2mV ... 8.192V
[AXP2101_ADC_VBUS_VOLTAGE] = {AXP2101_REG_ADC_VBUS_H, AXP2101_REG_ADCCHNENABLE, 1 << 2, 1, 1}, [AXP2101_ADC_VBUS_VOLTAGE] = {AXP2101_REG_ADC_VBUS_H, AXP2101_REG_ADCCHNENABLE, 1 << 2, 1, 1},
// 0mV 1mV 2mV ... 8.192V // 0mV 1mV 2mV ... 8.192V
[AXP2101_ADC_VSYS_VOLTAGE] = {AXP2101_REG_ADC_VSYS_H, AXP2101_REG_ADCCHNENABLE, 1 << 3, 1, 1}, [AXP2101_ADC_VSYS_VOLTAGE] = {AXP2101_REG_ADC_VSYS_H, AXP2101_REG_ADCCHNENABLE, 1 << 3, 1, 1},
// 0mV 0.5mV 1mV ... 4.096V // 0mV 0.5mV 0.1mV ... 4.096V
[AXP2101_ADC_TS_VOLTAGE] = {AXP2101_REG_ADC_TS_H, AXP2101_REG_ADCCHNENABLE, 1 << 1, 1, 1}, [AXP2101_ADC_TS_VOLTAGE] = {AXP2101_REG_ADC_TS_H, AXP2101_REG_ADCCHNENABLE, 1 << 1, 1, 2},
// 0mV 0.1mV 2mV ... 0.8192V // see axp2101_adc_conv_raw() for conversion
[AXP2101_ADC_DIE_TEMPERATURE] = {AXP2101_REG_ADC_TDIE_H, AXP2101_REG_ADCCHNENABLE, 1 << 4, 1, 1}, [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 > 0 && info->step_mV != 0) {
if(voltage < info->min_mV) if(voltage < info->min_mV)
return; return;
int regval; int regval;
// there's probably a more elegant way to do this... // there's probably a more elegant way to do this...
@ -446,11 +445,20 @@ int axp2101_adc_read_raw(int adc)
return INT_MIN; return INT_MIN;
/* Parse the value */ /* 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) 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; 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]); 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 int axp2101_egauge_read(void)
// 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 uint8_t buf;
// are clearly wrong or not! i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_BATT_PERCENTAGE, 1, &buf);
return (int)buf;
// TODO: what are DATA_BUFFER 0-3 for???? }
// there are many current settings: // there are many current settings:
// Reg 16: Input current limit control // Reg 16: Input current limit control
@ -534,6 +542,7 @@ enum {
AXP_DEBUG_BATTERY_STATUS, AXP_DEBUG_BATTERY_STATUS,
AXP_DEBUG_INPUT_STATUS, AXP_DEBUG_INPUT_STATUS,
AXP_DEBUG_CHARGE_CURRENT, AXP_DEBUG_CHARGE_CURRENT,
AXP_DEBUG_EGAUGE_VALUE,
AXP_DEBUG_FIRST_ADC, AXP_DEBUG_FIRST_ADC,
AXP_DEBUG_FIRST_SUPPLY = AXP_DEBUG_FIRST_ADC + AXP2101_NUM_ADC_CHANNELS, AXP_DEBUG_FIRST_SUPPLY = AXP_DEBUG_FIRST_ADC + AXP2101_NUM_ADC_CHANNELS,
AXP_DEBUG_NUM_ENTRIES = AXP_DEBUG_FIRST_SUPPLY + AXP2101_NUM_SUPPLIES, 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; (void)data;
static const char* const adc_names[] = { 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[] = { static const char* const adc_units[] = {
"mV", "mV", "mV", "mV", "C*100", "mV", "mV", "mV", "mV", "C",
}; };
static const char* const supply_names[] = { static const char* const supply_names[] = {
@ -625,6 +634,12 @@ static const char* axp2101_debug_menu_get_name(int item, void* data,
return buf; return buf;
} break; } break;
case AXP_DEBUG_EGAUGE_VALUE: {
int percent = axp2101_egauge_read();
snprintf(buf, buflen, "EGauge percent: %d", percent);
return buf;
} break;
default: default:
return "---"; return "---";
} }

View file

@ -97,10 +97,6 @@ void power_init(void)
} }
// These match the OF as far as I can discern // 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_DCDC1, 3300);
axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC2, 1200); axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC2, 1200);
axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC3, 2800); 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 /* Set the default charging current. This is the same as the
* OF's setting, although it's not strictly within the USB spec. */ * OF's setting, although it's not strictly within the USB spec. */
axp2101_set_charge_current(780); 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 { } else {
axp_init(); axp_init();
/* Set lowest sample rate */ /* Set lowest sample rate */
@ -138,7 +140,6 @@ void power_init(void)
(1 << ADC_INTERNAL_TEMP) | (1 << ADC_INTERNAL_TEMP) |
(1 << ADC_APS_VOLTAGE)); (1 << ADC_APS_VOLTAGE));
/* TODO: Set Output Voltages! */
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL);
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,