diff options
Diffstat (limited to 'firmware/drivers/axp173.c')
-rw-r--r-- | firmware/drivers/axp173.c | 105 |
1 files changed, 81 insertions, 24 deletions
diff --git a/firmware/drivers/axp173.c b/firmware/drivers/axp173.c index 22417650fc..0c9b9c81a4 100644 --- a/firmware/drivers/axp173.c +++ b/firmware/drivers/axp173.c | |||
@@ -35,21 +35,22 @@ static const struct axp173_adc_info { | |||
35 | uint8_t en_reg; | 35 | uint8_t en_reg; |
36 | uint8_t en_bit; | 36 | uint8_t en_bit; |
37 | } axp173_adc_info[NUM_ADC_CHANNELS] = { | 37 | } axp173_adc_info[NUM_ADC_CHANNELS] = { |
38 | {0x56, 0x82, 5}, /* ACIN_VOLTAGE */ | 38 | {0x56, AXP173_REG_ADCENABLE1, 5}, /* ACIN_VOLTAGE */ |
39 | {0x58, 0x82, 4}, /* ACIN_CURRENT */ | 39 | {0x58, AXP173_REG_ADCENABLE1, 4}, /* ACIN_CURRENT */ |
40 | {0x5a, 0x82, 3}, /* VBUS_VOLTAGE */ | 40 | {0x5a, AXP173_REG_ADCENABLE1, 3}, /* VBUS_VOLTAGE */ |
41 | {0x5c, 0x82, 2}, /* VBUS_CURRENT */ | 41 | {0x5c, AXP173_REG_ADCENABLE1, 2}, /* VBUS_CURRENT */ |
42 | {0x5e, 0x83, 7}, /* INTERNAL_TEMP */ | 42 | {0x5e, AXP173_REG_ADCENABLE2, 7}, /* INTERNAL_TEMP */ |
43 | {0x62, 0x82, 1}, /* TS_INPUT */ | 43 | {0x62, AXP173_REG_ADCENABLE1, 1}, /* TS_INPUT */ |
44 | {0x78, 0x82, 7}, /* BATTERY_VOLTAGE */ | 44 | {0x78, AXP173_REG_ADCENABLE1, 7}, /* BATTERY_VOLTAGE */ |
45 | {0x7a, 0x82, 6}, /* CHARGE_CURRENT */ | 45 | {0x7a, AXP173_REG_ADCENABLE1, 6}, /* CHARGE_CURRENT */ |
46 | {0x7c, 0x82, 6}, /* DISCHARGE_CURRENT */ | 46 | {0x7c, AXP173_REG_ADCENABLE1, 6}, /* DISCHARGE_CURRENT */ |
47 | {0x7e, 0x82, 1}, /* APS_VOLTAGE */ | 47 | {0x7e, AXP173_REG_ADCENABLE1, 1}, /* APS_VOLTAGE */ |
48 | {0x70, 0xff, 0}, /* BATTERY_POWER */ | 48 | {0x70, 0xff, 0}, /* BATTERY_POWER */ |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct axp173 { | 51 | static struct axp173 { |
52 | int adc_enable; | 52 | int adc_enable; |
53 | int chargecurrent_setting; | ||
53 | } axp173; | 54 | } axp173; |
54 | 55 | ||
55 | static void axp173_init_enabled_adcs(void) | 56 | static void axp173_init_enabled_adcs(void) |
@@ -58,7 +59,8 @@ static void axp173_init_enabled_adcs(void) | |||
58 | 59 | ||
59 | /* Read enabled ADCs from the hardware */ | 60 | /* Read enabled ADCs from the hardware */ |
60 | uint8_t regs[2]; | 61 | uint8_t regs[2]; |
61 | int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, 0x82, 2, ®s[0]); | 62 | int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, |
63 | AXP173_REG_ADCENABLE1, 2, ®s[0]); | ||
62 | if(rc != I2C_STATUS_OK) | 64 | if(rc != I2C_STATUS_OK) |
63 | return; | 65 | return; |
64 | 66 | ||
@@ -68,7 +70,7 @@ static void axp173_init_enabled_adcs(void) | |||
68 | if(info[i].en_reg == 0xff) | 70 | if(info[i].en_reg == 0xff) |
69 | continue; | 71 | continue; |
70 | 72 | ||
71 | if(regs[info[i].en_reg - 0x82] & info[i].en_bit) | 73 | if(regs[info[i].en_reg - AXP173_REG_ADCENABLE1] & info[i].en_bit) |
72 | axp173.adc_enable |= 1 << i; | 74 | axp173.adc_enable |= 1 << i; |
73 | } | 75 | } |
74 | 76 | ||
@@ -87,12 +89,16 @@ void axp173_init(void) | |||
87 | int bits = axp173.adc_enable; | 89 | int bits = axp173.adc_enable; |
88 | bits |= (1 << ADC_DISCHARGE_CURRENT); | 90 | bits |= (1 << ADC_DISCHARGE_CURRENT); |
89 | axp173_adc_set_enabled(bits); | 91 | axp173_adc_set_enabled(bits); |
92 | |||
93 | /* Read the maximum charging current */ | ||
94 | int value = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, AXP173_REG_CHARGECONTROL1); | ||
95 | axp173.chargecurrent_setting = (value < 0) ? -1 : value; | ||
90 | } | 96 | } |
91 | 97 | ||
92 | /* TODO: this can STILL indicate some false positives! */ | 98 | /* TODO: this can STILL indicate some false positives! */ |
93 | int axp173_battery_status(void) | 99 | int axp173_battery_status(void) |
94 | { | 100 | { |
95 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x00); | 101 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, AXP173_REG_POWERSTATUS); |
96 | if(r >= 0) { | 102 | if(r >= 0) { |
97 | /* Charging bit indicates we're currently charging */ | 103 | /* Charging bit indicates we're currently charging */ |
98 | if((r & 0x04) != 0) | 104 | if((r & 0x04) != 0) |
@@ -124,7 +130,7 @@ int axp173_input_status(void) | |||
124 | int input_status = AXP173_INPUT_BATTERY; | 130 | int input_status = AXP173_INPUT_BATTERY; |
125 | #endif | 131 | #endif |
126 | 132 | ||
127 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x00); | 133 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, AXP173_REG_POWERSTATUS); |
128 | if(r < 0) | 134 | if(r < 0) |
129 | return input_status; | 135 | return input_status; |
130 | 136 | ||
@@ -138,7 +144,7 @@ int axp173_input_status(void) | |||
138 | 144 | ||
139 | #ifdef HAVE_BATTERY_SWITCH | 145 | #ifdef HAVE_BATTERY_SWITCH |
140 | /* Check for battery presence if target defines it as removable */ | 146 | /* Check for battery presence if target defines it as removable */ |
141 | r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x01); | 147 | r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, AXP173_REG_CHARGESTATUS); |
142 | if(r >= 0 && (r & 0x20) != 0) | 148 | if(r >= 0 && (r & 0x20) != 0) |
143 | input_status |= AXP173_INPUT_BATTERY; | 149 | input_status |= AXP173_INPUT_BATTERY; |
144 | #endif | 150 | #endif |
@@ -251,13 +257,13 @@ void axp173_adc_set_enabled(int adc_bits) | |||
251 | } | 257 | } |
252 | 258 | ||
253 | /* Update the configuration */ | 259 | /* Update the configuration */ |
254 | i2c_reg_write(AXP173_BUS, AXP173_ADDR, 0x82, 2, ®s[0]); | 260 | i2c_reg_write(AXP173_BUS, AXP173_ADDR, AXP173_REG_ADCENABLE1, 2, ®s[0]); |
255 | axp173.adc_enable = adc_bits; | 261 | axp173.adc_enable = adc_bits; |
256 | } | 262 | } |
257 | 263 | ||
258 | int axp173_adc_get_rate(void) | 264 | int axp173_adc_get_rate(void) |
259 | { | 265 | { |
260 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x84); | 266 | int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, AXP173_REG_ADCSAMPLERATE); |
261 | if(r < 0) | 267 | if(r < 0) |
262 | return AXP173_ADC_RATE_100HZ; /* an arbitrary value */ | 268 | return AXP173_ADC_RATE_100HZ; /* an arbitrary value */ |
263 | 269 | ||
@@ -266,7 +272,7 @@ int axp173_adc_get_rate(void) | |||
266 | 272 | ||
267 | void axp173_adc_set_rate(int rate) | 273 | void axp173_adc_set_rate(int rate) |
268 | { | 274 | { |
269 | i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x84, | 275 | i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, AXP173_REG_ADCSAMPLERATE, |
270 | 0xc0, (rate & 3) << 6, NULL); | 276 | 0xc0, (rate & 3) << 6, NULL); |
271 | } | 277 | } |
272 | 278 | ||
@@ -278,7 +284,8 @@ static uint32_t axp173_cc_parse(const uint8_t* buf) | |||
278 | void axp173_cc_read(uint32_t* charge, uint32_t* discharge) | 284 | void axp173_cc_read(uint32_t* charge, uint32_t* discharge) |
279 | { | 285 | { |
280 | uint8_t buf[8]; | 286 | uint8_t buf[8]; |
281 | int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, 0xb0, 8, &buf[0]); | 287 | int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, |
288 | AXP173_REG_COULOMBCOUNTERBASE, 8, &buf[0]); | ||
282 | if(rc != I2C_STATUS_OK) { | 289 | if(rc != I2C_STATUS_OK) { |
283 | if(charge) | 290 | if(charge) |
284 | *charge = 0; | 291 | *charge = 0; |
@@ -295,19 +302,63 @@ void axp173_cc_read(uint32_t* charge, uint32_t* discharge) | |||
295 | 302 | ||
296 | void axp173_cc_clear(void) | 303 | void axp173_cc_clear(void) |
297 | { | 304 | { |
298 | i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0xb8, 5, 1, NULL); | 305 | i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, |
306 | AXP173_REG_COULOMBCOUNTERCTRL, 5, 1, NULL); | ||
299 | } | 307 | } |
300 | 308 | ||
301 | void axp173_cc_enable(bool en) | 309 | void axp173_cc_enable(bool en) |
302 | { | 310 | { |
303 | i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0xb8, 7, en ? 1 : 0, NULL); | 311 | i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, |
312 | AXP173_REG_COULOMBCOUNTERCTRL, 7, en ? 1 : 0, NULL); | ||
313 | } | ||
314 | |||
315 | static const int chargecurrent_tbl[] = { | ||
316 | 100, 190, 280, 360, | ||
317 | 450, 550, 630, 700, | ||
318 | 780, 880, 960, 1000, | ||
319 | 1080, 1160, 1240, 1320, | ||
320 | }; | ||
321 | |||
322 | static const int chargecurrent_tblsz = sizeof(chargecurrent_tbl)/sizeof(int); | ||
323 | |||
324 | void axp173_set_charge_current(int maxcurrent) | ||
325 | { | ||
326 | /* Find the charge current just higher than maxcurrent */ | ||
327 | int value = 0; | ||
328 | while(value < chargecurrent_tblsz && | ||
329 | chargecurrent_tbl[value] <= maxcurrent) | ||
330 | ++value; | ||
331 | |||
332 | /* Select the next lower current, the greatest current <= maxcurrent */ | ||
333 | if(value >= chargecurrent_tblsz) | ||
334 | value = chargecurrent_tblsz - 1; | ||
335 | else if(value > 0) | ||
336 | --value; | ||
337 | |||
338 | /* Don't issue i2c write if desired setting is already in use */ | ||
339 | if(value == axp173.chargecurrent_setting) | ||
340 | return; | ||
341 | |||
342 | /* Update register */ | ||
343 | i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, | ||
344 | AXP173_REG_CHARGECONTROL1, 0x0f, value, NULL); | ||
345 | axp173.chargecurrent_setting = value; | ||
346 | } | ||
347 | |||
348 | int axp173_get_charge_current(void) | ||
349 | { | ||
350 | if(axp173.chargecurrent_setting < 0) | ||
351 | return chargecurrent_tbl[0]; | ||
352 | else | ||
353 | return chargecurrent_tbl[axp173.chargecurrent_setting]; | ||
304 | } | 354 | } |
305 | 355 | ||
306 | #ifndef BOOTLOADER | 356 | #ifndef BOOTLOADER |
307 | #define AXP173_DEBUG_BATTERY_STATUS 0 | 357 | #define AXP173_DEBUG_BATTERY_STATUS 0 |
308 | #define AXP173_DEBUG_INPUT_STATUS 1 | 358 | #define AXP173_DEBUG_INPUT_STATUS 1 |
309 | #define AXP173_DEBUG_ADC_RATE 2 | 359 | #define AXP173_DEBUG_CHARGE_CURRENT 2 |
310 | #define AXP173_DEBUG_FIRST_ADC 3 | 360 | #define AXP173_DEBUG_ADC_RATE 3 |
361 | #define AXP173_DEBUG_FIRST_ADC 4 | ||
311 | #define AXP173_DEBUG_ENTRIES (AXP173_DEBUG_FIRST_ADC + NUM_ADC_CHANNELS) | 362 | #define AXP173_DEBUG_ENTRIES (AXP173_DEBUG_FIRST_ADC + NUM_ADC_CHANNELS) |
312 | 363 | ||
313 | static int axp173_debug_menu_cb(int action, struct gui_synclist* lists) | 364 | static int axp173_debug_menu_cb(int action, struct gui_synclist* lists) |
@@ -377,6 +428,12 @@ static const char* axp173_debug_menu_get_name(int item, void* data, | |||
377 | return buf; | 428 | return buf; |
378 | } break; | 429 | } break; |
379 | 430 | ||
431 | case AXP173_DEBUG_CHARGE_CURRENT: { | ||
432 | int current = axp173_get_charge_current(); | ||
433 | snprintf(buf, buflen, "Max charge current: %d mA", current); | ||
434 | return buf; | ||
435 | } break; | ||
436 | |||
380 | case AXP173_DEBUG_ADC_RATE: { | 437 | case AXP173_DEBUG_ADC_RATE: { |
381 | int rate = 25 << axp173_adc_get_rate(); | 438 | int rate = 25 << axp173_adc_get_rate(); |
382 | snprintf(buf, buflen, "ADC sample rate: %d Hz", rate); | 439 | snprintf(buf, buflen, "ADC sample rate: %d Hz", rate); |