hw25: add start reason detection

This commit is contained in:
Rene Straub 2020-11-27 15:46:39 +01:00
parent 7e9ca6d8fa
commit 0330a6b94f
3 changed files with 126 additions and 61 deletions

View File

@ -10,4 +10,4 @@ ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),)
obj-y := mux.o obj-y := mux.o
endif 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

View File

@ -34,6 +34,7 @@
#include "../common/bdparser.h" #include "../common/bdparser.h"
#include "../common/board_descriptor.h" #include "../common/board_descriptor.h"
#include "../common/da9063.h" #include "../common/da9063.h"
#include "../common/ether_crc.h"
#include "board.h" #include "board.h"
#include "fileaccess.h" #include "fileaccess.h"
@ -119,6 +120,7 @@ static int hw_type = -1;
static char hw_variant_name[64]; static char hw_variant_name[64];
#else #else
static int hw_type = -1; static int hw_type = -1;
static uint32_t sys_start_event = 0x0;
#endif #endif
#if !defined(CONFIG_SPL_BUILD) #if !defined(CONFIG_SPL_BUILD)
@ -294,31 +296,6 @@ struct dpll_params dpll_ddr = {
DDR3_CLOCK_FREQUENCY, OSC-1, 1, -1, -1, -1, -1 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) static void init_pmic_spl(void)
{ {
int bus; int bus;
@ -339,60 +316,152 @@ static void init_pmic_spl(void)
} }
struct reset_registers { struct reset_registers {
uint32_t value; /* Reboot Reasons, set by OS, expect watchdog set by bootloader */
uint32_t value_crc; 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 */ /* Start event token 'SRTE' */
static uint32_t ether_crc(size_t len, uint8_t const *p) #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; puts("\nStart Events: ");
unsigned i;
crc = ~0; if (events == 0) {
while (len--) { puts("-\n");
crc ^= *p++; }
for (i = 0; i < 8; i++) else {
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); 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));
/* Trim last comma, no 0 len check required, at least one entry is present */
buffer[strlen(buffer)-2] = 0;
printf("%s\n", buffer);
}
} }
/* an reverse the bits, cuz of way they arrive -- last-first */ static void check_pmic_reset_reason(unsigned int reset_reason_shm_location)
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;
}
void check_pmic_reset_reason(unsigned int reset_reason_shm_location)
{ {
volatile struct reset_registers* reset_regs = (struct reset_registers*)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; uint8_t state = 0x00;
int bus; int bus;
int ret; int ret;
bus = da9063_claim_i2c_bus(); 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); ret = da9063_get_reg(PMIC_REG_FAULT_LOG, &state);
if ((ret == 0) && (state != 0)) { if ((ret == 0) && (state != 0)) {
// PMIC Watchdog
if (state & PMIC_FAULT_TWD_ERROR_MASK) { if (state & PMIC_FAULT_TWD_ERROR_MASK) {
reset_regs->value = EXTERNAL_WATCHDOG_PATTERN; start_event |= SE_WATCHDOG;
reset_regs->value_crc = ether_crc(sizeof(reset_regs->value),
(const uint8_t*)&(reset_regs->value)); 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 */ /* 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);
} }
/*
* 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);
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); da9063_release_i2c_bus(bus);
}
#endif print_start_reason(reset_regs->se_events);
}
static void init_bd_spl(void) static void init_bd_spl(void)
{ {
@ -426,6 +495,9 @@ void am33xx_spl_board_init(void)
/* Get board descriptor */ /* Get board descriptor */
init_bd_spl(); init_bd_spl();
/* Detect reset/Wakeup reason */
check_pmic_reset_reason(RESET_REASON_SHM_LOCATION);
/* Setup PMIC */ /* Setup PMIC */
init_pmic_spl(); 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 */ /* Set MPU Frequency to what we detected now that voltages are set */
do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); 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 */ /* Debugger can place marker at end of SRAM to stop boot here */
if (is_jtag_boot(CONFIG_JTAG_MARKER_SPL)) if (is_jtag_boot(CONFIG_JTAG_MARKER_SPL))
{ {

View File

@ -308,10 +308,7 @@ int eth_phy_timeout(void);
#define CONFIG_JTAG_MARKER_UBOOT 0x807FFF00 #define CONFIG_JTAG_MARKER_UBOOT 0x807FFF00
/* NRSW PMIC Reset Reason */ /* NRSW PMIC Reset Reason */
#ifdef CONFIG_NRSW_BUILD
#define RESET_REASON_SHM_LOCATION 0x8e000000 #define RESET_REASON_SHM_LOCATION 0x8e000000
#define EXTERNAL_WATCHDOG_PATTERN 0x781f9ce2
#endif
/* SPL command is not needed */ /* SPL command is not needed */