drivers: hwinfo: Add reset cause support

Add `hwinfo_get_reset_cause` and `hwinfo_clear_reset_cause` to retrieve
and to clear cause of system reset on supported platforms.

Different platforms can provide different causes of reset, however
there is a great deal of overlap. `enum reset_cause` can be expanded in
the future to support additional reasons, as additional platforms are
supported.

Signed-off-by: Arvin Farahmand <arvinf@ip-logix.com>
This commit is contained in:
Arvin Farahmand 2020-04-30 22:32:52 -04:00 committed by Carles Cufí
commit 98a0ccd5c5
9 changed files with 409 additions and 35 deletions

View file

@ -10,9 +10,6 @@ menuconfig HWINFO
if HWINFO
config HWINFO_HAS_DRIVER
bool
config HWINFO_SHELL
bool "Enable HWINFO Shell"
default y
@ -24,7 +21,6 @@ config HWINFO_STM32
bool "STM32 hwinfo"
default y
depends on SOC_FAMILY_STM32
select HWINFO_HAS_DRIVER
help
Enable STM32 hwinfo driver.
@ -32,7 +28,6 @@ config HWINFO_NRF
bool "NRF device ID"
default y
depends on SOC_FAMILY_NRF && !TRUSTED_EXECUTION_NONSECURE
select HWINFO_HAS_DRIVER
help
Enable Nordic NRF hwinfo driver.
@ -40,7 +35,6 @@ config HWINFO_MCUX_SIM
bool "NXP kinetis device ID"
default y
depends on HAS_MCUX_SIM
select HWINFO_HAS_DRIVER
help
Enable NXP kinetis mcux hwinfo driver.
@ -48,7 +42,6 @@ config HWINFO_IMXRT
bool "NXP i.mx RT device ID"
default y
depends on SOC_SERIES_IMX_RT
select HWINFO_HAS_DRIVER
help
Enable NXP i.mx RT hwinfo driver.
@ -56,7 +49,6 @@ config HWINFO_SAM
bool "Atmel SAM device ID"
default y
depends on SOC_FAMILY_SAM && !SOC_SERIES_SAM4L
select HWINFO_HAS_DRIVER
help
Enable Atmel SAM hwinfo driver.
@ -64,7 +56,6 @@ config HWINFO_SAM4L
bool "Atmel SAM4L device ID"
default y
depends on SOC_SERIES_SAM4L
select HWINFO_HAS_DRIVER
help
Enable Atmel SAM4L hwinfo driver.
@ -72,7 +63,6 @@ config HWINFO_SAM0
bool "Atmel SAM0 device ID"
default y
depends on SOC_FAMILY_SAM0
select HWINFO_HAS_DRIVER
help
Enable Atmel SAM0 hwinfo driver.
@ -80,7 +70,6 @@ config HWINFO_ESP32
bool "ESP32 device ID"
default y
depends on SOC_ESP32
select HWINFO_HAS_DRIVER
help
Enable ESP32 hwinfo driver.
@ -88,7 +77,6 @@ config HWINFO_LITEX
bool "LiteX device ID"
default y
depends on SOC_RISCV32_LITEX_VEXRISCV
select HWINFO_HAS_DRIVER
help
Enable LiteX hwinfo driver
@ -96,7 +84,6 @@ config HWINFO_PSOC6
bool "Cypress PSoC-6 unique device ID"
default y
depends on SOC_FAMILY_PSOC6
select HWINFO_HAS_DRIVER
help
Enable Cypress PSoC-6 hwinfo driver.
@ -104,7 +91,6 @@ config HWINFO_GECKO
bool "GECKO hwinfo"
default y
depends on SOC_FAMILY_EXX32
select HWINFO_HAS_DRIVER
help
Enable Silabs GECKO hwinfo driver.

View file

@ -14,3 +14,34 @@ ssize_t z_vrfy_hwinfo_get_device_id(uint8_t *buffer, size_t length)
return z_impl_hwinfo_get_device_id((uint8_t *)buffer, (size_t)length);
}
#include <syscalls/hwinfo_get_device_id_mrsh.c>
int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause)
{
int ret;
uint32_t cause_copy;
ret = z_impl_hwinfo_get_reset_cause(&cause_copy);
Z_OOPS(z_user_to_copy(cause, &cause_copy, sizeof(uint32_t)));
return ret;
}
#include <syscalls/hwinfo_get_reset_cause_mrsh.c>
int z_vrfy_hwinfo_clear_reset_cause(void)
{
return z_impl_hwinfo_clear_reset_cause();
}
#include <syscalls/hwinfo_clear_reset_cause_mrsh.c>
int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported)
{
int ret;
uint32_t supported_copy;
ret = z_impl_hwinfo_get_supported_reset_cause(&supported_copy);
Z_OOPS(z_user_to_copy(supported, &supported_copy, sizeof(uint32_t)));
return ret;
}
#include <syscalls/hwinfo_get_supported_reset_cause_mrsh.c>

View file

@ -9,6 +9,9 @@
#include <string.h>
#include <hal/nrf_ficr.h>
#include <sys/byteorder.h>
#ifndef CONFIG_BOARD_QEMU_CORTEX_M0
#include <helpers/nrfx_reset_reason.h>
#endif
struct nrf_uid {
uint32_t id[2];
@ -29,3 +32,88 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
return length;
}
#ifndef CONFIG_BOARD_QEMU_CORTEX_M0
int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
{
uint32_t flags = 0;
uint32_t reason = nrfx_reset_reason_get();
if (reason & NRFX_RESET_REASON_RESETPIN_MASK) {
flags |= RESET_PIN;
}
if (reason & NRFX_RESET_REASON_DOG_MASK) {
flags |= RESET_WATCHDOG;
}
if (reason & NRFX_RESET_REASON_LOCKUP_MASK) {
flags |= RESET_CPU_LOCKUP;
}
if (reason & NRFX_RESET_REASON_OFF_MASK) {
flags |= RESET_LOW_POWER_WAKE;
}
if (reason & NRFX_RESET_REASON_DIF_MASK) {
flags |= RESET_DEBUG;
}
#if !NRF_POWER_HAS_RESETREAS
if (reason & NRFX_RESET_REASON_CTRLAP_MASK) {
flags |= RESET_DEBUG;
}
if (reason & NRFX_RESET_REASON_DOG0_MASK) {
flags |= RESET_WATCHDOG;
}
if (reason & NRFX_RESET_REASON_DOG1_MASK) {
flags |= RESET_WATCHDOG;
}
if (reason & NRFX_RESETREAS_SREQ_MASK) {
flags |= RESET_SOFTWARE;
}
#if NRF_RESET_HAS_NETWORK
if (reason & NRFX_RESET_REASON_LSREQ_MASK) {
flags |= RESET_SOFTWARE;
}
if (reason & NRFX_RESET_REASON_LLOCKUP_MASK) {
flags |= RESET_CPU_LOCKUP;
}
if (reason & NRFX_RESET_REASON_LDOG_MASK) {
flags |= RESET_WATCHDOG;
}
if (reason & NRFX_RESET_REASON_LCTRLAP_MASK) {
flags |= RESET_DEBUG;
}
#endif
#else
if (reason & NRFX_RESET_REASON_SREQ_MASK) {
flags |= RESET_SOFTWARE;
}
#endif
*cause = flags;
return 0;
}
int z_impl_hwinfo_clear_reset_cause(void)
{
uint32_t reason = -1;
nrfx_reset_reason_clear(reason);
return 0;
}
int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
{
*supported = (RESET_PIN
| RESET_WATCHDOG
| RESET_SOFTWARE
| RESET_CPU_LOCKUP
| RESET_LOW_POWER_WAKE
| RESET_DEBUG);
return 0;
}
#endif

View file

@ -6,6 +6,7 @@
#include <soc.h>
#include <stm32_ll_utils.h>
#include <stm32_ll_rcc.h>
#include <drivers/hwinfo.h>
#include <string.h>
#include <sys/byteorder.h>
@ -30,3 +31,78 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
return length;
}
int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
{
uint32_t flags = 0;
#if defined(RCC_FLAG_SFTRST)
if (LL_RCC_IsActiveFlag_SFTRST()) {
flags |= RESET_SOFTWARE;
}
#endif
#if defined(RCC_FLAG_PINRST)
if (LL_RCC_IsActiveFlag_PINRST()) {
flags |= RESET_PIN;
}
#endif
#if defined(RCC_FLAG_IWDGRST)
if (LL_RCC_IsActiveFlag_IWDGRST()) {
flags |= RESET_WATCHDOG;
}
#endif
#if defined(RCC_FLAG_WWDGRST)
if (LL_RCC_IsActiveFlag_WWDGRST()) {
flags |= RESET_WATCHDOG;
}
#endif
#if defined(RCC_FLAG_FWRST)
if (LL_RCC_IsActiveFlag_FWRST()) {
flags |= RESET_SECURITY;
}
#endif
#if defined(RCC_FLAG_BORRST)
if (LL_RCC_IsActiveFlag_BORRST()) {
flags |= RESET_BROWNOUT;
}
#endif
#if defined(RCC_FLAG_PWRRST)
if (LL_RCC_IsActiveFlag_PWRRST()) {
flags |= RESET_POR;
}
#endif
#if defined(RCC_FLAG_PORRST)
if (LL_RCC_IsActiveFlag_PORRST()) {
flags |= RESET_POR;
}
#endif
#if defined(RCC_FLAG_LPWRRST)
if (LL_RCC_IsActiveFlag_LPWRRST()) {
flags |= RESET_LOW_POWER_WAKE;
}
#endif
*cause = flags;
return 0;
}
int z_impl_hwinfo_clear_reset_cause(void)
{
LL_RCC_ClearResetFlags();
return 0;
}
int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
{
*supported = (RESET_PIN
| RESET_WATCHDOG
| RESET_SOFTWARE
| RESET_SECURITY
| RESET_LOW_POWER_WAKE
| RESET_POR
| RESET_BROWNOUT);
return 0;
}

View file

@ -8,5 +8,20 @@
ssize_t __weak z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
{
return -ENOTSUP;
return -ENOSYS;
}
int __weak z_impl_hwinfo_get_reset_cause(uint32_t *cause)
{
return -ENOSYS;
}
int __weak z_impl_hwinfo_clear_reset_cause(void)
{
return -ENOSYS;
}
int __weak z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
{
return -ENOSYS;
}