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 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 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 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 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 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 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 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 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 = ðosn_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