xref: /rk3399_ARM-atf/plat/arm/common/fconf/fconf_ethosn_getter.c (revision 42fb812a7525682362096d651a3749787b3bd555)
176a21174SMikael Olsson /*
2*a19a0241SMikael Olsson  * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
376a21174SMikael Olsson  *
476a21174SMikael Olsson  * SPDX-License-Identifier: BSD-3-Clause
576a21174SMikael Olsson  */
676a21174SMikael Olsson 
776a21174SMikael Olsson #include <assert.h>
876a21174SMikael Olsson #include <string.h>
976a21174SMikael Olsson 
1076a21174SMikael Olsson #include <common/debug.h>
1176a21174SMikael Olsson #include <common/fdt_wrappers.h>
1276a21174SMikael Olsson #include <libfdt.h>
1376a21174SMikael Olsson #include <plat/arm/common/fconf_ethosn_getter.h>
1476a21174SMikael Olsson 
15b139f1cfSMikael Olsson struct ethosn_config_t ethosn_config = {0};
1676a21174SMikael Olsson 
17b139f1cfSMikael Olsson struct ethosn_sub_allocator_t {
18b139f1cfSMikael Olsson 	const char *name;
19b139f1cfSMikael Olsson 	size_t name_len;
20b139f1cfSMikael Olsson 	uint32_t stream_id;
21b139f1cfSMikael Olsson };
22b139f1cfSMikael Olsson 
fdt_node_read_reserved_memory_addr(const void * fdt,int dev_node,uint64_t * reserved_mem_addrs)23*a19a0241SMikael Olsson static int fdt_node_read_reserved_memory_addr(const void *fdt,
24*a19a0241SMikael Olsson 					      int dev_node,
25*a19a0241SMikael Olsson 					      uint64_t *reserved_mem_addrs)
26*a19a0241SMikael Olsson {
27*a19a0241SMikael Olsson 	uintptr_t addr;
28*a19a0241SMikael Olsson 	uint32_t phandle;
29*a19a0241SMikael Olsson 	int err;
30*a19a0241SMikael Olsson 	int mem_node;
31*a19a0241SMikael Olsson 
32*a19a0241SMikael Olsson 	err = fdt_read_uint32(fdt, dev_node, "memory-region", &phandle);
33*a19a0241SMikael Olsson 	if (err != 0) {
34*a19a0241SMikael Olsson 		ERROR("FCONF: Failed to get reserved memory phandle\n");
35*a19a0241SMikael Olsson 		return err;
36*a19a0241SMikael Olsson 	}
37*a19a0241SMikael Olsson 
38*a19a0241SMikael Olsson 	mem_node = fdt_node_offset_by_phandle(fdt, phandle);
39*a19a0241SMikael Olsson 	if (mem_node < 0) {
40*a19a0241SMikael Olsson 		ERROR("FCONF: Failed to find reserved memory node from phandle\n");
41*a19a0241SMikael Olsson 		return mem_node;
42*a19a0241SMikael Olsson 	}
43*a19a0241SMikael Olsson 
44*a19a0241SMikael Olsson 	err = fdt_get_reg_props_by_index(fdt, mem_node, 0U, &addr, NULL);
45*a19a0241SMikael Olsson 	if (err != 0) {
46*a19a0241SMikael Olsson 		ERROR("FCONF: Failed to read reserved memory address\n");
47*a19a0241SMikael Olsson 		return err;
48*a19a0241SMikael Olsson 	}
49*a19a0241SMikael Olsson 
50*a19a0241SMikael Olsson 	*reserved_mem_addrs = addr;
51*a19a0241SMikael Olsson 
52*a19a0241SMikael Olsson 	return 0;
53*a19a0241SMikael Olsson }
54*a19a0241SMikael Olsson 
fdt_node_has_reserved_memory(const void * fdt,int dev_node)55b139f1cfSMikael Olsson static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
56b139f1cfSMikael Olsson {
57b139f1cfSMikael Olsson 	return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
58b139f1cfSMikael Olsson }
59b139f1cfSMikael Olsson 
fdt_node_get_iommus_stream_id(const void * fdt,int node,uint32_t * stream_id)60b139f1cfSMikael Olsson static int fdt_node_get_iommus_stream_id(const void *fdt, int node, uint32_t *stream_id)
61b139f1cfSMikael Olsson {
62b139f1cfSMikael Olsson 	int err;
63b139f1cfSMikael Olsson 	uint32_t iommus_array[2] = {0U};
64b139f1cfSMikael Olsson 
65b139f1cfSMikael Olsson 	err = fdt_read_uint32_array(fdt, node, "iommus", 2U, iommus_array);
66b139f1cfSMikael Olsson 	if (err) {
67b139f1cfSMikael Olsson 		return err;
68b139f1cfSMikael Olsson 	}
69b139f1cfSMikael Olsson 
70b139f1cfSMikael Olsson 	*stream_id = iommus_array[1];
71b139f1cfSMikael Olsson 	return 0;
72b139f1cfSMikael Olsson }
73b139f1cfSMikael Olsson 
fdt_node_populate_sub_allocators(const void * fdt,int alloc_node,struct ethosn_sub_allocator_t * sub_allocators,size_t num_allocs)74b139f1cfSMikael Olsson static int fdt_node_populate_sub_allocators(const void *fdt,
75b139f1cfSMikael Olsson 					    int alloc_node,
76b139f1cfSMikael Olsson 					    struct ethosn_sub_allocator_t *sub_allocators,
77b139f1cfSMikael Olsson 					    size_t num_allocs)
78b139f1cfSMikael Olsson {
79b139f1cfSMikael Olsson 	int sub_node;
80b139f1cfSMikael Olsson 	size_t i;
81b139f1cfSMikael Olsson 	int err = -FDT_ERR_NOTFOUND;
82b139f1cfSMikael Olsson 	uint32_t found_sub_allocators = 0U;
83b139f1cfSMikael Olsson 
84b139f1cfSMikael Olsson 	fdt_for_each_subnode(sub_node, fdt, alloc_node) {
85b139f1cfSMikael Olsson 		const char *node_name;
86b139f1cfSMikael Olsson 
87b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(fdt, sub_node)) {
88b139f1cfSMikael Olsson 			/* Ignore disabled node */
89b139f1cfSMikael Olsson 			continue;
90b139f1cfSMikael Olsson 		}
91b139f1cfSMikael Olsson 
92b139f1cfSMikael Olsson 		if (fdt_node_check_compatible(fdt, sub_node, "ethosn-memory") != 0) {
93b139f1cfSMikael Olsson 			continue;
94b139f1cfSMikael Olsson 		}
95b139f1cfSMikael Olsson 
96b139f1cfSMikael Olsson 		node_name = fdt_get_name(fdt, sub_node, NULL);
97b139f1cfSMikael Olsson 		for (i = 0U; i < num_allocs; ++i) {
98b139f1cfSMikael Olsson 			if (strncmp(node_name, sub_allocators[i].name,
99b139f1cfSMikael Olsson 				    sub_allocators[i].name_len) != 0) {
100b139f1cfSMikael Olsson 				continue;
101b139f1cfSMikael Olsson 			}
102b139f1cfSMikael Olsson 
103b139f1cfSMikael Olsson 			err = fdt_node_get_iommus_stream_id(fdt, sub_node,
104b139f1cfSMikael Olsson 							    &sub_allocators[i].stream_id);
105b139f1cfSMikael Olsson 			if (err) {
106b139f1cfSMikael Olsson 				ERROR("FCONF: Failed to get stream ID from sub-allocator %s\n",
107b139f1cfSMikael Olsson 				      node_name);
108b139f1cfSMikael Olsson 				return err;
109b139f1cfSMikael Olsson 			}
110b139f1cfSMikael Olsson 
111b139f1cfSMikael Olsson 			++found_sub_allocators;
112b139f1cfSMikael Olsson 			/* Nothing more to do for this node */
113b139f1cfSMikael Olsson 			break;
114b139f1cfSMikael Olsson 		}
115b139f1cfSMikael Olsson 
116b139f1cfSMikael Olsson 		/* Check that at least one of the sub-allocators matched */
117b139f1cfSMikael Olsson 		if (i == num_allocs) {
118b139f1cfSMikael Olsson 			ERROR("FCONF: Unknown sub-allocator %s\n", node_name);
119b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
120b139f1cfSMikael Olsson 		}
121b139f1cfSMikael Olsson 	}
122b139f1cfSMikael Olsson 
123b139f1cfSMikael Olsson 	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
124b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to parse sub-allocators\n");
125b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
126b139f1cfSMikael Olsson 	}
127b139f1cfSMikael Olsson 
128b139f1cfSMikael Olsson 	if (err == -FDT_ERR_NOTFOUND) {
129b139f1cfSMikael Olsson 		ERROR("FCONF: No matching sub-allocator found\n");
130b139f1cfSMikael Olsson 		return err;
131b139f1cfSMikael Olsson 	}
132b139f1cfSMikael Olsson 
133b139f1cfSMikael Olsson 	if (found_sub_allocators != num_allocs) {
134b139f1cfSMikael Olsson 		ERROR("FCONF: Not all sub-allocators were found\n");
135b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
136b139f1cfSMikael Olsson 	}
137b139f1cfSMikael Olsson 
138b139f1cfSMikael Olsson 	return 0;
139b139f1cfSMikael Olsson }
140b139f1cfSMikael Olsson 
fdt_node_populate_main_allocator(const void * fdt,int alloc_node,struct ethosn_main_allocator_t * allocator)141b139f1cfSMikael Olsson static int fdt_node_populate_main_allocator(const void *fdt,
142b139f1cfSMikael Olsson 					    int alloc_node,
143b139f1cfSMikael Olsson 					    struct ethosn_main_allocator_t *allocator)
144b139f1cfSMikael Olsson {
145b139f1cfSMikael Olsson 	int err;
146b139f1cfSMikael Olsson 	struct ethosn_sub_allocator_t sub_allocators[] = {
147b139f1cfSMikael Olsson 		{.name = "firmware", .name_len = 8U},
148b139f1cfSMikael Olsson 		{.name = "working_data", .name_len = 12U}
149b139f1cfSMikael Olsson 	};
150b139f1cfSMikael Olsson 
151b139f1cfSMikael Olsson 	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
152b139f1cfSMikael Olsson 					       ARRAY_SIZE(sub_allocators));
153b139f1cfSMikael Olsson 	if (err) {
154b139f1cfSMikael Olsson 		return err;
155b139f1cfSMikael Olsson 	}
156b139f1cfSMikael Olsson 
157b139f1cfSMikael Olsson 	allocator->firmware.stream_id = sub_allocators[0].stream_id;
158b139f1cfSMikael Olsson 	allocator->working_data.stream_id = sub_allocators[1].stream_id;
159b139f1cfSMikael Olsson 
160b139f1cfSMikael Olsson 	return 0;
161b139f1cfSMikael Olsson }
162b139f1cfSMikael Olsson 
fdt_node_populate_asset_allocator(const void * fdt,int alloc_node,struct ethosn_asset_allocator_t * allocator)163b139f1cfSMikael Olsson static int fdt_node_populate_asset_allocator(const void *fdt,
164b139f1cfSMikael Olsson 					    int alloc_node,
165b139f1cfSMikael Olsson 					    struct ethosn_asset_allocator_t *allocator)
166b139f1cfSMikael Olsson {
167b139f1cfSMikael Olsson 	int err;
168b139f1cfSMikael Olsson 	struct ethosn_sub_allocator_t sub_allocators[] = {
169b139f1cfSMikael Olsson 		{.name = "command_stream", .name_len = 14U},
170b139f1cfSMikael Olsson 		{.name = "weight_data", .name_len = 11U},
171b139f1cfSMikael Olsson 		{.name = "buffer_data", .name_len = 11U},
172b139f1cfSMikael Olsson 		{.name = "intermediate_data", .name_len = 17U}
173b139f1cfSMikael Olsson 	};
174b139f1cfSMikael Olsson 
175b139f1cfSMikael Olsson 	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
176b139f1cfSMikael Olsson 					       ARRAY_SIZE(sub_allocators));
177b139f1cfSMikael Olsson 	if (err) {
178b139f1cfSMikael Olsson 		return err;
179b139f1cfSMikael Olsson 	}
180b139f1cfSMikael Olsson 
181b139f1cfSMikael Olsson 
182b139f1cfSMikael Olsson 	allocator->command_stream.stream_id = sub_allocators[0].stream_id;
183b139f1cfSMikael Olsson 	allocator->weight_data.stream_id = sub_allocators[1].stream_id;
184b139f1cfSMikael Olsson 	allocator->buffer_data.stream_id = sub_allocators[2].stream_id;
185b139f1cfSMikael Olsson 	allocator->intermediate_data.stream_id = sub_allocators[3].stream_id;
186b139f1cfSMikael Olsson 	return 0;
187b139f1cfSMikael Olsson }
188b139f1cfSMikael Olsson 
fdt_node_populate_core(const void * fdt,int device_node,int core_node,bool has_reserved_memory,uint32_t core_index,struct ethosn_core_t * core)189b139f1cfSMikael Olsson static int fdt_node_populate_core(const void *fdt,
190b139f1cfSMikael Olsson 				  int device_node,
191b139f1cfSMikael Olsson 				  int core_node,
192b139f1cfSMikael Olsson 				  bool has_reserved_memory,
193b139f1cfSMikael Olsson 				  uint32_t core_index,
194b139f1cfSMikael Olsson 				  struct ethosn_core_t *core)
195b139f1cfSMikael Olsson {
196b139f1cfSMikael Olsson 	int err;
197b139f1cfSMikael Olsson 	int sub_node;
198b139f1cfSMikael Olsson 	uintptr_t core_addr;
199b139f1cfSMikael Olsson 
200b139f1cfSMikael Olsson 	err = fdt_get_reg_props_by_index(fdt, device_node, core_index,
201b139f1cfSMikael Olsson 					 &core_addr, NULL);
202b139f1cfSMikael Olsson 	if (err < 0) {
203b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to read reg property for NPU core %u\n",
204b139f1cfSMikael Olsson 		      core_index);
205b139f1cfSMikael Olsson 		return err;
206b139f1cfSMikael Olsson 	}
207b139f1cfSMikael Olsson 
208b139f1cfSMikael Olsson 	err = -FDT_ERR_NOTFOUND;
209b139f1cfSMikael Olsson 	fdt_for_each_subnode(sub_node, fdt, core_node) {
210b139f1cfSMikael Olsson 
211b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(fdt, sub_node)) {
212b139f1cfSMikael Olsson 			continue;
213b139f1cfSMikael Olsson 		}
214b139f1cfSMikael Olsson 
215b139f1cfSMikael Olsson 		if (fdt_node_check_compatible(fdt,
216b139f1cfSMikael Olsson 					      sub_node,
217b139f1cfSMikael Olsson 					      "ethosn-main_allocator") != 0) {
218b139f1cfSMikael Olsson 			continue;
219b139f1cfSMikael Olsson 		}
220b139f1cfSMikael Olsson 
221b139f1cfSMikael Olsson 		if (has_reserved_memory) {
222b139f1cfSMikael Olsson 			ERROR("FCONF: Main allocator not supported when using reserved memory\n");
223b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
224b139f1cfSMikael Olsson 		}
225b139f1cfSMikael Olsson 
226b139f1cfSMikael Olsson 		if (err != -FDT_ERR_NOTFOUND) {
227b139f1cfSMikael Olsson 			ERROR("FCONF: NPU core 0x%lx has more than one main allocator\n",
228b139f1cfSMikael Olsson 			      core_addr);
229b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
230b139f1cfSMikael Olsson 		}
231b139f1cfSMikael Olsson 
232b139f1cfSMikael Olsson 		err = fdt_node_populate_main_allocator(fdt, sub_node, &core->main_allocator);
233b139f1cfSMikael Olsson 		if (err) {
234b139f1cfSMikael Olsson 			ERROR("FCONF: Failed to parse main allocator for NPU core 0x%lx\n",
235b139f1cfSMikael Olsson 			      core_addr);
236b139f1cfSMikael Olsson 			return err;
237b139f1cfSMikael Olsson 		}
238b139f1cfSMikael Olsson 	}
239b139f1cfSMikael Olsson 
240b139f1cfSMikael Olsson 	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
241b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to parse core sub nodes\n");
242b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
243b139f1cfSMikael Olsson 	}
244b139f1cfSMikael Olsson 
245b139f1cfSMikael Olsson 	if (!has_reserved_memory && err) {
246b139f1cfSMikael Olsson 		ERROR("FCONF: Main allocator not found for NPU core 0x%lx\n",
247b139f1cfSMikael Olsson 		      core_addr);
248b139f1cfSMikael Olsson 		return err;
249b139f1cfSMikael Olsson 	}
250b139f1cfSMikael Olsson 
251b139f1cfSMikael Olsson 	core->addr = core_addr;
252b139f1cfSMikael Olsson 
253b139f1cfSMikael Olsson 	return 0;
25476a21174SMikael Olsson }
25576a21174SMikael Olsson 
fconf_populate_ethosn_config(uintptr_t config)25676a21174SMikael Olsson int fconf_populate_ethosn_config(uintptr_t config)
25776a21174SMikael Olsson {
25876a21174SMikael Olsson 	int ethosn_node;
259b139f1cfSMikael Olsson 	uint32_t dev_count = 0U;
26076a21174SMikael Olsson 	const void *hw_conf_dtb = (const void *)config;
26176a21174SMikael Olsson 
262b139f1cfSMikael Olsson 	INFO("Probing Arm(R) Ethos(TM)-N NPU\n");
2631c65989eSLaurent Carlier 
2641c65989eSLaurent Carlier 	fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
265b139f1cfSMikael Olsson 		struct ethosn_device_t *dev = &ethosn_config.devices[dev_count];
266b139f1cfSMikael Olsson 		uint32_t dev_asset_alloc_count = 0U;
267b139f1cfSMikael Olsson 		uint32_t dev_core_count = 0U;
268*a19a0241SMikael Olsson 		uint64_t reserved_memory_addr = 0U;
269b139f1cfSMikael Olsson 		bool has_reserved_memory;
2701c65989eSLaurent Carlier 		int sub_node;
271*a19a0241SMikael Olsson 		int err;
27276a21174SMikael Olsson 
273b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(hw_conf_dtb, ethosn_node)) {
2741c65989eSLaurent Carlier 			continue;
27576a21174SMikael Olsson 		}
27676a21174SMikael Olsson 
277b139f1cfSMikael Olsson 		if (dev_count >= ETHOSN_DEV_NUM_MAX) {
278b139f1cfSMikael Olsson 			ERROR("FCONF: Reached max number of NPUs\n");
2791c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
2801c65989eSLaurent Carlier 		}
28176a21174SMikael Olsson 
282b139f1cfSMikael Olsson 		has_reserved_memory = fdt_node_has_reserved_memory(hw_conf_dtb, ethosn_node);
283*a19a0241SMikael Olsson 		if (has_reserved_memory) {
284*a19a0241SMikael Olsson 			err = fdt_node_read_reserved_memory_addr(hw_conf_dtb,
285*a19a0241SMikael Olsson 								 ethosn_node,
286*a19a0241SMikael Olsson 								 &reserved_memory_addr);
287*a19a0241SMikael Olsson 			if (err != 0) {
288*a19a0241SMikael Olsson 				return err;
289*a19a0241SMikael Olsson 			}
290*a19a0241SMikael Olsson 		}
291*a19a0241SMikael Olsson 
292b139f1cfSMikael Olsson 		fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
293b139f1cfSMikael Olsson 
294b139f1cfSMikael Olsson 			if (!fdt_node_is_enabled(hw_conf_dtb, sub_node)) {
295b139f1cfSMikael Olsson 				/* Ignore disabled sub node */
296b139f1cfSMikael Olsson 				continue;
297b139f1cfSMikael Olsson 			}
298b139f1cfSMikael Olsson 
2991c65989eSLaurent Carlier 			if (fdt_node_check_compatible(hw_conf_dtb,
3001c65989eSLaurent Carlier 						      sub_node,
301b139f1cfSMikael Olsson 						      "ethosn-core") == 0) {
302b139f1cfSMikael Olsson 
303b139f1cfSMikael Olsson 				if (dev_core_count >= ETHOSN_DEV_CORE_NUM_MAX) {
304b139f1cfSMikael Olsson 					ERROR("FCONF: Reached max number of NPU cores for NPU %u\n",
305b139f1cfSMikael Olsson 					      dev_count);
306b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
30776a21174SMikael Olsson 				}
30876a21174SMikael Olsson 
309b139f1cfSMikael Olsson 				err = fdt_node_populate_core(hw_conf_dtb,
3101c65989eSLaurent Carlier 							     ethosn_node,
311b139f1cfSMikael Olsson 							     sub_node,
312b139f1cfSMikael Olsson 							     has_reserved_memory,
313b139f1cfSMikael Olsson 							     dev_core_count,
314b139f1cfSMikael Olsson 							     &(dev->cores[dev_core_count]));
315b139f1cfSMikael Olsson 				if (err) {
31676a21174SMikael Olsson 					return err;
31776a21174SMikael Olsson 				}
318b139f1cfSMikael Olsson 				++dev_core_count;
319b139f1cfSMikael Olsson 			} else if (fdt_node_check_compatible(hw_conf_dtb,
320b139f1cfSMikael Olsson 							     sub_node,
321b139f1cfSMikael Olsson 							     "ethosn-asset_allocator") == 0) {
32276a21174SMikael Olsson 
323b139f1cfSMikael Olsson 				if (dev_asset_alloc_count >=
324b139f1cfSMikael Olsson 				    ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX) {
325b139f1cfSMikael Olsson 					ERROR("FCONF: Reached max number of asset allocators for NPU %u\n",
326b139f1cfSMikael Olsson 					      dev_count);
327b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
328b139f1cfSMikael Olsson 				}
329b139f1cfSMikael Olsson 
330b139f1cfSMikael Olsson 				if (has_reserved_memory) {
331b139f1cfSMikael Olsson 					ERROR("FCONF: Asset allocator not supported when using reserved memory\n");
332b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
333b139f1cfSMikael Olsson 				}
334b139f1cfSMikael Olsson 
335b139f1cfSMikael Olsson 				err = fdt_node_populate_asset_allocator(hw_conf_dtb,
336b139f1cfSMikael Olsson 									sub_node,
337b139f1cfSMikael Olsson 									&(dev->asset_allocators[dev_asset_alloc_count]));
338b139f1cfSMikael Olsson 				if (err) {
339b139f1cfSMikael Olsson 					ERROR("FCONF: Failed to parse asset allocator for NPU %u\n",
340b139f1cfSMikael Olsson 					      dev_count);
341b139f1cfSMikael Olsson 					return err;
342b139f1cfSMikael Olsson 				}
343b139f1cfSMikael Olsson 				++dev_asset_alloc_count;
344b139f1cfSMikael Olsson 			}
34576a21174SMikael Olsson 		}
34676a21174SMikael Olsson 
34776a21174SMikael Olsson 		if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
348b139f1cfSMikael Olsson 			ERROR("FCONF: Failed to parse sub nodes for NPU %u\n",
349b139f1cfSMikael Olsson 			      dev_count);
3501c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
35176a21174SMikael Olsson 		}
35276a21174SMikael Olsson 
353b139f1cfSMikael Olsson 		if (dev_core_count == 0U) {
354b139f1cfSMikael Olsson 			ERROR("FCONF: NPU %u must have at least one enabled core\n",
355b139f1cfSMikael Olsson 			      dev_count);
3561c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
3571c65989eSLaurent Carlier 		}
358b139f1cfSMikael Olsson 
359b139f1cfSMikael Olsson 		if (!has_reserved_memory && dev_asset_alloc_count == 0U) {
360b139f1cfSMikael Olsson 			ERROR("FCONF: NPU %u must have at least one asset allocator\n",
361b139f1cfSMikael Olsson 			      dev_count);
362b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
36376a21174SMikael Olsson 		}
36476a21174SMikael Olsson 
365b139f1cfSMikael Olsson 		dev->num_cores = dev_core_count;
366b139f1cfSMikael Olsson 		dev->num_allocators = dev_asset_alloc_count;
367b139f1cfSMikael Olsson 		dev->has_reserved_memory = has_reserved_memory;
368*a19a0241SMikael Olsson 		dev->reserved_memory_addr = reserved_memory_addr;
369b139f1cfSMikael Olsson 		++dev_count;
370b139f1cfSMikael Olsson 	}
371b139f1cfSMikael Olsson 
372b139f1cfSMikael Olsson 	if (dev_count == 0U) {
3731c65989eSLaurent Carlier 		ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
3741c65989eSLaurent Carlier 		return -FDT_ERR_BADSTRUCTURE;
3751c65989eSLaurent Carlier 	}
3761c65989eSLaurent Carlier 
377b139f1cfSMikael Olsson 	ethosn_config.num_devices = dev_count;
37876a21174SMikael Olsson 
37976a21174SMikael Olsson 	return 0;
38076a21174SMikael Olsson }
38176a21174SMikael Olsson 
38276a21174SMikael Olsson FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);
383