summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/axp-pmu.c146
-rw-r--r--firmware/export/axp-pmu.h4
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c13
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c13
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c13
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
41struct axp_supply_info { 43struct axp_supply_info {
@@ -49,17 +51,16 @@ struct axp_supply_info {
49}; 51};
50 52
51static const struct axp_adc_info axp_adc_info[NUM_ADC_CHANNELS] = { 53static 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
65static const struct axp_supply_info axp_supply_info[AXP_NUM_SUPPLIES] = { 66static 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
129static struct axp_driver {
130 int adc_enable;
131} axp;
132
133static 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, &regs[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
161void axp_init(void) 130void 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
171void axp_supply_set_voltage(int supply, int voltage) 134void axp_supply_set_voltage(int supply, int voltage)
@@ -294,22 +257,15 @@ int axp_adc_read(int adc)
294 257
295int axp_adc_read_raw(int adc) 258int 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
318int axp_adc_conv_raw(int adc, int value) 274int 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
356int axp_adc_get_enabled(void)
357{
358 return axp.adc_enable;
359} 280}
360 281
361void axp_adc_set_enabled(int adc_bits) 282void 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, &regs[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
395int axp_adc_get_rate(void) 305int 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);
123extern int axp_adc_read(int adc); 122extern int axp_adc_read(int adc);
124extern int axp_adc_read_raw(int adc); 123extern int axp_adc_read_raw(int adc);
125extern int axp_adc_conv_raw(int adc, int value); 124extern int axp_adc_conv_raw(int adc, int value);
126extern int axp_adc_get_enabled(void);
127extern void axp_adc_set_enabled(int adc_bits); 125extern void axp_adc_set_enabled(int adc_bits);
128extern int axp_adc_get_rate(void); 126extern int axp_adc_get_rate(void);
129extern void axp_adc_set_rate(int rate); 127extern 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. */