1 /* 2 * Copyright (c) 2021, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <string.h> 9 10 #include <common/debug.h> 11 #include <common/fdt_wrappers.h> 12 #include <libfdt.h> 13 #include <plat/arm/common/fconf_ethosn_getter.h> 14 15 struct ethosn_config_t ethosn_config; 16 17 static uint8_t fdt_node_get_status(const void *fdt, int node) 18 { 19 int len; 20 uint8_t status = ETHOSN_STATUS_DISABLED; 21 const char *node_status; 22 23 node_status = fdt_getprop(fdt, node, "status", &len); 24 if (node_status == NULL || 25 (len == 5 && /* Includes null character */ 26 strncmp(node_status, "okay", 4U) == 0)) { 27 status = ETHOSN_STATUS_ENABLED; 28 } 29 30 return status; 31 } 32 33 int fconf_populate_ethosn_config(uintptr_t config) 34 { 35 int ethosn_node; 36 int sub_node; 37 uint8_t ethosn_status; 38 uint32_t core_count = 0U; 39 uint32_t core_addr_idx = 0U; 40 const void *hw_conf_dtb = (const void *)config; 41 42 /* Find offset to node with 'ethosn' compatible property */ 43 ethosn_node = fdt_node_offset_by_compatible(hw_conf_dtb, -1, "ethosn"); 44 if (ethosn_node < 0) { 45 ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n"); 46 return ethosn_node; 47 } 48 49 /* If the Arm Ethos-N NPU is disabled the core check can be skipped */ 50 ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node); 51 if (ethosn_status == ETHOSN_STATUS_DISABLED) { 52 return 0; 53 } 54 55 fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) { 56 int err; 57 uintptr_t addr; 58 uint8_t status; 59 60 /* Check that the sub node is "ethosn-core" compatible */ 61 if (fdt_node_check_compatible(hw_conf_dtb, sub_node, 62 "ethosn-core") != 0) { 63 /* Ignore incompatible sub node */ 64 continue; 65 } 66 67 /* Including disabled cores */ 68 if (core_addr_idx >= ETHOSN_CORE_NUM_MAX) { 69 ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n"); 70 return -1; 71 } 72 73 status = fdt_node_get_status(hw_conf_dtb, ethosn_node); 74 if (status == ETHOSN_STATUS_DISABLED) { 75 ++core_addr_idx; 76 continue; 77 } 78 79 err = fdt_get_reg_props_by_index(hw_conf_dtb, ethosn_node, 80 core_addr_idx, &addr, NULL); 81 if (err < 0) { 82 ERROR("FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n", 83 core_addr_idx); 84 return err; 85 } 86 87 ethosn_config.core_addr[core_count++] = addr; 88 ++core_addr_idx; 89 } 90 91 if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) { 92 ERROR("FCONF: Failed to parse sub nodes\n"); 93 return sub_node; 94 } 95 96 /* The Arm Ethos-N NPU can't be used if no cores were found */ 97 if (core_count == 0) { 98 ERROR("FCONF: No Arm Ethos-N NPU cores found\n"); 99 return -1; 100 } 101 102 ethosn_config.num_cores = core_count; 103 ethosn_config.status = ethosn_status; 104 105 return 0; 106 } 107 108 FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config); 109