summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-04-21 01:45:34 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-04-21 18:31:55 +0000
commit088ebb5fac02932178fe0da31dd8966472225bdf (patch)
tree68f21b20a7eb0a1c1479033ccf031a18701afa6b
parentf6d3680cb84c05d3037650b12e6f8c258b2a6758 (diff)
downloadrockbox-088ebb5fac02932178fe0da31dd8966472225bdf.tar.gz
rockbox-088ebb5fac02932178fe0da31dd8966472225bdf.zip
Minor enhancements to axp173 driver
- Added register names to reduce usage of magic numbers - Added function to control max charging current, needed for USB - Corrected comment about axp173, since FiiO M3K has an axp192 Change-Id: I6604ce8d44e5a2ee84061cf042d17ccc4734ac57
-rw-r--r--firmware/drivers/axp173.c105
-rw-r--r--firmware/export/axp173.h24
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c10
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c13
4 files changed, 120 insertions, 32 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);
diff --git a/firmware/export/axp173.h b/firmware/export/axp173.h
index 60519138e1..34f0c2ec19 100644
--- a/firmware/export/axp173.h
+++ b/firmware/export/axp173.h
@@ -25,6 +25,7 @@
25#include <stdbool.h> 25#include <stdbool.h>
26#include <stdint.h> 26#include <stdint.h>
27 27
28/* ADC channels */
28#define ADC_ACIN_VOLTAGE 0 29#define ADC_ACIN_VOLTAGE 0
29#define ADC_ACIN_CURRENT 1 30#define ADC_ACIN_CURRENT 1
30#define ADC_VBUS_VOLTAGE 2 31#define ADC_VBUS_VOLTAGE 2
@@ -55,6 +56,25 @@
55#define AXP173_INPUT_BATTERY (1 << 2) 56#define AXP173_INPUT_BATTERY (1 << 2)
56#define AXP173_INPUT_EXTERNAL (AXP173_INPUT_AC|AXP173_INPUT_USB) 57#define AXP173_INPUT_EXTERNAL (AXP173_INPUT_AC|AXP173_INPUT_USB)
57 58
59/* Registers -- common to AXP173 and AXP192 (incomplete listing) */
60#define AXP173_REG_POWERSTATUS 0x00
61#define AXP173_REG_CHARGESTATUS 0x01
62#define AXP173_REG_PWROUTPUTCTRL 0x12
63#define AXP173_REG_SHUTDOWNLEDCTRL 0x32
64#define AXP173_REG_CHARGECONTROL1 0x33
65#define AXP173_REG_DCDCWORKINGMODE 0x80
66#define AXP173_REG_ADCENABLE1 0x82
67#define AXP173_REG_ADCENABLE2 0x83
68#define AXP173_REG_ADCSAMPLERATE 0x84
69#define AXP173_REG_COULOMBCOUNTERBASE 0xb0
70#define AXP173_REG_COULOMBCOUNTERCTRL 0xb8
71
72/* AXP192-only registers (incomplete listing) */
73#define AXP192_REG_GPIO0FUNCTION 0x90
74#define AXP192_REG_GPIO1FUNCTION 0x92
75#define AXP192_REG_GPIO2FUNCTION 0x93
76#define AXP192_REG_GPIOSTATE1 0x94
77
58/* Must be called from power_init() to initialize the driver state */ 78/* Must be called from power_init() to initialize the driver state */
59extern void axp173_init(void); 79extern void axp173_init(void);
60 80
@@ -88,6 +108,10 @@ extern void axp173_cc_read(uint32_t* charge, uint32_t* discharge);
88extern void axp173_cc_clear(void); 108extern void axp173_cc_clear(void);
89extern void axp173_cc_enable(bool en); 109extern void axp173_cc_enable(bool en);
90 110
111/* Set/get maximum charging current in milliamps */
112extern void axp173_set_charge_current(int maxcurrent);
113extern int axp173_get_charge_current(void);
114
91/* Debug menu */ 115/* Debug menu */
92extern bool axp173_debug_menu(void); 116extern bool axp173_debug_menu(void);
93 117
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
index db5ece10b0..e27e0be464 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
@@ -23,13 +23,14 @@
23#include "kernel.h" 23#include "kernel.h"
24#include "backlight.h" 24#include "backlight.h"
25#include "panic.h" 25#include "panic.h"
26#include "lcd.h" 26#include "axp173.h"
27#include "gpio-x1000.h" 27#include "gpio-x1000.h"
28#include "i2c-x1000.h" 28#include "i2c-x1000.h"
29#include <string.h> 29#include <string.h>
30#include <stdbool.h> 30#include <stdbool.h>
31 31
32#ifndef BOOTLOADER 32#ifndef BOOTLOADER
33# include "lcd.h"
33# include "font.h" 34# include "font.h"
34#endif 35#endif
35 36
@@ -409,7 +410,7 @@ static int hp_detect_tmo_cb(struct timeout* tmo)
409static void hp_detect_init(void) 410static void hp_detect_init(void)
410{ 411{
411 static struct timeout tmo; 412 static struct timeout tmo;
412 static const uint8_t gpio_reg = 0x94; 413 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1;
413 static i2c_descriptor desc = { 414 static i2c_descriptor desc = {
414 .slave_addr = AXP173_ADDR, 415 .slave_addr = AXP173_ADDR,
415 .bus_cond = I2C_START | I2C_STOP, 416 .bus_cond = I2C_START | I2C_STOP,
@@ -423,9 +424,8 @@ static void hp_detect_init(void)
423 .next = NULL, 424 .next = NULL,
424 }; 425 };
425 426
426 /* Headphone detect is wired to an undocumented GPIO on the AXP173. 427 /* Headphone detect is wired to AXP192 GPIO: set it to input state */
427 * This sets it to input mode so we can see the pin state. */ 428 i2c_reg_write1(AXP173_BUS, AXP173_ADDR, AXP192_REG_GPIO2FUNCTION, 0x01);
428 i2c_reg_write1(AXP173_BUS, AXP173_ADDR, 0x93, 0x01);
429 429
430 /* Get an initial reading before startup */ 430 /* Get an initial reading before startup */
431 int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, gpio_reg); 431 int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, gpio_reg);
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
index b4923835aa..a3760d145a 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
@@ -68,8 +68,14 @@ void power_init(void)
68 axp173_adc_set_enabled(bits); 68 axp173_adc_set_enabled(bits);
69 69
70 /* Turn on all power outputs */ 70 /* Turn on all power outputs */
71 i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x12, 0, 0x5f, NULL); 71 i2c_reg_modify1(AXP173_BUS, AXP173_ADDR,
72 i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x80, 0, 0xc0, NULL); 72 AXP173_REG_PWROUTPUTCTRL, 0, 0x5f, NULL);
73 i2c_reg_modify1(AXP173_BUS, AXP173_ADDR,
74 AXP173_REG_DCDCWORKINGMODE, 0, 0xc0, NULL);
75
76 /* Set the default charging current. This is the same as the
77 * OF's setting, although it's not strictly within the USB spec. */
78 axp173_set_charge_current(780);
73 79
74 /* Short delay to give power outputs time to stabilize */ 80 /* Short delay to give power outputs time to stabilize */
75 mdelay(5); 81 mdelay(5);
@@ -82,7 +88,8 @@ void adc_init(void)
82void power_off(void) 88void power_off(void)
83{ 89{
84 /* Set the shutdown bit */ 90 /* Set the shutdown bit */
85 i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0x32, 7, 1, NULL); 91 i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR,
92 AXP173_REG_SHUTDOWNLEDCTRL, 7, 1, NULL);
86 while(1); 93 while(1);
87} 94}
88 95