diff --git a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c index aaa4af1fb8..80bb935791 100644 --- a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c +++ b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c @@ -32,6 +32,8 @@ #include #include #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; } diff --git a/board/netmodule/nm-common/da9063.c b/board/netmodule/nm-common/da9063.c index 14c9188e9a..28299057d4 100644 --- a/board/netmodule/nm-common/da9063.c +++ b/board/netmodule/nm-common/da9063.c @@ -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, ¶m1, &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, ¶m1, &data, &data_len);