mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 17:44:19 +00:00
Add SiP service to configure Arm Ethos-N NPU
By default the Arm Ethos-N NPU will boot up in secure mode. In this mode the non-secure world cannot access the registers needed to use the NPU. To still allow the non-secure world to use the NPU, a SiP service has been added that can delegate non-secure access to the registers needed to use it. Only the HW_CONFIG for the Arm Juno platform has been updated to include the device tree for the NPU and the platform currently only loads the HW_CONFIG in AArch64 builds. Signed-off-by: Mikael Olsson <mikael.olsson@arm.com> Change-Id: I65dfd864042ed43faae0a259dcf319cbadb5f3d2
This commit is contained in:
parent
5d5fb10f9c
commit
76a21174d2
10 changed files with 452 additions and 7 deletions
|
@ -91,6 +91,12 @@ Arm Platform Build Options
|
|||
platforms. If this option is specified, then the path to the CryptoCell
|
||||
SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag.
|
||||
|
||||
- ``ARM_ETHOSN_NPU_DRIVER``: boolean option to enable a SiP service that can
|
||||
configure an Arm Ethos-N NPU. To use this service the target platform's
|
||||
``HW_CONFIG`` must include the device tree nodes for the NPU. Currently, only
|
||||
the Arm Juno platform has this included in its ``HW_CONFIG`` and the platform
|
||||
only loads the ``HW_CONFIG`` in AArch64 builds. Default is 0.
|
||||
|
||||
- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
|
||||
SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
|
||||
|
||||
|
@ -128,4 +134,4 @@ Arm CSS Platform-Specific Build Options
|
|||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
|
||||
*Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
|
||||
|
|
164
drivers/arm/ethosn/ethosn_smc.c
Normal file
164
drivers/arm/ethosn/ethosn_smc.c
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <drivers/arm/ethosn.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/arm/common/fconf_ethosn_getter.h>
|
||||
|
||||
/* Arm Ethos-N NPU (NPU) status */
|
||||
#define ETHOSN_STATUS \
|
||||
FCONF_GET_PROPERTY(hw_config, ethosn_config, status)
|
||||
|
||||
/* Number of NPU cores available */
|
||||
#define ETHOSN_NUM_CORES \
|
||||
FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores)
|
||||
|
||||
/* Address to an NPU core */
|
||||
#define ETHOSN_CORE_ADDR(core_idx) \
|
||||
FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx)
|
||||
|
||||
/* NPU core sec registry address */
|
||||
#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
|
||||
(core_addr + reg_offset)
|
||||
|
||||
/* Reset timeout in us */
|
||||
#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000)
|
||||
#define ETHOSN_RESET_WAIT_US U(1)
|
||||
|
||||
#define SEC_DEL_REG U(0x0004)
|
||||
#define SEC_DEL_VAL U(0x81C)
|
||||
#define SEC_DEL_EXCC_MASK U(0x20)
|
||||
|
||||
#define SEC_SECCTLR_REG U(0x0010)
|
||||
#define SEC_SECCTLR_VAL U(0x3)
|
||||
|
||||
#define SEC_DEL_MMUSID_REG U(0x2008)
|
||||
#define SEC_DEL_MMUSID_VAL U(0x3FFFF)
|
||||
|
||||
#define SEC_DEL_ADDR_EXT_REG U(0x201C)
|
||||
#define SEC_DEL_ADDR_EXT_VAL U(0x15)
|
||||
|
||||
#define SEC_SYSCTRL0_REG U(0x0018)
|
||||
#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29)
|
||||
#define SEC_SYSCTRL0_HARD_RESET U(1U << 31)
|
||||
|
||||
static void ethosn_delegate_to_ns(uintptr_t core_addr)
|
||||
{
|
||||
mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
|
||||
SEC_SECCTLR_VAL);
|
||||
|
||||
mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
|
||||
SEC_DEL_VAL);
|
||||
|
||||
mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG),
|
||||
SEC_DEL_MMUSID_VAL);
|
||||
|
||||
mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
|
||||
SEC_DEL_ADDR_EXT_VAL);
|
||||
}
|
||||
|
||||
static int ethosn_is_sec(void)
|
||||
{
|
||||
if ((mmio_read_32(ETHOSN_CORE_SEC_REG(ETHOSN_CORE_ADDR(0), SEC_DEL_REG))
|
||||
& SEC_DEL_EXCC_MASK) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
|
||||
{
|
||||
unsigned int timeout;
|
||||
const uintptr_t sysctrl0_reg =
|
||||
ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
|
||||
const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
|
||||
: SEC_SYSCTRL0_SOFT_RESET;
|
||||
|
||||
mmio_write_32(sysctrl0_reg, reset_val);
|
||||
|
||||
/* Wait for reset to complete */
|
||||
for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
|
||||
timeout += ETHOSN_RESET_WAIT_US) {
|
||||
|
||||
if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(ETHOSN_RESET_WAIT_US);
|
||||
}
|
||||
|
||||
return timeout < ETHOSN_RESET_TIMEOUT_US;
|
||||
}
|
||||
|
||||
uintptr_t ethosn_smc_handler(uint32_t smc_fid,
|
||||
u_register_t core_idx,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
uintptr_t core_addr;
|
||||
int hard_reset = 0;
|
||||
|
||||
/* Only SiP fast calls are expected */
|
||||
if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
|
||||
(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
/* Truncate parameters to 32-bits for SMC32 */
|
||||
if (GET_SMC_CC(smc_fid) == SMC_32) {
|
||||
core_idx &= 0xFFFFFFFF;
|
||||
x2 &= 0xFFFFFFFF;
|
||||
x3 &= 0xFFFFFFFF;
|
||||
x4 &= 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if (!is_ethosn_fid(smc_fid)) {
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
if (ETHOSN_STATUS == ETHOSN_STATUS_DISABLED) {
|
||||
WARN("ETHOSN: Arm Ethos-N NPU not available\n");
|
||||
SMC_RET1(handle, ETHOSN_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
switch (smc_fid & FUNCID_NUM_MASK) {
|
||||
case ETHOSN_FNUM_VERSION:
|
||||
SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
|
||||
case ETHOSN_FNUM_IS_SEC:
|
||||
SMC_RET1(handle, ethosn_is_sec());
|
||||
case ETHOSN_FNUM_HARD_RESET:
|
||||
hard_reset = 1;
|
||||
/* Fallthrough */
|
||||
case ETHOSN_FNUM_SOFT_RESET:
|
||||
if (core_idx >= ETHOSN_NUM_CORES) {
|
||||
WARN("ETHOSN: core index out of range\n");
|
||||
SMC_RET1(handle, ETHOSN_CORE_IDX_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
core_addr = ETHOSN_CORE_ADDR(core_idx);
|
||||
|
||||
if (!ethosn_reset(core_addr, hard_reset)) {
|
||||
SMC_RET1(handle, ETHOSN_FAILURE);
|
||||
}
|
||||
|
||||
ethosn_delegate_to_ns(core_addr);
|
||||
|
||||
SMC_RET1(handle, ETHOSN_SUCCESS);
|
||||
default:
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
}
|
25
fdts/juno-ethosn.dtsi
Normal file
25
fdts/juno-ethosn.dtsi
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
ethosn: ethosn@6f300000 {
|
||||
compatible = "ethosn";
|
||||
reg = <0 0x6f300000 0 0x00100000>;
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* Single-core NPU. For multi-core NPU, additional core nodes
|
||||
* and reg values must be added.
|
||||
*/
|
||||
core0 {
|
||||
compatible = "ethosn-core";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -9,3 +9,7 @@
|
|||
/ {
|
||||
|
||||
};
|
||||
|
||||
#if ARM_ETHOSN_NPU_DRIVER
|
||||
#include "juno-ethosn.dtsi"
|
||||
#endif
|
||||
|
|
61
include/drivers/arm/ethosn.h
Normal file
61
include/drivers/arm/ethosn.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef ETHOSN_H
|
||||
#define ETHOSN_H
|
||||
|
||||
#include <lib/smccc.h>
|
||||
|
||||
/* Function numbers */
|
||||
#define ETHOSN_FNUM_VERSION U(0x50)
|
||||
#define ETHOSN_FNUM_IS_SEC U(0x51)
|
||||
#define ETHOSN_FNUM_HARD_RESET U(0x52)
|
||||
#define ETHOSN_FNUM_SOFT_RESET U(0x53)
|
||||
/* 0x54-0x5F reserved for future use */
|
||||
|
||||
/* SMC64 function IDs */
|
||||
#define ETHOSN_FID_64(func_num) U(0xC2000000 | func_num)
|
||||
#define ETHOSN_FID_VERSION_64 ETHOSN_FID_64(ETHOSN_FNUM_VERSION)
|
||||
#define ETHOSN_FID_IS_SEC_64 ETHOSN_FID_64(ETHOSN_FNUM_IS_SEC)
|
||||
#define ETHOSN_FID_HARD_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_HARD_RESET)
|
||||
#define ETHOSN_FID_SOFT_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_SOFT_RESET)
|
||||
|
||||
/* SMC32 function IDs */
|
||||
#define ETHOSN_FID_32(func_num) U(0x82000000 | func_num)
|
||||
#define ETHOSN_FID_VERSION_32 ETHOSN_FID_32(ETHOSN_FNUM_VERSION)
|
||||
#define ETHOSN_FID_IS_SEC_32 ETHOSN_FID_32(ETHOSN_FNUM_IS_SEC)
|
||||
#define ETHOSN_FID_HARD_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_HARD_RESET)
|
||||
#define ETHOSN_FID_SOFT_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_SOFT_RESET)
|
||||
|
||||
#define ETHOSN_NUM_SMC_CALLS 8
|
||||
|
||||
/* Macro to identify function calls */
|
||||
#define ETHOSN_FID_MASK U(0xFFF0)
|
||||
#define ETHOSN_FID_VALUE U(0x50)
|
||||
#define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE)
|
||||
|
||||
/* Service version */
|
||||
#define ETHOSN_VERSION_MAJOR U(0)
|
||||
#define ETHOSN_VERSION_MINOR U(1)
|
||||
|
||||
/* Return codes for function calls */
|
||||
#define ETHOSN_SUCCESS 0
|
||||
#define ETHOSN_NOT_SUPPORTED -1
|
||||
/* -2 Reserved for NOT_REQUIRED */
|
||||
/* -3 Reserved for INVALID_PARAMETER */
|
||||
#define ETHOSN_FAILURE -4
|
||||
#define ETHOSN_CORE_IDX_OUT_OF_RANGE -5
|
||||
|
||||
uintptr_t ethosn_smc_handler(uint32_t smc_fid,
|
||||
u_register_t core_idx,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags);
|
||||
|
||||
#endif /* ETHOSN_H */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -25,6 +25,12 @@
|
|||
/* DEBUGFS_SMC_32 0x82000030U */
|
||||
/* DEBUGFS_SMC_64 0xC2000030U */
|
||||
|
||||
/*
|
||||
* Arm Ethos-N NPU SiP SMC function IDs
|
||||
* 0xC2000050-0xC200005F
|
||||
* 0x82000050-0x8200005F
|
||||
*/
|
||||
|
||||
/* ARM SiP Service Calls version numbers */
|
||||
#define ARM_SIP_SVC_VERSION_MAJOR U(0x0)
|
||||
#define ARM_SIP_SVC_VERSION_MINOR U(0x2)
|
||||
|
|
35
include/plat/arm/common/fconf_ethosn_getter.h
Normal file
35
include/plat/arm/common/fconf_ethosn_getter.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef FCONF_ETHOSN_GETTER_H
|
||||
#define FCONF_ETHOSN_GETTER_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <lib/fconf/fconf.h>
|
||||
|
||||
#define hw_config__ethosn_config_getter(prop) ethosn_config.prop
|
||||
#define hw_config__ethosn_core_addr_getter(idx) __extension__ ({ \
|
||||
assert(idx < ethosn_config.num_cores); \
|
||||
ethosn_config.core_addr[idx]; \
|
||||
})
|
||||
|
||||
#define ETHOSN_STATUS_DISABLED U(0)
|
||||
#define ETHOSN_STATUS_ENABLED U(1)
|
||||
|
||||
#define ETHOSN_CORE_NUM_MAX U(64)
|
||||
|
||||
struct ethosn_config_t {
|
||||
uint8_t status;
|
||||
uint32_t num_cores;
|
||||
uint64_t core_addr[ETHOSN_CORE_NUM_MAX];
|
||||
};
|
||||
|
||||
int fconf_populate_arm_ethosn(uintptr_t config);
|
||||
|
||||
extern struct ethosn_config_t ethosn_config;
|
||||
|
||||
#endif /* FCONF_ETHOSN_GETTER_H */
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
||||
# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
@ -100,6 +100,11 @@ ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
|
|||
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
|
||||
endif
|
||||
|
||||
# Arm Ethos-N NPU SiP service
|
||||
ARM_ETHOSN_NPU_DRIVER := 0
|
||||
$(eval $(call assert_boolean,ARM_ETHOSN_NPU_DRIVER))
|
||||
$(eval $(call add_define,ARM_ETHOSN_NPU_DRIVER))
|
||||
|
||||
# Use an implementation of SHA-256 with a smaller memory footprint but reduced
|
||||
# speed.
|
||||
$(eval $(call add_define,MBEDTLS_SHA256_SMALLER))
|
||||
|
@ -248,14 +253,26 @@ BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \
|
|||
plat/arm/common/arm_topology.c \
|
||||
plat/common/plat_psci_common.c
|
||||
|
||||
ifeq (${ENABLE_PMF}, 1)
|
||||
ifneq ($(filter 1,${ENABLE_PMF} ${ARM_ETHOSN_NPU_DRIVER}),)
|
||||
ARM_SVC_HANDLER_SRCS :=
|
||||
|
||||
ifeq (${ENABLE_PMF},1)
|
||||
ARM_SVC_HANDLER_SRCS += lib/pmf/pmf_smc.c
|
||||
endif
|
||||
|
||||
ifeq (${ARM_ETHOSN_NPU_DRIVER},1)
|
||||
ARM_SVC_HANDLER_SRCS += plat/arm/common/fconf/fconf_ethosn_getter.c \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/arm/ethosn/ethosn_smc.c
|
||||
endif
|
||||
|
||||
ifeq (${ARCH}, aarch64)
|
||||
BL31_SOURCES += plat/arm/common/aarch64/execution_state_switch.c\
|
||||
plat/arm/common/arm_sip_svc.c \
|
||||
lib/pmf/pmf_smc.c
|
||||
${ARM_SVC_HANDLER_SRCS}
|
||||
else
|
||||
BL32_SOURCES += plat/arm/common/arm_sip_svc.c \
|
||||
lib/pmf/pmf_smc.c
|
||||
${ARM_SVC_HANDLER_SRCS}
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <drivers/arm/ethosn.h>
|
||||
#include <lib/debugfs.h>
|
||||
#include <lib/pmf/pmf.h>
|
||||
#include <plat/arm/common/arm_sip_svc.h>
|
||||
|
@ -50,6 +51,8 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
|
|||
{
|
||||
int call_count = 0;
|
||||
|
||||
#if ENABLE_PMF
|
||||
|
||||
/*
|
||||
* Dispatch PMF calls to PMF SMC handler and return its return
|
||||
* value
|
||||
|
@ -59,6 +62,8 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
|
|||
handle, flags);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_PMF */
|
||||
|
||||
#if USE_DEBUGFS
|
||||
|
||||
if (is_debugfs_fid(smc_fid)) {
|
||||
|
@ -68,6 +73,15 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
|
|||
|
||||
#endif /* USE_DEBUGFS */
|
||||
|
||||
#if ARM_ETHOSN_NPU_DRIVER
|
||||
|
||||
if (is_ethosn_fid(smc_fid)) {
|
||||
return ethosn_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
|
||||
handle, flags);
|
||||
}
|
||||
|
||||
#endif /* ARM_ETHOSN_NPU_DRIVER */
|
||||
|
||||
switch (smc_fid) {
|
||||
case ARM_SIP_SVC_EXE_STATE_SWITCH: {
|
||||
/* Execution state can be switched only if EL3 is AArch64 */
|
||||
|
@ -92,6 +106,11 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
|
|||
/* PMF calls */
|
||||
call_count += PMF_NUM_SMC_CALLS;
|
||||
|
||||
#if ARM_ETHOSN_NPU_DRIVER
|
||||
/* ETHOSN calls */
|
||||
call_count += ETHOSN_NUM_SMC_CALLS;
|
||||
#endif /* ARM_ETHOSN_NPU_DRIVER */
|
||||
|
||||
/* State switch call */
|
||||
call_count += 1;
|
||||
|
||||
|
|
108
plat/arm/common/fconf/fconf_ethosn_getter.c
Normal file
108
plat/arm/common/fconf/fconf_ethosn_getter.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/arm/common/fconf_ethosn_getter.h>
|
||||
|
||||
struct ethosn_config_t ethosn_config;
|
||||
|
||||
static uint8_t fdt_node_get_status(const void *fdt, int node)
|
||||
{
|
||||
int len;
|
||||
uint8_t status = ETHOSN_STATUS_DISABLED;
|
||||
const char *node_status;
|
||||
|
||||
node_status = fdt_getprop(fdt, node, "status", &len);
|
||||
if (node_status == NULL ||
|
||||
(len == 5 && /* Includes null character */
|
||||
strncmp(node_status, "okay", 4U) == 0)) {
|
||||
status = ETHOSN_STATUS_ENABLED;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int fconf_populate_ethosn_config(uintptr_t config)
|
||||
{
|
||||
int ethosn_node;
|
||||
int sub_node;
|
||||
uint8_t ethosn_status;
|
||||
uint32_t core_count = 0U;
|
||||
uint32_t core_addr_idx = 0U;
|
||||
const void *hw_conf_dtb = (const void *)config;
|
||||
|
||||
/* Find offset to node with 'ethosn' compatible property */
|
||||
ethosn_node = fdt_node_offset_by_compatible(hw_conf_dtb, -1, "ethosn");
|
||||
if (ethosn_node < 0) {
|
||||
ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
|
||||
return ethosn_node;
|
||||
}
|
||||
|
||||
/* If the Arm Ethos-N NPU is disabled the core check can be skipped */
|
||||
ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
|
||||
if (ethosn_status == ETHOSN_STATUS_DISABLED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
|
||||
int err;
|
||||
uintptr_t addr;
|
||||
uint8_t status;
|
||||
|
||||
/* Check that the sub node is "ethosn-core" compatible */
|
||||
if (fdt_node_check_compatible(hw_conf_dtb, sub_node,
|
||||
"ethosn-core") != 0) {
|
||||
/* Ignore incompatible sub node */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Including disabled cores */
|
||||
if (core_addr_idx >= ETHOSN_CORE_NUM_MAX) {
|
||||
ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
|
||||
if (status == ETHOSN_STATUS_DISABLED) {
|
||||
++core_addr_idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = fdt_get_reg_props_by_index(hw_conf_dtb, ethosn_node,
|
||||
core_addr_idx, &addr, NULL);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n",
|
||||
core_addr_idx);
|
||||
return err;
|
||||
}
|
||||
|
||||
ethosn_config.core_addr[core_count++] = addr;
|
||||
++core_addr_idx;
|
||||
}
|
||||
|
||||
if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("FCONF: Failed to parse sub nodes\n");
|
||||
return sub_node;
|
||||
}
|
||||
|
||||
/* The Arm Ethos-N NPU can't be used if no cores were found */
|
||||
if (core_count == 0) {
|
||||
ERROR("FCONF: No Arm Ethos-N NPU cores found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ethosn_config.num_cores = core_count;
|
||||
ethosn_config.status = ethosn_status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);
|
Loading…
Add table
Reference in a new issue