/* * Copyright (c) 2022 Yonatan Schachter * Copyright (c) 2024 Andrew Featherstone * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #if defined(CONFIG_SOC_SERIES_RP2040) #include #else #include #endif #define FLASH_RUID_DATA_BYTES 8 #if defined(CONFIG_SOC_SERIES_RP2040) #define HAD_RUN_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_LSB) #define HAD_PSM_RESTART_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_LSB) #define HAD_POR_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_LSB) #else #define HAD_RUN_BIT BIT(POWMAN_CHIP_RESET_HAD_RUN_LOW_LSB) #define HAD_PSM_RESTART_BIT BIT(POWMAN_CHIP_RESET_HAD_DP_RESET_REQ_LSB) #define HAD_POR_BIT BIT(POWMAN_CHIP_RESET_HAD_POR_LSB) #endif ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) { uint8_t id[FLASH_RUID_DATA_BYTES]; uint32_t key; /* * flash_get_unique_id temporarily disables XIP to query the * flash for its ID. If the CPU is interrupted while XIP is * disabled, it will halt. Therefore, interrupts must be disabled * before fetching the ID. */ key = irq_lock(); flash_get_unique_id(id); irq_unlock(key); if (length > sizeof(id)) { length = sizeof(id); } memcpy(buffer, id, length); return length; } int z_impl_hwinfo_get_reset_cause(uint32_t *cause) { uint32_t flags = 0; #if defined(CONFIG_SOC_SERIES_RP2040) uint32_t reset_register = vreg_and_chip_reset_hw->chip_reset; #else uint32_t reset_register = powman_hw->chip_reset; #endif if (reset_register & HAD_POR_BIT) { flags |= RESET_POR; } if (reset_register & HAD_RUN_BIT) { flags |= RESET_PIN; } if (reset_register & HAD_PSM_RESTART_BIT) { flags |= RESET_DEBUG; } #if defined(CONFIG_SOC_SERIES_RP2350) if (reset_register & POWMAN_CHIP_RESET_HAD_BOR_BITS) { flags |= RESET_BROWNOUT; } if (reset_register & (POWMAN_CHIP_RESET_HAD_WATCHDOG_RESET_RSM_BITS | POWMAN_CHIP_RESET_HAD_WATCHDOG_RESET_SWCORE_BITS | POWMAN_CHIP_RESET_HAD_WATCHDOG_RESET_POWMAN_BITS | POWMAN_CHIP_RESET_HAD_WATCHDOG_RESET_POWMAN_ASYNC_BITS)) { flags |= RESET_WATCHDOG; } #endif *cause = flags; return 0; } int z_impl_hwinfo_clear_reset_cause(void) { /* The reset register can't be modified, nothing to do. */ return -ENOSYS; } int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) { *supported = RESET_PIN | RESET_DEBUG | RESET_POR; #if defined(CONFIG_SOC_SERIES_RP2350) *supported |= RESET_BROWNOUT | RESET_WATCHDOG; #endif return 0; }