summaryrefslogtreecommitdiff
path: root/firmware/drivers/axp173.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/axp173.c')
-rw-r--r--firmware/drivers/axp173.c105
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
51static struct axp173 { 51static struct axp173 {
52 int adc_enable; 52 int adc_enable;
53 int chargecurrent_setting;
53} axp173; 54} axp173;
54 55
55static void axp173_init_enabled_adcs(void) 56static 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, &regs[0]); 62 int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR,
63 AXP173_REG_ADCENABLE1, 2, &regs[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! */
93int axp173_battery_status(void) 99int 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, &regs[0]); 260 i2c_reg_write(AXP173_BUS, AXP173_ADDR, AXP173_REG_ADCENABLE1, 2, &regs[0]);
255 axp173.adc_enable = adc_bits; 261 axp173.adc_enable = adc_bits;
256} 262}
257 263
258int axp173_adc_get_rate(void) 264int 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
267void axp173_adc_set_rate(int rate) 273void 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)
278void axp173_cc_read(uint32_t* charge, uint32_t* discharge) 284void 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
296void axp173_cc_clear(void) 303void 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
301void axp173_cc_enable(bool en) 309void 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
315static 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
322static const int chargecurrent_tblsz = sizeof(chargecurrent_tbl)/sizeof(int);
323
324void 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
348int 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
313static int axp173_debug_menu_cb(int action, struct gui_synclist* lists) 364static 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);