diff --git a/board/nm/hw25/Makefile b/board/nm/hw25/Makefile index e9a013ecbb..65e1cad0b9 100644 --- a/board/nm/hw25/Makefile +++ b/board/nm/hw25/Makefile @@ -10,4 +10,4 @@ ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) obj-y := mux.o endif -obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o ../common/da9063.o fileaccess.o +obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o ../common/da9063.o ../common/ether_crc.o fileaccess.o diff --git a/board/nm/hw25/board.c b/board/nm/hw25/board.c index 9eda4a6c37..67415a418e 100644 --- a/board/nm/hw25/board.c +++ b/board/nm/hw25/board.c @@ -34,6 +34,7 @@ #include "../common/bdparser.h" #include "../common/board_descriptor.h" #include "../common/da9063.h" +#include "../common/ether_crc.h" #include "board.h" #include "fileaccess.h" @@ -119,6 +120,7 @@ static int hw_type = -1; static char hw_variant_name[64]; #else static int hw_type = -1; +static uint32_t sys_start_event = 0x0; #endif #if !defined(CONFIG_SPL_BUILD) @@ -294,31 +296,6 @@ struct dpll_params dpll_ddr = { DDR3_CLOCK_FREQUENCY, OSC-1, 1, -1, -1, -1, -1 }; -// TODO: Since there is no ignition logic (with edge generator) on hw25 -// TODO: the following is not required -#if 0 -static void pmic_ignition_gate_on(void) -{ - uint8_t val; - - /* Configure GPIO15 to permanent high, so that ignition sense signal is readable */ - - (void)da9063_set_reg(PMIC_REG_GPIO14_15, 0xCC); /* GPIO14/15 = Outputs open drain */ - - (void)da9063_get_reg(PMIC_REG_CONFIG_L, &val); /* Enable pull ups on GPIO14/15 */ - val |= 0xC0; - (void)da9063_set_reg(PMIC_REG_CONFIG_L, val); - - (void)da9063_get_reg(PMIC_REG_CONTROL_D, &val); /* No blinking, state selected by GPIOxx_MODE */ - val &= ~0xF8; - (void)da9063_set_reg(PMIC_REG_CONTROL_D, val); - - (void)da9063_get_reg(PMIC_REG_GPIO_MODE8_15, &val); /* Set to GPIO14,15 to high */ - val |= 0xC0; - (void)da9063_set_reg(PMIC_REG_GPIO_MODE8_15, val); -} -#endif - static void init_pmic_spl(void) { int bus; @@ -339,60 +316,152 @@ static void init_pmic_spl(void) } struct reset_registers { - uint32_t value; - uint32_t value_crc; + /* Reboot Reasons, set by OS, expect watchdog set by bootloader */ + uint32_t rr_value; + uint32_t rr_value_crc; + + /* Start Events */ + uint32_t se_magic; /* Token to check presence of following fields */ + uint32_t se_events; /* Events bitmask, see SE_... defines */ + uint32_t se_checksum; /* Checksum over se_events */ }; -#ifdef CONFIG_NRSW_BUILD +/* Watchdog reboot reason event */ +#define RR_EXTERNAL_WATCHDOG_PATTERN 0x781f9ce2 -/* TODO: Move ethernet crc to dedicated file */ -static uint32_t ether_crc(size_t len, uint8_t const *p) +/* Start event token 'SRTE' */ +#define SE_MAGIC 0x53525445 + +/* Possible start events (see se_events) */ +#define SE_POR 0x00000001 +#define SE_WATCHDOG 0x00000010 +#define SE_IGNITION 0x00000100 +#define SE_RTC_ALARM 0x00000200 +#define SE_RTC_TICK 0x00000400 + + +static void print_start_reason(uint32_t events) { - uint32_t crc; - unsigned i; + puts("\nStart Events: "); - crc = ~0; - while (len--) { - crc ^= *p++; - for (i = 0; i < 8; i++) - crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + if (events == 0) { + puts("-\n"); } + else { + static char buffer[10+11+11+6+6+1]; + + buffer[0] = 0; + if (events & SE_POR) + strncat(buffer, "PowerOn, ", sizeof(buffer)); + if (events & SE_WATCHDOG) + strncat(buffer, "Watchdog, ", sizeof(buffer)); + if (events & SE_IGNITION) + strncat(buffer, "Ignition, ", sizeof(buffer)); + if (events & SE_RTC_ALARM) + strncat(buffer, "RTC, ", sizeof(buffer)); + if (events & SE_RTC_TICK) + strncat(buffer, "Tick, ", sizeof(buffer)); - /* an reverse the bits, cuz of way they arrive -- last-first */ - crc = (crc >> 16) | (crc << 16); - crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00); - crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0); - crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc); - crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa); - - return crc; + /* Trim last comma, no 0 len check required, at least one entry is present */ + buffer[strlen(buffer)-2] = 0; + printf("%s\n", buffer); + } } -void check_pmic_reset_reason(unsigned int reset_reason_shm_location) +static void check_pmic_reset_reason(unsigned int reset_reason_shm_location) { volatile struct reset_registers* reset_regs = (struct reset_registers*)reset_reason_shm_location; + uint32_t start_event = 0; uint8_t state = 0x00; int bus; int ret; bus = da9063_claim_i2c_bus(); + /* + * Check/write boot marker to GP_ID_0 + * If this marker is not present, we have a power on reset + */ + ret = da9063_get_reg(PMIC_GP_ID_0, &state); + if ((ret == 0) && (state != 0xC5)) { + start_event |= SE_POR; + (void)da9063_set_reg(PMIC_GP_ID_0, 0xC5); + } + + /* + * 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)) { + // PMIC Watchdog if (state & PMIC_FAULT_TWD_ERROR_MASK) { - reset_regs->value = EXTERNAL_WATCHDOG_PATTERN; - reset_regs->value_crc = ether_crc(sizeof(reset_regs->value), - (const uint8_t*)&(reset_regs->value)); + start_event |= SE_WATCHDOG; + + reset_regs->rr_value = RR_EXTERNAL_WATCHDOG_PATTERN; + reset_regs->rr_value_crc = ether_crc(sizeof(reset_regs->rr_value), + (const uint8_t*)&(reset_regs->rr_value)); + } + + // PMIC Power On Reset (only when RTC battery is removed) + if (state & PMIC_FAULT_POR_MASK) { + start_event |= SE_POR; } /* clear pmic fault log by writing back all bits currently set */ - da9063_set_reg(PMIC_REG_FAULT_LOG, state); + (void)da9063_set_reg(PMIC_REG_FAULT_LOG, state); } - da9063_release_i2c_bus(bus); -} + /* + * Event Register A + * - Event B Activity + * - RTC Alarm + * - RTC Tick + */ + ret = da9063_get_reg(PMIC_REG_EVENT_A, &state); + if ((ret == 0) && (state != 0)) { + (void)da9063_set_reg(PMIC_REG_EVENT_A, state); -#endif + if (state & PMIC_REG_EVENT_RTC_ALARM_MASK) { + start_event |= SE_RTC_ALARM; + } + + if (state & PMIC_REG_EVENT_RTC_TICK_MASK) { + start_event |= SE_RTC_TICK; + } + + if (state & PMIC_REG_EVENT_EVENTS_B_MASK) { + /* + * Event Register B + * - COMP 1V2: Ignition + */ + ret = da9063_get_reg(PMIC_REG_EVENT_B, &state); + if ((ret == 0) && (state != 0)) { + (void)da9063_set_reg(PMIC_REG_EVENT_B, state); + + if (state & PMIC_REG_EVENT_COMP1V2_MASK) { + start_event |= SE_IGNITION; + } + } + } + + /* TODO: Should we clear events here or leave them for Linux driver? */ + } + + sys_start_event = start_event; + + /* Store start events in shared memory region for OS */ + reset_regs->se_magic = SE_MAGIC; + reset_regs->se_events = start_event; + reset_regs->se_checksum = 0; + reset_regs->se_checksum = ether_crc(sizeof(reset_regs->se_events), + (const uint8_t*)&(reset_regs->se_events)); + + da9063_release_i2c_bus(bus); + + print_start_reason(reset_regs->se_events); +} static void init_bd_spl(void) { @@ -426,6 +495,9 @@ void am33xx_spl_board_init(void) /* Get board descriptor */ init_bd_spl(); + /* Detect reset/Wakeup reason */ + check_pmic_reset_reason(RESET_REASON_SHM_LOCATION); + /* Setup PMIC */ init_pmic_spl(); @@ -438,10 +510,6 @@ void am33xx_spl_board_init(void) /* Set MPU Frequency to what we detected now that voltages are set */ do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); -#ifdef CONFIG_NRSW_BUILD - check_pmic_reset_reason(RESET_REASON_SHM_LOCATION); -#endif - /* Debugger can place marker at end of SRAM to stop boot here */ if (is_jtag_boot(CONFIG_JTAG_MARKER_SPL)) { diff --git a/include/configs/am335x_hw25.h b/include/configs/am335x_hw25.h index ef2a99638c..661ec24c72 100644 --- a/include/configs/am335x_hw25.h +++ b/include/configs/am335x_hw25.h @@ -308,10 +308,7 @@ int eth_phy_timeout(void); #define CONFIG_JTAG_MARKER_UBOOT 0x807FFF00 /* NRSW PMIC Reset Reason */ -#ifdef CONFIG_NRSW_BUILD #define RESET_REASON_SHM_LOCATION 0x8e000000 -#define EXTERNAL_WATCHDOG_PATTERN 0x781f9ce2 -#endif /* SPL command is not needed */