zephyr/drivers/hwinfo/hwinfo_nrf.c
Carles Cufi ebd31d3916 drivers: hwinfo: Add support for generating device id from device addr
In some ICs (including nRF54H20) the DEVICEID register is not part of
FICR, and thus it is not accessible to applications. Use instead the
device address, along with a couple of bytes from ER and IR, to
generated a unique device id.

At the same time update the pointer to the hal_nordic repo to pull in
https://github.com/zephyrproject-rtos/hal_nordic/pull/196.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
2024-08-02 13:49:54 +01:00

188 lines
4.3 KiB
C

/*
* 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_SOC_SERIES_NRF54HX) && !defined(CONFIG_BOARD_QEMU_CORTEX_M0)
#include <helpers/nrfx_reset_reason.h>
#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/ble 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 !defined(CONFIG_SOC_SERIES_NRF54HX) && !defined(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 (reason & NRFX_RESET_REASON_SREQ_MASK) {
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 !NRF_POWER_HAS_RESETREAS
if (reason & NRFX_RESET_REASON_DOG1_MASK) {
flags |= RESET_WATCHDOG;
}
#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