blob: 1ba9f3a23a2f978e5ec0544d743a5d6d7ef977d1 [file] [log] [blame]
Mikael Olsson7da66192021-02-12 17:30:22 +01001/*
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
15struct ethosn_config_t ethosn_config;
16
17static 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
33int 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
108FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);