xref: /rk3399_ARM-atf/plat/arm/common/fconf/fconf_ethosn_getter.c (revision b139f1cf975f9968eb8bd1182a173b976ecf06f9)
176a21174SMikael Olsson /*
2*b139f1cfSMikael Olsson  * Copyright (c) 2021-2022, 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 
15*b139f1cfSMikael Olsson struct ethosn_config_t ethosn_config = {0};
1676a21174SMikael Olsson 
17*b139f1cfSMikael Olsson struct ethosn_sub_allocator_t {
18*b139f1cfSMikael Olsson 	const char *name;
19*b139f1cfSMikael Olsson 	size_t name_len;
20*b139f1cfSMikael Olsson 	uint32_t stream_id;
21*b139f1cfSMikael Olsson };
22*b139f1cfSMikael Olsson 
23*b139f1cfSMikael Olsson static bool fdt_node_is_enabled(const void *fdt, int node)
2476a21174SMikael Olsson {
2576a21174SMikael Olsson 	int len;
2676a21174SMikael Olsson 	const char *node_status;
2776a21174SMikael Olsson 
2876a21174SMikael Olsson 	node_status = fdt_getprop(fdt, node, "status", &len);
2976a21174SMikael Olsson 	if (node_status == NULL ||
3076a21174SMikael Olsson 	    (len == 5 && /* Includes null character */
3176a21174SMikael Olsson 	     strncmp(node_status, "okay", 4U) == 0)) {
32*b139f1cfSMikael Olsson 		return true;
3376a21174SMikael Olsson 	}
3476a21174SMikael Olsson 
35*b139f1cfSMikael Olsson 	return false;
36*b139f1cfSMikael Olsson }
37*b139f1cfSMikael Olsson 
38*b139f1cfSMikael Olsson static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
39*b139f1cfSMikael Olsson {
40*b139f1cfSMikael Olsson 	return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
41*b139f1cfSMikael Olsson }
42*b139f1cfSMikael Olsson 
43*b139f1cfSMikael Olsson static int fdt_node_get_iommus_stream_id(const void *fdt, int node, uint32_t *stream_id)
44*b139f1cfSMikael Olsson {
45*b139f1cfSMikael Olsson 	int err;
46*b139f1cfSMikael Olsson 	uint32_t iommus_array[2] = {0U};
47*b139f1cfSMikael Olsson 
48*b139f1cfSMikael Olsson 	err = fdt_read_uint32_array(fdt, node, "iommus", 2U, iommus_array);
49*b139f1cfSMikael Olsson 	if (err) {
50*b139f1cfSMikael Olsson 		return err;
51*b139f1cfSMikael Olsson 	}
52*b139f1cfSMikael Olsson 
53*b139f1cfSMikael Olsson 	*stream_id = iommus_array[1];
54*b139f1cfSMikael Olsson 	return 0;
55*b139f1cfSMikael Olsson }
56*b139f1cfSMikael Olsson 
57*b139f1cfSMikael Olsson static int fdt_node_populate_sub_allocators(const void *fdt,
58*b139f1cfSMikael Olsson 					    int alloc_node,
59*b139f1cfSMikael Olsson 					    struct ethosn_sub_allocator_t *sub_allocators,
60*b139f1cfSMikael Olsson 					    size_t num_allocs)
61*b139f1cfSMikael Olsson {
62*b139f1cfSMikael Olsson 	int sub_node;
63*b139f1cfSMikael Olsson 	size_t i;
64*b139f1cfSMikael Olsson 	int err = -FDT_ERR_NOTFOUND;
65*b139f1cfSMikael Olsson 	uint32_t found_sub_allocators = 0U;
66*b139f1cfSMikael Olsson 
67*b139f1cfSMikael Olsson 	fdt_for_each_subnode(sub_node, fdt, alloc_node) {
68*b139f1cfSMikael Olsson 		const char *node_name;
69*b139f1cfSMikael Olsson 
70*b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(fdt, sub_node)) {
71*b139f1cfSMikael Olsson 			/* Ignore disabled node */
72*b139f1cfSMikael Olsson 			continue;
73*b139f1cfSMikael Olsson 		}
74*b139f1cfSMikael Olsson 
75*b139f1cfSMikael Olsson 		if (fdt_node_check_compatible(fdt, sub_node, "ethosn-memory") != 0) {
76*b139f1cfSMikael Olsson 			continue;
77*b139f1cfSMikael Olsson 		}
78*b139f1cfSMikael Olsson 
79*b139f1cfSMikael Olsson 		node_name = fdt_get_name(fdt, sub_node, NULL);
80*b139f1cfSMikael Olsson 		for (i = 0U; i < num_allocs; ++i) {
81*b139f1cfSMikael Olsson 			if (strncmp(node_name, sub_allocators[i].name,
82*b139f1cfSMikael Olsson 				    sub_allocators[i].name_len) != 0) {
83*b139f1cfSMikael Olsson 				continue;
84*b139f1cfSMikael Olsson 			}
85*b139f1cfSMikael Olsson 
86*b139f1cfSMikael Olsson 			err = fdt_node_get_iommus_stream_id(fdt, sub_node,
87*b139f1cfSMikael Olsson 							    &sub_allocators[i].stream_id);
88*b139f1cfSMikael Olsson 			if (err) {
89*b139f1cfSMikael Olsson 				ERROR("FCONF: Failed to get stream ID from sub-allocator %s\n",
90*b139f1cfSMikael Olsson 				      node_name);
91*b139f1cfSMikael Olsson 				return err;
92*b139f1cfSMikael Olsson 			}
93*b139f1cfSMikael Olsson 
94*b139f1cfSMikael Olsson 			++found_sub_allocators;
95*b139f1cfSMikael Olsson 			/* Nothing more to do for this node */
96*b139f1cfSMikael Olsson 			break;
97*b139f1cfSMikael Olsson 		}
98*b139f1cfSMikael Olsson 
99*b139f1cfSMikael Olsson 		/* Check that at least one of the sub-allocators matched */
100*b139f1cfSMikael Olsson 		if (i == num_allocs) {
101*b139f1cfSMikael Olsson 			ERROR("FCONF: Unknown sub-allocator %s\n", node_name);
102*b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
103*b139f1cfSMikael Olsson 		}
104*b139f1cfSMikael Olsson 	}
105*b139f1cfSMikael Olsson 
106*b139f1cfSMikael Olsson 	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
107*b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to parse sub-allocators\n");
108*b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
109*b139f1cfSMikael Olsson 	}
110*b139f1cfSMikael Olsson 
111*b139f1cfSMikael Olsson 	if (err == -FDT_ERR_NOTFOUND) {
112*b139f1cfSMikael Olsson 		ERROR("FCONF: No matching sub-allocator found\n");
113*b139f1cfSMikael Olsson 		return err;
114*b139f1cfSMikael Olsson 	}
115*b139f1cfSMikael Olsson 
116*b139f1cfSMikael Olsson 	if (found_sub_allocators != num_allocs) {
117*b139f1cfSMikael Olsson 		ERROR("FCONF: Not all sub-allocators were found\n");
118*b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
119*b139f1cfSMikael Olsson 	}
120*b139f1cfSMikael Olsson 
121*b139f1cfSMikael Olsson 	return 0;
122*b139f1cfSMikael Olsson }
123*b139f1cfSMikael Olsson 
124*b139f1cfSMikael Olsson static int fdt_node_populate_main_allocator(const void *fdt,
125*b139f1cfSMikael Olsson 					    int alloc_node,
126*b139f1cfSMikael Olsson 					    struct ethosn_main_allocator_t *allocator)
127*b139f1cfSMikael Olsson {
128*b139f1cfSMikael Olsson 	int err;
129*b139f1cfSMikael Olsson 	struct ethosn_sub_allocator_t sub_allocators[] = {
130*b139f1cfSMikael Olsson 		{.name = "firmware", .name_len = 8U},
131*b139f1cfSMikael Olsson 		{.name = "working_data", .name_len = 12U}
132*b139f1cfSMikael Olsson 	};
133*b139f1cfSMikael Olsson 
134*b139f1cfSMikael Olsson 	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
135*b139f1cfSMikael Olsson 					       ARRAY_SIZE(sub_allocators));
136*b139f1cfSMikael Olsson 	if (err) {
137*b139f1cfSMikael Olsson 		return err;
138*b139f1cfSMikael Olsson 	}
139*b139f1cfSMikael Olsson 
140*b139f1cfSMikael Olsson 	allocator->firmware.stream_id = sub_allocators[0].stream_id;
141*b139f1cfSMikael Olsson 	allocator->working_data.stream_id = sub_allocators[1].stream_id;
142*b139f1cfSMikael Olsson 
143*b139f1cfSMikael Olsson 	return 0;
144*b139f1cfSMikael Olsson }
145*b139f1cfSMikael Olsson 
146*b139f1cfSMikael Olsson static int fdt_node_populate_asset_allocator(const void *fdt,
147*b139f1cfSMikael Olsson 					    int alloc_node,
148*b139f1cfSMikael Olsson 					    struct ethosn_asset_allocator_t *allocator)
149*b139f1cfSMikael Olsson {
150*b139f1cfSMikael Olsson 	int err;
151*b139f1cfSMikael Olsson 	struct ethosn_sub_allocator_t sub_allocators[] = {
152*b139f1cfSMikael Olsson 		{.name = "command_stream", .name_len = 14U},
153*b139f1cfSMikael Olsson 		{.name = "weight_data", .name_len = 11U},
154*b139f1cfSMikael Olsson 		{.name = "buffer_data", .name_len = 11U},
155*b139f1cfSMikael Olsson 		{.name = "intermediate_data", .name_len = 17U}
156*b139f1cfSMikael Olsson 	};
157*b139f1cfSMikael Olsson 
158*b139f1cfSMikael Olsson 	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
159*b139f1cfSMikael Olsson 					       ARRAY_SIZE(sub_allocators));
160*b139f1cfSMikael Olsson 	if (err) {
161*b139f1cfSMikael Olsson 		return err;
162*b139f1cfSMikael Olsson 	}
163*b139f1cfSMikael Olsson 
164*b139f1cfSMikael Olsson 
165*b139f1cfSMikael Olsson 	allocator->command_stream.stream_id = sub_allocators[0].stream_id;
166*b139f1cfSMikael Olsson 	allocator->weight_data.stream_id = sub_allocators[1].stream_id;
167*b139f1cfSMikael Olsson 	allocator->buffer_data.stream_id = sub_allocators[2].stream_id;
168*b139f1cfSMikael Olsson 	allocator->intermediate_data.stream_id = sub_allocators[3].stream_id;
169*b139f1cfSMikael Olsson 	return 0;
170*b139f1cfSMikael Olsson }
171*b139f1cfSMikael Olsson 
172*b139f1cfSMikael Olsson static int fdt_node_populate_core(const void *fdt,
173*b139f1cfSMikael Olsson 				  int device_node,
174*b139f1cfSMikael Olsson 				  int core_node,
175*b139f1cfSMikael Olsson 				  bool has_reserved_memory,
176*b139f1cfSMikael Olsson 				  uint32_t core_index,
177*b139f1cfSMikael Olsson 				  struct ethosn_core_t *core)
178*b139f1cfSMikael Olsson {
179*b139f1cfSMikael Olsson 	int err;
180*b139f1cfSMikael Olsson 	int sub_node;
181*b139f1cfSMikael Olsson 	uintptr_t core_addr;
182*b139f1cfSMikael Olsson 
183*b139f1cfSMikael Olsson 	err = fdt_get_reg_props_by_index(fdt, device_node, core_index,
184*b139f1cfSMikael Olsson 					 &core_addr, NULL);
185*b139f1cfSMikael Olsson 	if (err < 0) {
186*b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to read reg property for NPU core %u\n",
187*b139f1cfSMikael Olsson 		      core_index);
188*b139f1cfSMikael Olsson 		return err;
189*b139f1cfSMikael Olsson 	}
190*b139f1cfSMikael Olsson 
191*b139f1cfSMikael Olsson 	err = -FDT_ERR_NOTFOUND;
192*b139f1cfSMikael Olsson 	fdt_for_each_subnode(sub_node, fdt, core_node) {
193*b139f1cfSMikael Olsson 
194*b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(fdt, sub_node)) {
195*b139f1cfSMikael Olsson 			continue;
196*b139f1cfSMikael Olsson 		}
197*b139f1cfSMikael Olsson 
198*b139f1cfSMikael Olsson 		if (fdt_node_check_compatible(fdt,
199*b139f1cfSMikael Olsson 					      sub_node,
200*b139f1cfSMikael Olsson 					      "ethosn-main_allocator") != 0) {
201*b139f1cfSMikael Olsson 			continue;
202*b139f1cfSMikael Olsson 		}
203*b139f1cfSMikael Olsson 
204*b139f1cfSMikael Olsson 		if (has_reserved_memory) {
205*b139f1cfSMikael Olsson 			ERROR("FCONF: Main allocator not supported when using reserved memory\n");
206*b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
207*b139f1cfSMikael Olsson 		}
208*b139f1cfSMikael Olsson 
209*b139f1cfSMikael Olsson 		if (err != -FDT_ERR_NOTFOUND) {
210*b139f1cfSMikael Olsson 			ERROR("FCONF: NPU core 0x%lx has more than one main allocator\n",
211*b139f1cfSMikael Olsson 			      core_addr);
212*b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
213*b139f1cfSMikael Olsson 		}
214*b139f1cfSMikael Olsson 
215*b139f1cfSMikael Olsson 		err = fdt_node_populate_main_allocator(fdt, sub_node, &core->main_allocator);
216*b139f1cfSMikael Olsson 		if (err) {
217*b139f1cfSMikael Olsson 			ERROR("FCONF: Failed to parse main allocator for NPU core 0x%lx\n",
218*b139f1cfSMikael Olsson 			      core_addr);
219*b139f1cfSMikael Olsson 			return err;
220*b139f1cfSMikael Olsson 		}
221*b139f1cfSMikael Olsson 	}
222*b139f1cfSMikael Olsson 
223*b139f1cfSMikael Olsson 	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
224*b139f1cfSMikael Olsson 		ERROR("FCONF: Failed to parse core sub nodes\n");
225*b139f1cfSMikael Olsson 		return -FDT_ERR_BADSTRUCTURE;
226*b139f1cfSMikael Olsson 	}
227*b139f1cfSMikael Olsson 
228*b139f1cfSMikael Olsson 	if (!has_reserved_memory && err) {
229*b139f1cfSMikael Olsson 		ERROR("FCONF: Main allocator not found for NPU core 0x%lx\n",
230*b139f1cfSMikael Olsson 		      core_addr);
231*b139f1cfSMikael Olsson 		return err;
232*b139f1cfSMikael Olsson 	}
233*b139f1cfSMikael Olsson 
234*b139f1cfSMikael Olsson 	core->addr = core_addr;
235*b139f1cfSMikael Olsson 
236*b139f1cfSMikael Olsson 	return 0;
23776a21174SMikael Olsson }
23876a21174SMikael Olsson 
23976a21174SMikael Olsson int fconf_populate_ethosn_config(uintptr_t config)
24076a21174SMikael Olsson {
24176a21174SMikael Olsson 	int ethosn_node;
242*b139f1cfSMikael Olsson 	uint32_t dev_count = 0U;
24376a21174SMikael Olsson 	const void *hw_conf_dtb = (const void *)config;
24476a21174SMikael Olsson 
245*b139f1cfSMikael Olsson 	INFO("Probing Arm(R) Ethos(TM)-N NPU\n");
2461c65989eSLaurent Carlier 
2471c65989eSLaurent Carlier 	fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
248*b139f1cfSMikael Olsson 		struct ethosn_device_t *dev = &ethosn_config.devices[dev_count];
249*b139f1cfSMikael Olsson 		uint32_t dev_asset_alloc_count = 0U;
250*b139f1cfSMikael Olsson 		uint32_t dev_core_count = 0U;
251*b139f1cfSMikael Olsson 		bool has_reserved_memory;
2521c65989eSLaurent Carlier 		int sub_node;
25376a21174SMikael Olsson 
254*b139f1cfSMikael Olsson 		if (!fdt_node_is_enabled(hw_conf_dtb, ethosn_node)) {
2551c65989eSLaurent Carlier 			continue;
25676a21174SMikael Olsson 		}
25776a21174SMikael Olsson 
258*b139f1cfSMikael Olsson 		if (dev_count >= ETHOSN_DEV_NUM_MAX) {
259*b139f1cfSMikael Olsson 			ERROR("FCONF: Reached max number of NPUs\n");
2601c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
2611c65989eSLaurent Carlier 		}
26276a21174SMikael Olsson 
263*b139f1cfSMikael Olsson 		has_reserved_memory = fdt_node_has_reserved_memory(hw_conf_dtb, ethosn_node);
264*b139f1cfSMikael Olsson 		fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
265*b139f1cfSMikael Olsson 			int err;
266*b139f1cfSMikael Olsson 
267*b139f1cfSMikael Olsson 			if (!fdt_node_is_enabled(hw_conf_dtb, sub_node)) {
268*b139f1cfSMikael Olsson 				/* Ignore disabled sub node */
269*b139f1cfSMikael Olsson 				continue;
270*b139f1cfSMikael Olsson 			}
271*b139f1cfSMikael Olsson 
2721c65989eSLaurent Carlier 			if (fdt_node_check_compatible(hw_conf_dtb,
2731c65989eSLaurent Carlier 						      sub_node,
274*b139f1cfSMikael Olsson 						      "ethosn-core") == 0) {
275*b139f1cfSMikael Olsson 
276*b139f1cfSMikael Olsson 				if (dev_core_count >= ETHOSN_DEV_CORE_NUM_MAX) {
277*b139f1cfSMikael Olsson 					ERROR("FCONF: Reached max number of NPU cores for NPU %u\n",
278*b139f1cfSMikael Olsson 					      dev_count);
279*b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
28076a21174SMikael Olsson 				}
28176a21174SMikael Olsson 
282*b139f1cfSMikael Olsson 				err = fdt_node_populate_core(hw_conf_dtb,
2831c65989eSLaurent Carlier 							     ethosn_node,
284*b139f1cfSMikael Olsson 							     sub_node,
285*b139f1cfSMikael Olsson 							     has_reserved_memory,
286*b139f1cfSMikael Olsson 							     dev_core_count,
287*b139f1cfSMikael Olsson 							     &(dev->cores[dev_core_count]));
288*b139f1cfSMikael Olsson 				if (err) {
28976a21174SMikael Olsson 					return err;
29076a21174SMikael Olsson 				}
291*b139f1cfSMikael Olsson 				++dev_core_count;
292*b139f1cfSMikael Olsson 			} else if (fdt_node_check_compatible(hw_conf_dtb,
293*b139f1cfSMikael Olsson 							     sub_node,
294*b139f1cfSMikael Olsson 							     "ethosn-asset_allocator") == 0) {
29576a21174SMikael Olsson 
296*b139f1cfSMikael Olsson 				if (dev_asset_alloc_count >=
297*b139f1cfSMikael Olsson 				    ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX) {
298*b139f1cfSMikael Olsson 					ERROR("FCONF: Reached max number of asset allocators for NPU %u\n",
299*b139f1cfSMikael Olsson 					      dev_count);
300*b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
301*b139f1cfSMikael Olsson 				}
302*b139f1cfSMikael Olsson 
303*b139f1cfSMikael Olsson 				if (has_reserved_memory) {
304*b139f1cfSMikael Olsson 					ERROR("FCONF: Asset allocator not supported when using reserved memory\n");
305*b139f1cfSMikael Olsson 					return -FDT_ERR_BADSTRUCTURE;
306*b139f1cfSMikael Olsson 				}
307*b139f1cfSMikael Olsson 
308*b139f1cfSMikael Olsson 				err = fdt_node_populate_asset_allocator(hw_conf_dtb,
309*b139f1cfSMikael Olsson 									sub_node,
310*b139f1cfSMikael Olsson 									&(dev->asset_allocators[dev_asset_alloc_count]));
311*b139f1cfSMikael Olsson 				if (err) {
312*b139f1cfSMikael Olsson 					ERROR("FCONF: Failed to parse asset allocator for NPU %u\n",
313*b139f1cfSMikael Olsson 					      dev_count);
314*b139f1cfSMikael Olsson 					return err;
315*b139f1cfSMikael Olsson 				}
316*b139f1cfSMikael Olsson 				++dev_asset_alloc_count;
317*b139f1cfSMikael Olsson 			}
31876a21174SMikael Olsson 		}
31976a21174SMikael Olsson 
32076a21174SMikael Olsson 		if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
321*b139f1cfSMikael Olsson 			ERROR("FCONF: Failed to parse sub nodes for NPU %u\n",
322*b139f1cfSMikael Olsson 			      dev_count);
3231c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
32476a21174SMikael Olsson 		}
32576a21174SMikael Olsson 
326*b139f1cfSMikael Olsson 		if (dev_core_count == 0U) {
327*b139f1cfSMikael Olsson 			ERROR("FCONF: NPU %u must have at least one enabled core\n",
328*b139f1cfSMikael Olsson 			      dev_count);
3291c65989eSLaurent Carlier 			return -FDT_ERR_BADSTRUCTURE;
3301c65989eSLaurent Carlier 		}
331*b139f1cfSMikael Olsson 
332*b139f1cfSMikael Olsson 		if (!has_reserved_memory && dev_asset_alloc_count == 0U) {
333*b139f1cfSMikael Olsson 			ERROR("FCONF: NPU %u must have at least one asset allocator\n",
334*b139f1cfSMikael Olsson 			      dev_count);
335*b139f1cfSMikael Olsson 			return -FDT_ERR_BADSTRUCTURE;
33676a21174SMikael Olsson 		}
33776a21174SMikael Olsson 
338*b139f1cfSMikael Olsson 		dev->num_cores = dev_core_count;
339*b139f1cfSMikael Olsson 		dev->num_allocators = dev_asset_alloc_count;
340*b139f1cfSMikael Olsson 		dev->has_reserved_memory = has_reserved_memory;
341*b139f1cfSMikael Olsson 		++dev_count;
342*b139f1cfSMikael Olsson 	}
343*b139f1cfSMikael Olsson 
344*b139f1cfSMikael Olsson 	if (dev_count == 0U) {
3451c65989eSLaurent Carlier 		ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
3461c65989eSLaurent Carlier 		return -FDT_ERR_BADSTRUCTURE;
3471c65989eSLaurent Carlier 	}
3481c65989eSLaurent Carlier 
349*b139f1cfSMikael Olsson 	ethosn_config.num_devices = dev_count;
35076a21174SMikael Olsson 
35176a21174SMikael Olsson 	return 0;
35276a21174SMikael Olsson }
35376a21174SMikael Olsson 
35476a21174SMikael Olsson FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);
355