diff --git a/components/drivers/ofw/Kconfig b/components/drivers/ofw/Kconfig index bebb5b43843..3f6735e6045 100755 --- a/components/drivers/ofw/Kconfig +++ b/components/drivers/ofw/Kconfig @@ -20,3 +20,9 @@ config RT_FDT_EARLYCON_MSG_SIZE int "Earlycon message buffer size (KB)" depends on RT_USING_OFW default 128 + +config RT_USING_OFW_BUS_RANGES_NUMBER + int "Max bus ranges number" + depends on RT_USING_OFW + default 8 if ARCH_CPU_64BIT + default 4 diff --git a/components/drivers/ofw/io.c b/components/drivers/ofw/io.c index 5f4892c1485..d9065c07f49 100755 --- a/components/drivers/ofw/io.c +++ b/components/drivers/ofw/io.c @@ -13,6 +13,7 @@ #include #include #include +#include #define DBG_TAG "rtdm.ofw" #define DBG_LVL DBG_INFO @@ -20,6 +21,9 @@ #include "ofw_internal.h" +static volatile rt_atomic_t _bus_ranges_idx = 0; +static struct bus_ranges *_bus_ranges[RT_USING_OFW_BUS_RANGES_NUMBER] = {}; + static int ofw_bus_addr_cells(struct rt_ofw_node *np) { int res = OFW_ROOT_NODE_ADDR_CELLS_DEFAULT; @@ -245,6 +249,7 @@ int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_re static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_prop *prop) { + int id; const fdt32_t *cell; struct bus_ranges *ranges = RT_NULL; int child_address_cells, child_size_cells, parent_address_cells, groups; @@ -322,7 +327,12 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p *child_size++ = rt_fdt_next_cell(&cell, child_size_cells); } - rt_ofw_data(np) = ranges; + ranges->np = np; + + id = (int)rt_atomic_add(&_bus_ranges_idx, 1); + RT_ASSERT(id < RT_ARRAY_SIZE(_bus_ranges)); + + _bus_ranges[id] = ranges; } while (0); return ranges; @@ -341,7 +351,7 @@ rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_t { rt_ssize_t len; struct rt_ofw_prop *prop; - struct bus_ranges *ranges; + struct bus_ranges *ranges = RT_NULL; prop = rt_ofw_get_prop(np, range_type, &len); @@ -350,7 +360,19 @@ rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_t continue; } - ranges = rt_ofw_data(np); + for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) + { + if (!_bus_ranges[i]) + { + break; + } + + if (_bus_ranges[i]->np == np) + { + ranges = _bus_ranges[i]; + break; + } + } if (!ranges) { diff --git a/components/drivers/ofw/ofw_internal.h b/components/drivers/ofw/ofw_internal.h index f536b382cab..0a8c7c8b234 100755 --- a/components/drivers/ofw/ofw_internal.h +++ b/components/drivers/ofw/ofw_internal.h @@ -50,6 +50,7 @@ struct alias_info struct bus_ranges { rt_size_t nr; + struct rt_ofw_node *np; rt_uint64_t *child_addr; rt_uint64_t *parent_addr;