diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2022-01-09 18:55:28 +0000 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2022-01-09 20:12:41 +0000 |
commit | c62c323ebc71da33bf653624e45becee096906c3 (patch) | |
tree | a328d9400b9b2ff4c637110cf5fb701d5eba5904 | |
parent | b490f08b7c6f8b32b214e0fbf6dd3974066ec150 (diff) | |
download | rockbox-c62c323ebc71da33bf653624e45becee096906c3.tar.gz rockbox-c62c323ebc71da33bf653624e45becee096906c3.zip |
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
-rw-r--r-- | firmware/drivers/axp-pmu.c | 146 | ||||
-rw-r--r-- | firmware/export/axp-pmu.h | 4 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c | 13 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c | 13 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/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 { | |||
36 | uint8_t reg; | 36 | uint8_t reg; |
37 | uint8_t en_reg; | 37 | uint8_t en_reg; |
38 | uint8_t en_bit; | 38 | uint8_t en_bit; |
39 | int8_t num; | ||
40 | int8_t den; | ||
39 | }; | 41 | }; |
40 | 42 | ||
41 | struct axp_supply_info { | 43 | struct axp_supply_info { |
@@ -49,17 +51,16 @@ struct axp_supply_info { | |||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static const struct axp_adc_info axp_adc_info[NUM_ADC_CHANNELS] = { | 53 | static const struct axp_adc_info axp_adc_info[NUM_ADC_CHANNELS] = { |
52 | {0x56, AXP_REG_ADCENABLE1, 5}, /* ACIN_VOLTAGE */ | 54 | [ADC_ACIN_VOLTAGE] = {0x56, AXP_REG_ADCENABLE1, 1 << 5, 17, 10}, |
53 | {0x58, AXP_REG_ADCENABLE1, 4}, /* ACIN_CURRENT */ | 55 | [ADC_ACIN_CURRENT] = {0x58, AXP_REG_ADCENABLE1, 1 << 4, 5, 8}, |
54 | {0x5a, AXP_REG_ADCENABLE1, 3}, /* VBUS_VOLTAGE */ | 56 | [ADC_VBUS_VOLTAGE] = {0x5a, AXP_REG_ADCENABLE1, 1 << 3, 17, 10}, |
55 | {0x5c, AXP_REG_ADCENABLE1, 2}, /* VBUS_CURRENT */ | 57 | [ADC_VBUS_CURRENT] = {0x5c, AXP_REG_ADCENABLE1, 1 << 2, 3, 8}, |
56 | {0x5e, AXP_REG_ADCENABLE2, 7}, /* INTERNAL_TEMP */ | 58 | [ADC_INTERNAL_TEMP] = {0x5e, AXP_REG_ADCENABLE2, 1 << 7, 0, 0}, |
57 | {0x62, AXP_REG_ADCENABLE1, 1}, /* TS_INPUT */ | 59 | [ADC_TS_INPUT] = {0x62, AXP_REG_ADCENABLE1, 1 << 1, 4, 5}, |
58 | {0x78, AXP_REG_ADCENABLE1, 7}, /* BATTERY_VOLTAGE */ | 60 | [ADC_BATTERY_VOLTAGE] = {0x78, AXP_REG_ADCENABLE1, 1 << 7, 11, 10}, |
59 | {0x7a, AXP_REG_ADCENABLE1, 6}, /* CHARGE_CURRENT */ | 61 | [ADC_CHARGE_CURRENT] = {0x7a, AXP_REG_ADCENABLE1, 1 << 6, 1, 2}, |
60 | {0x7c, AXP_REG_ADCENABLE1, 6}, /* DISCHARGE_CURRENT */ | 62 | [ADC_DISCHARGE_CURRENT] = {0x7c, AXP_REG_ADCENABLE1, 1 << 6, 1, 2}, |
61 | {0x7e, AXP_REG_ADCENABLE1, 1}, /* APS_VOLTAGE */ | 63 | [ADC_APS_VOLTAGE] = {0x7e, AXP_REG_ADCENABLE1, 1 << 1, 7, 5}, |
62 | {0x70, 0xff, 0}, /* BATTERY_POWER */ | ||
63 | }; | 64 | }; |
64 | 65 | ||
65 | static const struct axp_supply_info axp_supply_info[AXP_NUM_SUPPLIES] = { | 66 | 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] = { | |||
126 | #endif | 127 | #endif |
127 | }; | 128 | }; |
128 | 129 | ||
129 | static struct axp_driver { | ||
130 | int adc_enable; | ||
131 | } axp; | ||
132 | |||
133 | static void axp_init_enabled_adcs(void) | ||
134 | { | ||
135 | axp.adc_enable = 0; | ||
136 | |||
137 | /* Read enabled ADCs from the hardware */ | ||
138 | uint8_t regs[2]; | ||
139 | int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, | ||
140 | AXP_REG_ADCENABLE1, 2, ®s[0]); | ||
141 | if(rc != I2C_STATUS_OK) | ||
142 | return; | ||
143 | |||
144 | /* Parse registers to set ADC enable bits */ | ||
145 | const struct axp_adc_info* info = axp_adc_info; | ||
146 | for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { | ||
147 | if(info[i].en_reg == 0xff) | ||
148 | continue; | ||
149 | |||
150 | if(regs[info[i].en_reg - AXP_REG_ADCENABLE1] & info[i].en_bit) | ||
151 | axp.adc_enable |= 1 << i; | ||
152 | } | ||
153 | |||
154 | /* Handle battery power ADC */ | ||
155 | if((axp.adc_enable & (1 << ADC_BATTERY_VOLTAGE)) && | ||
156 | (axp.adc_enable & (1 << ADC_DISCHARGE_CURRENT))) { | ||
157 | axp.adc_enable |= (1 << ADC_BATTERY_POWER); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | void axp_init(void) | 130 | void axp_init(void) |
162 | { | 131 | { |
163 | axp_init_enabled_adcs(); | ||
164 | |||
165 | /* We need discharge current ADC to reliably poll for a full battery */ | ||
166 | int bits = axp.adc_enable; | ||
167 | bits |= (1 << ADC_DISCHARGE_CURRENT); | ||
168 | axp_adc_set_enabled(bits); | ||
169 | } | 132 | } |
170 | 133 | ||
171 | void axp_supply_set_voltage(int supply, int voltage) | 134 | void axp_supply_set_voltage(int supply, int voltage) |
@@ -294,22 +257,15 @@ int axp_adc_read(int adc) | |||
294 | 257 | ||
295 | int axp_adc_read_raw(int adc) | 258 | int axp_adc_read_raw(int adc) |
296 | { | 259 | { |
297 | /* Don't give a reading if the ADC is not enabled */ | ||
298 | if((axp.adc_enable & (1 << adc)) == 0) | ||
299 | return INT_MIN; | ||
300 | |||
301 | /* Read the ADC */ | 260 | /* Read the ADC */ |
302 | uint8_t buf[3]; | 261 | uint8_t buf[2]; |
303 | int count = (adc == ADC_BATTERY_POWER) ? 3 : 2; | ||
304 | uint8_t reg = axp_adc_info[adc].reg; | 262 | uint8_t reg = axp_adc_info[adc].reg; |
305 | int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, reg, count, &buf[0]); | 263 | int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, reg, 2, &buf[0]); |
306 | if(rc != I2C_STATUS_OK) | 264 | if(rc != I2C_STATUS_OK) |
307 | return INT_MIN; | 265 | return INT_MIN; |
308 | 266 | ||
309 | /* Parse the value */ | 267 | /* Parse the value */ |
310 | if(adc == ADC_BATTERY_POWER) | 268 | if(adc == ADC_CHARGE_CURRENT || adc == ADC_DISCHARGE_CURRENT) |
311 | return (buf[0] << 16) | (buf[1] << 8) | buf[2]; | ||
312 | else if(adc == ADC_CHARGE_CURRENT || adc == ADC_DISCHARGE_CURRENT) | ||
313 | return (buf[0] << 5) | (buf[1] & 0x1f); | 269 | return (buf[0] << 5) | (buf[1] & 0x1f); |
314 | else | 270 | else |
315 | return (buf[0] << 4) | (buf[1] & 0xf); | 271 | return (buf[0] << 4) | (buf[1] & 0xf); |
@@ -317,79 +273,33 @@ int axp_adc_read_raw(int adc) | |||
317 | 273 | ||
318 | int axp_adc_conv_raw(int adc, int value) | 274 | int axp_adc_conv_raw(int adc, int value) |
319 | { | 275 | { |
320 | switch(adc) { | 276 | if(adc == ADC_INTERNAL_TEMP) |
321 | case ADC_ACIN_VOLTAGE: | ||
322 | case ADC_VBUS_VOLTAGE: | ||
323 | /* 0 mV ... 6.9615 mV, step 1.7 mV */ | ||
324 | return value * 17 / 10; | ||
325 | case ADC_ACIN_CURRENT: | ||
326 | /* 0 mA ... 2.5594 A, step 0.625 mA */ | ||
327 | return value * 5 / 8; | ||
328 | case ADC_VBUS_CURRENT: | ||
329 | /* 0 mA ... 1.5356 A, step 0.375 mA */ | ||
330 | return value * 3 / 8; | ||
331 | case ADC_INTERNAL_TEMP: | ||
332 | /* -144.7 C ... 264.8 C, step 0.1 C */ | ||
333 | return value - 1447; | 277 | return value - 1447; |
334 | case ADC_TS_INPUT: | 278 | else |
335 | /* 0 mV ... 3.276 V, step 0.8 mV */ | 279 | return axp_adc_info[adc].num * value / axp_adc_info[adc].den; |
336 | return value * 4 / 5; | ||
337 | case ADC_BATTERY_VOLTAGE: | ||
338 | /* 0 mV ... 4.5045 V, step 1.1 mV */ | ||
339 | return value * 11 / 10; | ||
340 | case ADC_CHARGE_CURRENT: | ||
341 | case ADC_DISCHARGE_CURRENT: | ||
342 | /* 0 mA to 4.095 A, step 0.5 mA */ | ||
343 | return value / 2; | ||
344 | case ADC_APS_VOLTAGE: | ||
345 | /* 0 mV to 5.733 V, step 1.4 mV */ | ||
346 | return value * 7 / 5; | ||
347 | case ADC_BATTERY_POWER: | ||
348 | /* 0 uW to 23.6404 W, step 0.55 uW */ | ||
349 | return value * 11 / 20; | ||
350 | default: | ||
351 | /* Shouldn't happen */ | ||
352 | return INT_MIN; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | int axp_adc_get_enabled(void) | ||
357 | { | ||
358 | return axp.adc_enable; | ||
359 | } | 280 | } |
360 | 281 | ||
361 | void axp_adc_set_enabled(int adc_bits) | 282 | void axp_adc_set_enabled(int adc_bits) |
362 | { | 283 | { |
363 | /* Ignore no-op */ | 284 | uint8_t xfer[3]; |
364 | if(adc_bits == axp.adc_enable) | 285 | xfer[0] = 0; |
365 | return; | 286 | xfer[1] = AXP_REG_ADCENABLE2; |
287 | xfer[2] = 0; | ||
366 | 288 | ||
367 | /* Compute the new register values */ | 289 | /* Compute the new register values */ |
368 | const struct axp_adc_info* info = axp_adc_info; | 290 | const struct axp_adc_info* info = axp_adc_info; |
369 | uint8_t regs[2] = {0, 0}; | ||
370 | for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { | 291 | for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { |
371 | if(info[i].en_reg == 0xff) | 292 | if(!(adc_bits & (1 << i))) |
372 | continue; | 293 | continue; |
373 | 294 | ||
374 | if(adc_bits & (1 << i)) | 295 | if(info[i].en_reg == AXP_REG_ADCENABLE1) |
375 | regs[info[i].en_reg - 0x82] |= 1 << info[i].en_bit; | 296 | xfer[0] |= info[i].en_bit; |
376 | } | 297 | else |
377 | 298 | xfer[2] |= info[i].en_bit; | |
378 | /* These ADCs share an enable bit */ | ||
379 | if(adc_bits & ((1 << ADC_CHARGE_CURRENT)|(1 << ADC_DISCHARGE_CURRENT))) { | ||
380 | adc_bits |= (1 << ADC_CHARGE_CURRENT); | ||
381 | adc_bits |= (1 << ADC_DISCHARGE_CURRENT); | ||
382 | } | ||
383 | |||
384 | /* Enable required bits for battery power ADC */ | ||
385 | if(adc_bits & (1 << ADC_BATTERY_POWER)) { | ||
386 | regs[0] |= 1 << info[ADC_DISCHARGE_CURRENT].en_bit; | ||
387 | regs[0] |= 1 << info[ADC_BATTERY_VOLTAGE].en_bit; | ||
388 | } | 299 | } |
389 | 300 | ||
390 | /* Update the configuration */ | 301 | /* Update the configuration */ |
391 | i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP_REG_ADCENABLE1, 2, ®s[0]); | 302 | i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP_REG_ADCENABLE1, 3, &xfer[0]); |
392 | axp.adc_enable = adc_bits; | ||
393 | } | 303 | } |
394 | 304 | ||
395 | int axp_adc_get_rate(void) | 305 | 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 @@ | |||
37 | #define ADC_CHARGE_CURRENT 7 | 37 | #define ADC_CHARGE_CURRENT 7 |
38 | #define ADC_DISCHARGE_CURRENT 8 | 38 | #define ADC_DISCHARGE_CURRENT 8 |
39 | #define ADC_APS_VOLTAGE 9 | 39 | #define ADC_APS_VOLTAGE 9 |
40 | #define ADC_BATTERY_POWER 10 | 40 | #define NUM_ADC_CHANNELS 10 |
41 | #define NUM_ADC_CHANNELS 11 | ||
42 | 41 | ||
43 | /* ADC sampling rates */ | 42 | /* ADC sampling rates */ |
44 | #define AXP_ADC_RATE_25HZ 0 | 43 | #define AXP_ADC_RATE_25HZ 0 |
@@ -123,7 +122,6 @@ extern int axp_input_status(void); | |||
123 | extern int axp_adc_read(int adc); | 122 | extern int axp_adc_read(int adc); |
124 | extern int axp_adc_read_raw(int adc); | 123 | extern int axp_adc_read_raw(int adc); |
125 | extern int axp_adc_conv_raw(int adc, int value); | 124 | extern int axp_adc_conv_raw(int adc, int value); |
126 | extern int axp_adc_get_enabled(void); | ||
127 | extern void axp_adc_set_enabled(int adc_bits); | 125 | extern void axp_adc_set_enabled(int adc_bits); |
128 | extern int axp_adc_get_rate(void); | 126 | extern int axp_adc_get_rate(void); |
129 | extern void axp_adc_set_rate(int rate); | 127 | 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) | |||
63 | /* Set lowest sample rate */ | 63 | /* Set lowest sample rate */ |
64 | axp_adc_set_rate(AXP_ADC_RATE_25HZ); | 64 | axp_adc_set_rate(AXP_ADC_RATE_25HZ); |
65 | 65 | ||
66 | /* Ensure battery voltage ADC is enabled */ | 66 | /* Enable required ADCs */ |
67 | int bits = axp_adc_get_enabled(); | 67 | axp_adc_set_enabled( |
68 | bits |= (1 << ADC_BATTERY_VOLTAGE); | 68 | (1 << ADC_BATTERY_VOLTAGE) | |
69 | axp_adc_set_enabled(bits); | 69 | (1 << ADC_CHARGE_CURRENT) | |
70 | (1 << ADC_DISCHARGE_CURRENT) | | ||
71 | (1 << ADC_VBUS_VOLTAGE) | | ||
72 | (1 << ADC_VBUS_CURRENT) | | ||
73 | (1 << ADC_INTERNAL_TEMP) | | ||
74 | (1 << ADC_APS_VOLTAGE)); | ||
70 | 75 | ||
71 | /* Turn on all power outputs */ | 76 | /* Turn on all power outputs */ |
72 | i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, | 77 | 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) | |||
61 | /* Set lowest sample rate */ | 61 | /* Set lowest sample rate */ |
62 | axp_adc_set_rate(AXP_ADC_RATE_25HZ); | 62 | axp_adc_set_rate(AXP_ADC_RATE_25HZ); |
63 | 63 | ||
64 | /* Ensure battery voltage ADC is enabled */ | 64 | /* Enable required ADCs */ |
65 | int bits = axp_adc_get_enabled(); | 65 | axp_adc_set_enabled( |
66 | bits |= (1 << ADC_BATTERY_VOLTAGE); | 66 | (1 << ADC_BATTERY_VOLTAGE) | |
67 | axp_adc_set_enabled(bits); | 67 | (1 << ADC_CHARGE_CURRENT) | |
68 | (1 << ADC_DISCHARGE_CURRENT) | | ||
69 | (1 << ADC_VBUS_VOLTAGE) | | ||
70 | (1 << ADC_VBUS_CURRENT) | | ||
71 | (1 << ADC_INTERNAL_TEMP) | | ||
72 | (1 << ADC_APS_VOLTAGE)); | ||
68 | 73 | ||
69 | /* Turn on all power outputs */ | 74 | /* Turn on all power outputs */ |
70 | i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, | 75 | 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) | |||
78 | cw2015_init(); | 78 | cw2015_init(); |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | /* Set lowest sample rate */ | ||
82 | axp_adc_set_rate(AXP_ADC_RATE_25HZ); | ||
83 | |||
84 | /* Enable required ADCs */ | ||
85 | axp_adc_set_enabled( | ||
86 | (1 << ADC_BATTERY_VOLTAGE) | | ||
87 | (1 << ADC_CHARGE_CURRENT) | | ||
88 | (1 << ADC_DISCHARGE_CURRENT) | | ||
89 | (1 << ADC_VBUS_VOLTAGE) | | ||
90 | (1 << ADC_VBUS_CURRENT) | | ||
91 | (1 << ADC_INTERNAL_TEMP) | | ||
92 | (1 << ADC_APS_VOLTAGE)); | ||
93 | |||
81 | /* Change supply voltage from the default of 1250 mV to 1200 mV, | 94 | /* Change supply voltage from the default of 1250 mV to 1200 mV, |
82 | * this matches the original firmware's settings. Didn't observe | 95 | * this matches the original firmware's settings. Didn't observe |
83 | * any obviously bad behavior at 1250 mV, but better to be safe. */ | 96 | * any obviously bad behavior at 1250 mV, but better to be safe. */ |