Add hwinfo driver for Silicon Labs Series 2 devices. The driver is separate from the Series 0/1 Gecko driver because the available reset causes are completely different. Signed-off-by: Aksel Skauge Mellbye <aksel.mellbye@silabs.com>
124 lines
3 KiB
C
124 lines
3 KiB
C
/*
|
|
* Copyright (c) 2025 Silicon Laboratories Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/drivers/hwinfo.h>
|
|
#include <zephyr/sys/byteorder.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <em_system.h>
|
|
#include <em_rmu.h>
|
|
|
|
/* Ensure that all possible reset causes have a definition */
|
|
#ifndef EMU_RSTCAUSE_BOOSTON
|
|
#define EMU_RSTCAUSE_BOOSTON 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_WDOG1
|
|
#define EMU_RSTCAUSE_WDOG1 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_IOVDD1BOD
|
|
#define EMU_RSTCAUSE_IOVDD1BOD 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_IOVDD2BOD
|
|
#define EMU_RSTCAUSE_IOVDD2BOD 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_SETAMPER
|
|
#define EMU_RSTCAUSE_SETAMPER 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_SESYSREQ
|
|
#define EMU_RSTCAUSE_SESYSREQ 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_SELOCKUP
|
|
#define EMU_RSTCAUSE_SELOCKUP 0
|
|
#endif
|
|
#ifndef EMU_RSTCAUSE_DCI
|
|
#define EMU_RSTCAUSE_DCI 0
|
|
#endif
|
|
|
|
/* The Zephyr API expects hwinfo_get_reset_cause() to return 0 after hwinfo_clear_reset_cause() has
|
|
* been called. This matches the hardware behavior on Series 2, but not the HAL API. The HAL stores
|
|
* the reset cause upon first read, and returns this cached value on subsequent calls to the API
|
|
* to allow multiple subsystems to read the reset cause despite it having been cleared in hardware
|
|
* already. Emulate the hardware behavior while staying compatible with other users of the HAL API
|
|
* by keeping track of whether the reset cause should be considered cleared or not ourselves.
|
|
*/
|
|
static bool reset_cleared;
|
|
|
|
ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
|
|
{
|
|
uint64_t unique_id = sys_cpu_to_be64(SYSTEM_GetUnique());
|
|
|
|
if (length > sizeof(unique_id)) {
|
|
length = sizeof(unique_id);
|
|
}
|
|
|
|
memcpy(buffer, &unique_id, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
|
|
{
|
|
uint32_t flags = 0;
|
|
uint32_t rmu = RMU_ResetCauseGet();
|
|
|
|
if (reset_cleared) {
|
|
*cause = 0;
|
|
return 0;
|
|
}
|
|
|
|
if (rmu & EMU_RSTCAUSE_POR) {
|
|
flags |= RESET_POR;
|
|
}
|
|
|
|
if (rmu & EMU_RSTCAUSE_PIN) {
|
|
flags |= RESET_PIN;
|
|
}
|
|
|
|
if (rmu & (EMU_RSTCAUSE_EM4 | EMU_RSTCAUSE_BOOSTON)) {
|
|
flags |= RESET_LOW_POWER_WAKE;
|
|
}
|
|
|
|
if (rmu & (EMU_RSTCAUSE_WDOG0 | EMU_RSTCAUSE_WDOG1)) {
|
|
flags |= RESET_WATCHDOG;
|
|
}
|
|
|
|
if (rmu & EMU_RSTCAUSE_LOCKUP) {
|
|
flags |= RESET_CPU_LOCKUP;
|
|
}
|
|
|
|
if (rmu & EMU_RSTCAUSE_SYSREQ) {
|
|
flags |= RESET_SOFTWARE;
|
|
}
|
|
|
|
if (rmu & (EMU_RSTCAUSE_DVDDBOD | EMU_RSTCAUSE_DVDDLEBOD | EMU_RSTCAUSE_DECBOD |
|
|
EMU_RSTCAUSE_AVDDBOD | EMU_RSTCAUSE_IOVDD0BOD |
|
|
EMU_RSTCAUSE_IOVDD1BOD | EMU_RSTCAUSE_IOVDD2BOD)) {
|
|
flags |= RESET_BROWNOUT;
|
|
}
|
|
|
|
if (rmu & (EMU_RSTCAUSE_SETAMPER | EMU_RSTCAUSE_SESYSREQ |
|
|
EMU_RSTCAUSE_SELOCKUP | EMU_RSTCAUSE_DCI)) {
|
|
flags |= RESET_SECURITY;
|
|
}
|
|
|
|
*cause = flags;
|
|
return 0;
|
|
}
|
|
|
|
int z_impl_hwinfo_clear_reset_cause(void)
|
|
{
|
|
RMU_ResetCauseClear();
|
|
reset_cleared = true;
|
|
return 0;
|
|
}
|
|
|
|
int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
|
|
{
|
|
*supported = RESET_PIN | RESET_SOFTWARE | RESET_BROWNOUT | RESET_POR | RESET_WATCHDOG |
|
|
RESET_SECURITY | RESET_LOW_POWER_WAKE | RESET_CPU_LOCKUP;
|
|
return 0;
|
|
}
|