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
This commit is contained in:
Aidan MacDonald 2022-01-09 18:55:28 +00:00
parent b490f08b7c
commit c62c323ebc
5 changed files with 60 additions and 129 deletions

View file

@ -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, &regs[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, &regs[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)

View file

@ -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);

View file

@ -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,

View file

@ -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,

View file

@ -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. */