|  | /* | 
|  | * Copyright (c) 2018 Alexander Wachter | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <soc.h> | 
|  | #include <zephyr/drivers/hwinfo.h> | 
|  | #include <string.h> | 
|  | #include <zephyr/sys/byteorder.h> | 
|  | #if defined(CONFIG_BOARD_QEMU_CORTEX_M0) || \ | 
|  | (defined(CONFIG_NRF_PLATFORM_HALTIUM) && \ | 
|  | defined(CONFIG_RISCV_CORE_NORDIC_VPR)) | 
|  | #define RESET_CAUSE_AVAILABLE 0 | 
|  | #else | 
|  | #include <helpers/nrfx_reset_reason.h> | 
|  | #define RESET_CAUSE_AVAILABLE 1 | 
|  | #endif | 
|  |  | 
|  | #if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) | 
|  | #include <soc_secure.h> | 
|  | #else | 
|  | #include <hal/nrf_ficr.h> | 
|  | #endif | 
|  |  | 
|  | struct nrf_uid { | 
|  | uint32_t id[2]; | 
|  | }; | 
|  |  | 
|  | ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) | 
|  | { | 
|  | struct nrf_uid dev_id; | 
|  | uint32_t buf[2]; | 
|  |  | 
|  | #if NRF_FICR_HAS_DEVICE_ID || NRF_FICR_HAS_INFO_DEVICE_ID | 
|  | /* DEVICEID is accessible, use this */ | 
|  | #if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) | 
|  | soc_secure_read_deviceid(buf); | 
|  | #else | 
|  | buf[0] = nrf_ficr_deviceid_get(NRF_FICR, 0); | 
|  | buf[1] = nrf_ficr_deviceid_get(NRF_FICR, 1); | 
|  | #endif | 
|  | #elif NRF_FICR_HAS_DEVICE_ADDR || NRF_FICR_HAS_BLE_ADDR | 
|  | /* DEVICEID is not accessible, use device/Bluetooth LE address instead. | 
|  | * Assume that it is always accessible from the non-secure image. | 
|  | */ | 
|  | buf[0] = nrf_ficr_deviceaddr_get(NRF_FICR, 0); | 
|  | buf[1] = nrf_ficr_deviceaddr_get(NRF_FICR, 1); | 
|  |  | 
|  | /* Assume that ER and IR are available whenever deviceaddr is. | 
|  | * Use the LSBytes from ER and IR to complete the device id. | 
|  | */ | 
|  | buf[1] |= (nrf_ficr_er_get(NRF_FICR, 0) & 0xFF) << 16; | 
|  | buf[1] |= (nrf_ficr_ir_get(NRF_FICR, 0) & 0xFF) << 24; | 
|  | #else | 
|  | #error "No suitable source for hwinfo device_id generation" | 
|  | #endif | 
|  |  | 
|  | dev_id.id[0] = sys_cpu_to_be32(buf[1]); | 
|  | dev_id.id[1] = sys_cpu_to_be32(buf[0]); | 
|  |  | 
|  | if (length > sizeof(dev_id.id)) { | 
|  | length = sizeof(dev_id.id); | 
|  | } | 
|  |  | 
|  | memcpy(buffer, dev_id.id, length); | 
|  |  | 
|  | return length; | 
|  | } | 
|  |  | 
|  | #if RESET_CAUSE_AVAILABLE | 
|  |  | 
|  | #if defined(NRF_RESETINFO) | 
|  |  | 
|  | #define REASON_LOCKUP (NRFX_RESET_REASON_LOCKUP_MASK | NRFX_RESET_REASON_LOCAL_LOCKUP_MASK) | 
|  | #define REASON_SOFTWARE (NRFX_RESET_REASON_SREQ_MASK | NRFX_RESET_REASON_LOCAL_SREQ_MASK) | 
|  | #define REASON_WATCHDOG	\ | 
|  | (NRFX_RESET_REASON_DOG_MASK | \ | 
|  | NRFX_RESET_REASON_LOCAL_DOG1_MASK | \ | 
|  | NRFX_RESET_REASON_LOCAL_DOG0_MASK) | 
|  |  | 
|  | #else /* NRF_RESETINFO */ | 
|  |  | 
|  | #define REASON_LOCKUP NRFX_RESET_REASON_LOCKUP_MASK | 
|  | #define REASON_SOFTWARE NRFX_RESET_REASON_SREQ_MASK | 
|  |  | 
|  | #if NRF_POWER_HAS_RESETREAS | 
|  | #define REASON_WATCHDOG NRFX_RESET_REASON_DOG_MASK | 
|  | #else | 
|  | #define REASON_WATCHDOG	(NRFX_RESET_REASON_DOG0_MASK | NRFX_RESET_REASON_DOG1_MASK) | 
|  | #endif /* NRF_POWER_HAS_RESETREAS */ | 
|  |  | 
|  | #endif /* NRF_RESETINFO */ | 
|  |  | 
|  | 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 & REASON_WATCHDOG) { | 
|  | flags |= RESET_WATCHDOG; | 
|  | } | 
|  |  | 
|  | if (reason & REASON_LOCKUP) { | 
|  | 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 (reason & REASON_SOFTWARE) { | 
|  | flags |= RESET_SOFTWARE; | 
|  | } | 
|  |  | 
|  | #if NRFX_RESET_REASON_HAS_CTRLAP | 
|  | if (reason & NRFX_RESET_REASON_CTRLAP_MASK) { | 
|  | flags |= RESET_DEBUG; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_LPCOMP | 
|  | if (reason & NRFX_RESET_REASON_LPCOMP_MASK) { | 
|  | flags |= RESET_LOW_POWER_WAKE; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_NFC | 
|  | if (reason & NRFX_RESET_REASON_NFC_MASK) { | 
|  | flags |= RESET_LOW_POWER_WAKE; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_VBUS | 
|  | if (reason & NRFX_RESET_REASON_VBUS_MASK) { | 
|  | flags |= RESET_POR; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_CTRLAPSOFT | 
|  | if (reason & NRFX_RESET_REASON_CTRLAPSOFT_MASK) { | 
|  | flags |= RESET_DEBUG; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_CTRLAPHARD | 
|  | if (reason & NRFX_RESET_REASON_CTRLAPHARD_MASK) { | 
|  | flags |= RESET_DEBUG; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_HAS_CTRLAPPIN | 
|  | if (reason & NRFX_RESET_REASON_CTRLAPPIN_MASK) { | 
|  | flags |= RESET_DEBUG; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if NRFX_RESET_REASON_HAS_GRTC | 
|  | if (reason & NRFX_RESET_REASON_GRTC_MASK) { | 
|  | flags |= RESET_CLOCK; | 
|  | } | 
|  | #endif | 
|  | #if NRFX_RESET_REASON_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 | 
|  | #if defined(NRFX_RESET_REASON_TAMPC_MASK) | 
|  | if (reason & NRFX_RESET_REASON_TAMPC_MASK) { | 
|  | flags |= RESET_SECURITY; | 
|  | } | 
|  | #endif | 
|  | #if defined(NRFX_RESET_REASON_SECTAMPER_MASK) | 
|  | if (reason & NRFX_RESET_REASON_SECTAMPER_MASK) { | 
|  | flags |= RESET_SECURITY; | 
|  | } | 
|  | #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 /* RESET_CAUSE_AVAILABLE */ |