HW23: Add support for reset reason

Part of SSF integration

BugzID: 71440
This commit is contained in:
Alexandre Bard 2021-04-26 19:00:46 +02:00
parent 4a75ab8d4f
commit d8d15bcfc8
2 changed files with 164 additions and 3 deletions

View File

@ -32,6 +32,8 @@
#include <cdns3-uboot.h>
#include <asm/arch/lpcg.h>
#include "../nm-common/board_descriptor.h"
#include "../nm-common/da9063.h"
#include "../nm-common/reset_reason.h"
DECLARE_GLOBAL_DATA_PTR;
@ -40,6 +42,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define BD_ADDRESS (0x0000)
#define PD_ADDRESS (0x0200)
#define RESET_REASON_SHM_LOCATION 0x95000000
static uint32_t sys_start_event = 0x0;
static BD_Context bdctx[3];
#define ESDHC_PAD_CTRL ((SC_PAD_CONFIG_NORMAL << PADRING_CONFIG_SHIFT) | (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) \
@ -511,9 +516,24 @@ void reset_cpu(ulong addr)
putc('.');
}
static void ft_start_event(void *blob, uint64_t reset_reason_shm_location)
{
volatile struct reset_registers* reset_regs = (struct reset_registers*)reset_reason_shm_location;
if (rr_is_start_reason_valid(reset_regs)) {
int node_offset;
node_offset = fdt_path_offset(blob, "/sysstate-start/");
if (node_offset != -1) {
fdt_setprop_u32(blob, node_offset, "start-reason", reset_regs->sr_events);
}
}
}
#ifdef CONFIG_OF_BOARD_SETUP
int ft_board_setup(void *blob, bd_t *bd)
{
ft_start_event(blob, RESET_REASON_SHM_LOCATION);
return 0;
}
#endif
@ -539,6 +559,144 @@ int board_mmc_get_env_dev(int devno)
return devno;
}
static void check_reset_reason(uint64_t reset_reason_shm_location)
{
volatile struct reset_registers* reset_regs = (struct reset_registers*)reset_reason_shm_location;
uint32_t start_reason = 0;
uint32_t reset_reason = 0;
uint8_t state = 0x00;
int ret;
char strbuf[256];
/*
* Check/write boot marker to PMIC register GP_ID_1
* If this marker is not present, we have a power on reset
*/
ret = da9063_get_reg(PMIC_GP_ID_1, &state);
if ((ret == 0) && (state != 0xC5)) {
(void)da9063_set_reg(PMIC_GP_ID_1, 0xC5);
start_reason |= SR_POR;
}
/*
* Check Fault Log register for
* - Power On Reset: No Power, RTC Delivery -> requires removal of RTC battery
* - Watchdog
*/
ret = da9063_get_reg(PMIC_REG_FAULT_LOG, &state);
if ((ret == 0) && (state != 0)) {
/* clear pmic fault log by writing back all bits currently set */
(void)da9063_set_reg(PMIC_REG_FAULT_LOG, state);
/* PMIC Power On Reset (only when RTC battery is removed) */
if (state & PMIC_FAULT_POR_MASK) {
start_reason |= SR_POR;
}
/* PMIC Watchdog */
if (state & PMIC_FAULT_TWD_ERROR_MASK) {
start_reason |= SR_WATCHDOG;
}
}
/*
* Check Wakeup Events
* Event Register A holds:
* - Event B, C Activity
* - nONKEY: Button
* - RTC Alarm
* - RTC Tick
* Event Register B
* - COMP 1V2: Ignition
*/
ret = da9063_get_reg(PMIC_REG_EVENT_A, &state);
if ((ret == 0) && (state != 0)) {
(void)da9063_set_reg(PMIC_REG_EVENT_A, state);
if (state & PMIC_REG_EVENT_ONKEY_MASK) {
start_reason |= (SR_WAKEUP | SR_EVT_BUTTON);
}
if (state & PMIC_REG_EVENT_RTC_ALARM_MASK) {
start_reason |= (SR_WAKEUP | SR_EVT_RTC_ALARM);
}
if (state & PMIC_REG_EVENT_RTC_TICK_MASK) {
start_reason |= (SR_WAKEUP | SR_EVT_RTC_TICK);
}
if (state & PMIC_REG_EVENT_EVENTS_B_MASK) {
uint8_t state_b;
ret = da9063_get_reg(PMIC_REG_EVENT_B, &state_b);
if ((ret == 0) && (state_b != 0)) {
(void)da9063_set_reg(PMIC_REG_EVENT_B, state_b);
if (state_b & PMIC_REG_EVENT_COMP1V2_MASK) {
start_reason |= (SR_WAKEUP | SR_EVT_IGNITION);
}
}
}
}
/*
* Check for software reboot indicated by OS via shared memory
* - checksum valid?
* - Reason == 'REBO' or 'OOPS'
*/
if (rr_is_reset_reason_valid(reset_regs))
{
if (reset_regs->rr_value == RR_REBOOT_PATTERN) {
start_reason |= SR_REBOOT;
}
else if (reset_regs->rr_value == RR_OOPS_PATTERN) {
/* Treat kernel oops as reboot */
start_reason |= SR_REBOOT;
}
else if (reset_regs->rr_value == RR_WAKE_PATTERN) {
start_reason |= SR_WAKEUP;
}
else {
/* Unknown reset reason */
}
}
/*
* Priority decoder for start and reset reason
*/
if (start_reason & SR_WATCHDOG) {
/* Watchdog has highest priority as it also sets POR and other events */
start_reason = SR_WATCHDOG;
reset_reason = RR_EXTERNAL_WATCHDOG_PATTERN;
}
else if (start_reason & SR_POR) {
start_reason = SR_POR;
reset_reason = RR_POWEROFF_PATTERN;
}
else if (start_reason & SR_WAKEUP) {
/* Include start events when wakeup is detected */
start_reason = SR_WAKEUP | (start_reason & SR_EVT_WAKE_MASK);
reset_reason = RR_WAKE_PATTERN;
}
else if (start_reason & SR_REBOOT) {
start_reason = SR_REBOOT;
reset_reason = reset_regs->rr_value;
}
else {
/* Unknown start reason, assume reboot */
start_reason = SR_REBOOT;
reset_reason = reset_regs->rr_value;
}
sys_start_event = start_reason;
rr_set_reset_reason(reset_regs, reset_reason);
rr_set_start_reason(reset_regs, start_reason);
rr_start_reason_to_str(reset_regs->sr_events, strbuf, sizeof(strbuf));
printf("\nStart Events: %s\n", strbuf);
}
static int _bd_init(void)
{
if (bd_get_context(&bdctx[0], BD_EEPROM_ADDR, BD_ADDRESS) != 0) {
@ -584,6 +742,9 @@ int board_late_init(void)
get_hw_version();
board_eth_init(NULL);
da9063_init();
check_reset_reason(RESET_REASON_SHM_LOCATION);
return 0;
}

View File

@ -55,7 +55,7 @@ int da9063_get_reg(uint32_t reg, uint8_t* val)
if (reg < 0x100)
param1 = CONFIG_PMIC_I2C_ADDR | reg << 8 | read << 16;
else
param1 = (CONFIG_PMIC_I2C_ADDR + 1) | reg << 8 | read << 16;
param1 = (CONFIG_PMIC_I2C_ADDR + 1) | (reg & 0xff) << 8 | read << 16;
ret = sc_misc_board_ioctl(ipc, &param1, &data, &data_len);
@ -72,7 +72,7 @@ int da9063_set_reg(uint32_t reg, uint8_t val)
{
sc_err_t ret;
uint8_t read = 0;
uint32_t param1 = CONFIG_PMIC_I2C_ADDR | reg << 8 | read << 16;
uint32_t param1;
uint32_t data = val;
uint32_t data_len = 1;
@ -90,7 +90,7 @@ int da9063_set_reg(uint32_t reg, uint8_t val)
if (reg < 0x100)
param1 = CONFIG_PMIC_I2C_ADDR | reg << 8 | read << 16;
else
param1 = (CONFIG_PMIC_I2C_ADDR + 1) | reg << 8 | read << 16;
param1 = (CONFIG_PMIC_I2C_ADDR + 1) | (reg & 0xff) << 8 | read << 16;
ret = sc_misc_board_ioctl(ipc, &param1, &data, &data_len);