util: Refactor power management (reboot/power off)

This commit is contained in:
CTCaer 2020-12-15 19:33:46 +02:00
parent 9d79f39897
commit 601c85c23e
4 changed files with 82 additions and 63 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -132,53 +132,57 @@ void panic(u32 val)
usleep(1);
}
void reboot_normal()
void power_set_state(power_state_t state)
{
u8 reg;
// Unmount and power down sd card.
sd_end();
hw_reinit_workaround(false, 0);
panic(0x21); // Bypass fuse programming in package1.
}
void reboot_rcm()
{
sd_end();
hw_reinit_workaround(false, 0);
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
while (true)
bpmp_halt();
}
void reboot_full()
{
sd_end();
hw_reinit_workaround(false, 0);
// Enable soft reset wake event.
u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Do a soft reset.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
while (true)
bpmp_halt();
}
void power_off()
{
sd_end();
// De-initialize and power down various hardware.
hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm();
// Set power state.
switch (state)
{
case REBOOT_RCM:
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
break;
case REBOOT_BYPASS_FUSES:
panic(0x21); // Bypass fuse programming in package1.
break;
case POWER_OFF:
// Initiate power down sequence and do not generate a reset (regulators retain state).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
break;
case POWER_OFF_RESET:
case POWER_OFF_REBOOT:
// Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET)
reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off.
else // POWER_OFF_REBOOT.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Initiate power down sequence and generate a reset (regulators' state resets).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
break;
}
while (true)
bpmp_halt();
}
void power_set_state_ex(void *param)
{
power_state_t *state = (power_state_t *)param;
power_set_state(*state);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -23,6 +23,16 @@
#define NYX_NEW_INFO 0x3058594E
typedef enum
{
REBOOT_RCM, // PMC reset. Enter RCM mode.
REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1.
POWER_OFF, // Power off PMIC. Do not reset regulators.
POWER_OFF_RESET, // Power off PMIC. Reset regulators.
POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on.
} power_state_t;
typedef enum
{
NYX_CFG_BIS = BIT(5),
@ -71,17 +81,18 @@ typedef struct _nyx_storage_t
emc_table_t mtc_table[10];
} nyx_storage_t;
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
u32 get_tmr_us();
u32 get_tmr_ms();
u32 get_tmr_s();
void usleep(u32 us);
void msleep(u32 ms);
void panic(u32 val);
void reboot_normal();
void reboot_rcm();
void reboot_full();
void power_off();
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
void power_set_state(power_state_t state);
void power_set_state_ex(void *param);
#endif

View file

@ -133,7 +133,7 @@ void check_power_off_from_hos()
msleep(600);
display_backlight_brightness(0, 20000);
}
power_off();
power_set_state(POWER_OFF);
}
}
@ -1304,7 +1304,7 @@ static void _check_low_battery()
if (!current_charge_status)
{
max77620_low_battery_monitor_config(true);
power_off();
power_set_state(POWER_OFF);
}
display_end();
@ -1498,6 +1498,10 @@ ment_t ment_tools[] = {
menu_t menu_tools = { ment_tools, "Tools", 0, 0 };
power_state_t STATE_POWER_OFF = POWER_OFF;
power_state_t STATE_REBOOT_RCM = REBOOT_RCM;
power_state_t STATE_REBOOT_BYPASS_FUSES = REBOOT_BYPASS_FUSES;
ment_t ment_top[] = {
MDEF_HANDLER("Launch", launch_firmware),
//MDEF_MENU("Options", &menu_options),
@ -1506,9 +1510,9 @@ ment_t ment_top[] = {
MDEF_MENU("Console info", &menu_cinfo),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("Reload", ipl_reload),
MDEF_HANDLER("Reboot (Normal)", reboot_normal),
MDEF_HANDLER("Reboot (RCM)", reboot_rcm),
MDEF_HANDLER("Power off", power_off),
MDEF_HANDLER_EX("Reboot (Normal)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("About", _about),
MDEF_END()

View file

@ -901,12 +901,12 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
{
case 0:
if (h_cfg.rcm_patched)
reboot_full();
power_set_state(POWER_OFF_REBOOT);
else
reboot_rcm();
power_set_state(REBOOT_RCM);
break;
case 1:
power_off();
power_set_state(POWER_OFF);
break;
case 2:
sd_end();
@ -955,14 +955,14 @@ static lv_res_t _reboot_action(lv_obj_t *btns, const char *txt)
{
case 0:
if (h_cfg.rcm_patched)
reboot_full();
power_set_state(POWER_OFF_REBOOT);
else
reboot_normal();
power_set_state(REBOOT_BYPASS_FUSES);
break;
case 1:
if (h_cfg.rcm_patched)
break;
reboot_rcm();
power_set_state(REBOOT_RCM);
break;
}
@ -972,7 +972,7 @@ static lv_res_t _reboot_action(lv_obj_t *btns, const char *txt)
static lv_res_t _poweroff_action(lv_obj_t *btns, const char *txt)
{
if (!lv_btnm_get_pressed(btns))
power_off();
power_set_state(POWER_OFF);
return mbox_action(btns, txt);
}