diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 6316722c1c5..45d0fb297c1 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -23,3 +23,4 @@ zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM hwinfo_sam.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM0 hwinfo_sam0.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM4L hwinfo_sam4l.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_STM32 hwinfo_stm32.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_ANDES hwinfo_andes.c) diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index 57caf04c0fb..5d31786a2fa 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -144,4 +144,11 @@ config HWINFO_GECKO help Enable Silabs GECKO hwinfo driver. +config HWINFO_ANDES + bool "Andes system ID" + default y + depends on SOC_SERIES_RISCV_ANDES_V5 + help + Enable Andes hwinfo driver + endif diff --git a/drivers/hwinfo/hwinfo_andes.c b/drivers/hwinfo/hwinfo_andes.c new file mode 100644 index 00000000000..08a7e52a76e --- /dev/null +++ b/drivers/hwinfo/hwinfo_andes.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/* + * SMU(System Management Unit) Registers for hwinfo driver + */ + +/* Register offset*/ +#define SMU_SYSTEMVER 0x00 +#define SMU_WRSR 0x10 + +/* Wake-Up and Reset Status Register bitmask */ +#define SMU_WRSR_APOR BIT(0) +#define SMU_WRSR_MPOR BIT(1) +#define SMU_WRSR_HW BIT(2) +#define SMU_WRSR_WDT BIT(3) +#define SMU_WRSR_SW BIT(4) + +#define ANDES_RESET_STATUS_MASK BIT_MASK(5) + +ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) +{ + int ret = 0; + uint8_t id[3]; + uint32_t ver; + const struct device *const syscon_dev = + DEVICE_DT_GET(DT_NODELABEL(syscon)); + + ret = syscon_read_reg(syscon_dev, SMU_SYSTEMVER, &ver); + if (ret < 0) { + return ret; + } + + if (length > sizeof(id)) { + length = sizeof(id); + } + + id[0] = (uint8_t)(ver >> 16); + id[1] = (uint8_t)(ver >> 8); + id[2] = (uint8_t)(ver >> 0); + + memcpy(buffer, id, length); + + return length; +} + +int z_impl_hwinfo_get_reset_cause(uint32_t *cause) +{ + int ret = 0; + uint32_t reason, flags = 0; + const struct device *const syscon_dev = + DEVICE_DT_GET(DT_NODELABEL(syscon)); + + ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason); + if (ret < 0) { + return ret; + } + + if (reason & SMU_WRSR_APOR) { + flags |= RESET_POR; + } + if (reason & SMU_WRSR_MPOR) { + flags |= RESET_POR; + } + if (reason & SMU_WRSR_HW) { + flags |= RESET_PIN; + } + if (reason & SMU_WRSR_WDT) { + flags |= RESET_WATCHDOG; + } + if (reason & SMU_WRSR_SW) { + flags |= RESET_SOFTWARE; + } + + *cause = flags; + + return 0; +} + +int z_impl_hwinfo_clear_reset_cause(void) +{ + int ret = 0; + uint32_t reason; + const struct device *const syscon_dev = + DEVICE_DT_GET(DT_NODELABEL(syscon)); + + ret = syscon_write_reg(syscon_dev, SMU_WRSR, ANDES_RESET_STATUS_MASK); + if (ret < 0) { + return ret; + } + + do { + ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason); + } while ((reason & ANDES_RESET_STATUS_MASK) && (!ret)); + + return ret; +} + +int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) +{ + *supported = (RESET_PIN + | RESET_WATCHDOG + | RESET_SOFTWARE + | RESET_POR); + + return 0; +}