AXP2101 PMU eFuse configuration after replacement – help needed

Hi everyone,

I accidentally inserted my battery in reverse, which killed the AXP2101 PMU on my PicoCalc. I replaced it with an AXP2101 sourced from LCSC, but ran into some issues I hope someone here can help with.

ClockworkPi support unfortunately wasn’t very helpful — they just pointed me to Google for the datasheet — so I’m hoping the community might have more hands-on experience.

After some digging, I realized the original AXP2101 appears to have custom factory eFuse settings that differ from the picocalc version. Because of this, I had to modify the STM32 firmware to set the output voltages correctly. Could anyone confirm whether all rails need to be set to 3.3V? Specifically: DCDC1, ALDO1–4, and BLDO1/2?

The second problem is with power control. As soon as I connect the battery or USB, the device powers on automatically. I can live with that, but the bigger issue is that I can’t turn it off — pressing the power button causes it to immediately turn back on.

As a workaround, I’ve modified the STM32 firmware to put the PMIC into “sleep” mode turning of the powerrails instead of a proper shutdown, which works for now but doesn’t feel like the right solution.

Questions

  • Has anyone else run into this after replacing the AXP2101?
  • Is there any documentation on the specific eFuse configuration used in the PicoCalc?
  • Is there a known source for a pre-configured replacement AXP2101 with the correct eFuse settings?
  • Is there a cleaner workaround for the power button issue when using a “vanilla” AXP2101?

Any help or pointers would be greatly appreciated. Thanks!

1 Like

OOF.

The efuses should be programmable, the hard part is getting the programming method. But it looks like they’re basically only setting defaults for various registers which can be overridden. So your problem is really just with the registers that have changed defaults that the firmware isn’t explicitly setting, and a modified firmware should be enough to restore proper function.

Just need someone to make a register dump from their stock picocalc’s axp2101 so you can check the differences. I’ll see what I can do.

A replacement board is on its way. Maybe I’ll compare the efuses of the chips and see what I can do about patching the firmware to support standard AXP2101 versions.

Got my replacement PCB yesterday and i read the default register values as a first step in the stm32 firmware. But for now i will use the replacementboard.

Original PicoCalc AXP2101 registers after power on:

============================================================
  AXP2101 Full Register Dump (Factory Defaults)
  Must be read BEFORE any PMU configuration!
============================================================
IC_TYPE       (0x03): 0x4A  [0x4A = AXP2101]
STATUS1       (0x00): 0x20  [VBUS_good=1  BATFET=0  BAT_present=0]
STATUS2       (0x01): 0x15  [BatDir=00  SysOn=1  chg_state=5]
PWRON_STATUS  (0x20): 0x01
PWROFF_STATUS (0x21): 0x00

--- Full Register Dump 0x00..0xAF ---
      |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
------+------------------------------------------------
 0x00 | 20 15 00 4A 00 00 00 00 0C 00 00 00 00 00 00 00
 0x10 | 34 00 00 03 65 06 04 00 0A 06 A1 00 00 00 09 00
 0x20 | 01 00 04 3F 00 19 08 16 00 00 00 00 00 00 00 00
 0x30 | 01 00 00 00 07 CB 82 58 00 00 00 00 00 00 00 00
 0x40 | FF FC 5F 00 00 00 00 00 40 81 00 00 00 00 00 00
 0x50 | 12 00 02 01 29 58 3E 4C 00 14 37 1E 02 58 00 00
 0x60 | 02 05 13 15 03 02 01 E6 01 01 03 00 00 00 00 00
 0x70 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x80 | 01 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x90 | 3F 00 1C 1C 1C 1C 1E 1E 00 00 00 00 00 00 00 00
 0xA0 | 00 BE 00 EA 00 00 00 00 00 00 00 03 00 00 00 00

--- eFuse-backed Registers (OTP Defaults, per Datasheet) ---
    Reg  | Val  | Description
    -----+------+-----------------------------------------------
    0x12 | 0x00 | BATFET_CTRL     bit[3]: BATFET enable in power-off (battery only)
    0x22 | 0x04 | PWROFF_EN       bit[1]: PWRON>OFFLEVEL as poweroff source
                                  bit[0]: power-off(0) or restart(1) on btn
    0x24 | 0x00 | VOFF_SET        bits[2:0]: VSYS power-down threshold (2.6-3.3V)
    0x25 | 0x19 | PWROK_SEQU_CTRL bits[1:0]: PWROK delay after all outputs valid
    0x27 | 0x16 | IRQ_OFF_ON_LVL  bits[1:0]: PWRON key on-level (128ms/512ms/1s/2s)
    0x50 | 0x12 | TS_PIN_CTRL     bit[4]: TS function (temp sensor vs. fixed input)
                                  bits[3:2]: TS current source on/off mode
    0x58 | 0x00 | JIETA_EN_CTRL   bit[0]: JEITA standard enable
    0x62 | 0x13 | ICC_CHG_SET     bits[4:0]: CC charge current limit (0-1500mA)
    0x69 | 0x01 | CHGLED_SET_CTRL bits[2:1]: CHGLED display function (type A/B/reg)
    0x80 | 0x01 | DCDC_ONOFF_DVM  bit[3]: DCDC4 enable
                                  bit[2]: DCDC3 enable
                                  bit[1]: DCDC2 enable
                                  bit[0]: DCDC1 enable
    0x82 | 0x12 | DCDC1_VOL       bits[4:0]: DCDC1 startup voltage (1.5-3.4V)
    0x83 | 0x00 | DCDC2_VOL       bits[6:0]: DCDC2 startup voltage (0.5-1.54V)
    0x84 | 0x00 | DCDC3_VOL       bits[6:0]: DCDC3 startup voltage (0.5-1.54V)
    0x85 | 0x00 | DCDC4_VOL       bits[6:0]: DCDC4 startup voltage (0.5-1.84V)
    0x90 | 0x3F | LDO_ONOFF_CTRL0 bit[7]: DLDO1  bit[6]: CPUSLDO  bit[5]: BLDO2
                                  bit[4]: BLDO1  bit[3]: ALDO4  bit[2]: ALDO3
                                  bit[1]: ALDO2  bit[0]: ALDO1  (enable defaults)
    0x91 | 0x00 | LDO_ONOFF_CTRL1 bit[0]: DLDO2 enable default
    0x92 | 0x1C | ALDO1_VOL       bits[4:0]: ALDO1 startup voltage (0.5-3.5V)
    0x93 | 0x1C | ALDO2_VOL       bits[4:0]: ALDO2 startup voltage (0.5-3.5V)
    0x94 | 0x1C | ALDO3_VOL       bits[4:0]: ALDO3 startup voltage (0.5-3.5V)
    0x95 | 0x1C | ALDO4_VOL       bits[4:0]: ALDO4 startup voltage (0.5-3.5V)
    0x96 | 0x1E | BLDO1_VOL       bits[4:0]: BLDO1 startup voltage (0.5-3.5V)
    0x97 | 0x1E | BLDO2_VOL       bits[4:0]: BLDO2 startup voltage (0.5-3.5V)
    0x98 | 0x00 | CPUSLDO_VOL     bits[4:0]: CPUSLDO startup voltage (0.5-1.4V)
    0x99 | 0x00 | DLDO1_VOL       bits[4:0]: DLDO1 startup voltage (0.5-3.4V)
    0x9A | 0x00 | DLDO2_VOL       bits[4:0]: DLDO2 startup voltage (0.5-1.4V)
============================================================


LCSC replacement AXP2101 registers after power on:

============================================================
  AXP2101 Full Register Dump (Factory Defaults)
  Must be read BEFORE any PMU configuration!
============================================================
IC_TYPE       (0x03): 0x4A  [0x4A = AXP2101]
STATUS1       (0x00): 0x20  [VBUS_good=1  BATFET=0  BAT_present=0]
STATUS2       (0x01): 0x15  [BatDir=00  SysOn=1  chg_state=5]
PWRON_STATUS  (0x20): 0x02
PWROFF_STATUS (0x21): 0x00

--- Full Register Dump 0x00..0xAF ---
      |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
------+------------------------------------------------
 0x00 | 20 15 00 4A 00 00 00 00 04 00 00 00 00 00 00 00
 0x10 | 34 00 00 03 65 06 04 00 0A 06 A1 00 00 00 09 00
 0x20 | 02 00 06 3F 00 18 08 15 00 00 00 00 00 00 00 00
 0x30 | 01 00 00 00 07 91 82 58 00 00 00 00 00 00 00 00
 0x40 | FF FC 5F 00 00 00 00 00 40 80 40 00 00 00 00 00
 0x50 | 0A 00 02 01 29 58 3E 4C 00 14 37 1E 02 58 00 00
 0x60 | 02 05 09 15 03 02 01 E6 01 01 03 00 00 00 00 00
 0x70 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x80 | 0F 00 12 28 28 3C 19 00 00 00 00 00 00 00 00 00
 0x90 | 55 00 0D 17 1C 18 0D 17 08 00 0E 00 00 00 00 00
 0xA0 | 00 82 00 1C 00 00 00 00 00 00 00 03 00 00 00 00

--- eFuse-backed Registers (OTP Defaults, per Datasheet) ---
    Reg  | Val  | Description
    -----+------+-----------------------------------------------
    0x12 | 0x00 | BATFET_CTRL     bit[3]: BATFET enable in power-off (battery only)
    0x22 | 0x06 | PWROFF_EN       bit[1]: PWRON>OFFLEVEL as poweroff source
                                  bit[0]: power-off(0) or restart(1) on btn
    0x24 | 0x00 | VOFF_SET        bits[2:0]: VSYS power-down threshold (2.6-3.3V)
    0x25 | 0x18 | PWROK_SEQU_CTRL bits[1:0]: PWROK delay after all outputs valid
    0x27 | 0x15 | IRQ_OFF_ON_LVL  bits[1:0]: PWRON key on-level (128ms/512ms/1s/2s)
    0x50 | 0x0A | TS_PIN_CTRL     bit[4]: TS function (temp sensor vs. fixed input)
                                  bits[3:2]: TS current source on/off mode
    0x58 | 0x00 | JIETA_EN_CTRL   bit[0]: JEITA standard enable
    0x62 | 0x09 | ICC_CHG_SET     bits[4:0]: CC charge current limit (0-1500mA)
    0x69 | 0x01 | CHGLED_SET_CTRL bits[2:1]: CHGLED display function (type A/B/reg)
    0x80 | 0x0F | DCDC_ONOFF_DVM  bit[3]: DCDC4 enable
                                  bit[2]: DCDC3 enable
                                  bit[1]: DCDC2 enable
                                  bit[0]: DCDC1 enable
    0x82 | 0x12 | DCDC1_VOL       bits[4:0]: DCDC1 startup voltage (1.5-3.4V)
    0x83 | 0x28 | DCDC2_VOL       bits[6:0]: DCDC2 startup voltage (0.5-1.54V)
    0x84 | 0x28 | DCDC3_VOL       bits[6:0]: DCDC3 startup voltage (0.5-1.54V)
    0x85 | 0x3C | DCDC4_VOL       bits[6:0]: DCDC4 startup voltage (0.5-1.84V)
    0x90 | 0x55 | LDO_ONOFF_CTRL0 bit[7]: DLDO1  bit[6]: CPUSLDO  bit[5]: BLDO2
                                  bit[4]: BLDO1  bit[3]: ALDO4  bit[2]: ALDO3
                                  bit[1]: ALDO2  bit[0]: ALDO1  (enable defaults)
    0x91 | 0x00 | LDO_ONOFF_CTRL1 bit[0]: DLDO2 enable default
    0x92 | 0x0D | ALDO1_VOL       bits[4:0]: ALDO1 startup voltage (0.5-3.5V)
    0x93 | 0x17 | ALDO2_VOL       bits[4:0]: ALDO2 startup voltage (0.5-3.5V)
    0x94 | 0x1C | ALDO3_VOL       bits[4:0]: ALDO3 startup voltage (0.5-3.5V)
    0x95 | 0x18 | ALDO4_VOL       bits[4:0]: ALDO4 startup voltage (0.5-3.5V)
    0x96 | 0x0D | BLDO1_VOL       bits[4:0]: BLDO1 startup voltage (0.5-3.5V)
    0x97 | 0x17 | BLDO2_VOL       bits[4:0]: BLDO2 startup voltage (0.5-3.5V)
    0x98 | 0x08 | CPUSLDO_VOL     bits[4:0]: CPUSLDO startup voltage (0.5-1.4V)
    0x99 | 0x00 | DLDO1_VOL       bits[4:0]: DLDO1 startup voltage (0.5-3.4V)
    0x9A | 0x0E | DLDO2_VOL       bits[4:0]: DLDO2 startup voltage (0.5-1.4V)
============================================================

1 Like

I was in the same situation, accidentally inserted my battery in reverse and killed AXP2101. I replaced it with the one I bought on aliexpress, but my LCD was not comming up after this replacement. Then I found this thread and thanks to the dump of orginal values of the stock AXP registers provided by @cathiele I was able to fix it. I used @JackCarterSmith rewrite of the picocalc BIOS described here:

GIT:

What I basically did is:

modified Src/axp2101.c file and added:

#define AXPI2C_RETRIES 3
#define AXPI2C_TIMEOUT_MS 100

typedef struct {
    uint8_t reg;
    uint8_t val;
} reg_pair_t;

static const reg_pair_t axp_init[] = {
    {0x12,0x00},
    {0x22,0x04},
    {0x24,0x00},
    {0x25,0x19},
    {0x27,0x16},
    {0x58,0x00},
    {0x50,0x12},
    {0x62,0x13},
    {0x69,0x01},
    {0x80,0x01},
    {0x82,0x12},
    {0x83,0x00},
    {0x84,0x00},
    {0x85,0x00},
    {0x90,0x3F},
    {0x91,0x00},
    {0x92,0x1C},
    {0x93,0x1C},
    {0x94,0x1C},
    {0x95,0x1C},
    {0x96,0x1E},
    {0x97,0x1E},
    {0x98,0x00},
    {0x99,0x00},
    {0x9A,0x00},
};


static HAL_StatusTypeDef axp2101_write_reg(uint8_t reg, uint8_t val)
{
    HAL_StatusTypeDef ret;
    for (int attempt = 0; attempt < AXPI2C_RETRIES; ++attempt) {
        ret = HAL_I2C_Mem_Write(&hi2c2,  AXP2101_DEV_I2C_ID, reg, I2C_MEMADD_SIZE_8BIT, &val, 1, AXPI2C_TIMEOUT_MS);
        if (ret == HAL_OK) return HAL_OK;
        HAL_Delay(5);
    }
    return ret;
}



int axp2101_init_regs(void)
{
    size_t n = sizeof(axp_init)/sizeof(axp_init[0]);
    for (size_t i = 0; i < n; ++i) {
        HAL_StatusTypeDef s = axp2101_write_reg(axp_init[i].reg, axp_init[i].val);
        if (s != HAL_OK) {
            // TODO: error handle
            return -1;
        }
    }
    return 0;
}

modified Inc/axp2101.h and added function declaration:

int axp2101_init_regs(void);

and then modified main.c file and added the following after AXP initialization in main() (after line 195)

            if (axp2101_init_regs() != 0) {
                    // TODO: error handling
            }

and BUM, it works! Maybe this will help you as well.

2 Likes