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