Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIXUP/FEATURE/OFW] OFW API #9411

Merged
merged 7 commits into from
Sep 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions components/drivers/include/drivers/ofw.h
Original file line number Diff line number Diff line change
@@ -376,9 +376,9 @@ rt_inline rt_bool_t rt_ofw_node_is_type(const struct rt_ofw_node *np, const char
for (np = rt_ofw_find_node_by_type(RT_NULL, type); np; \
np = rt_ofw_find_node_by_type(np, type))

#define rt_ofw_foreach_node_by_compatible(np, type, compatible) \
for (np = rt_ofw_find_node_by_compatible(RT_NULL, type, compatible); np; \
np = rt_ofw_find_node_by_compatible(np, type, compatible))
#define rt_ofw_foreach_node_by_compatible(np, compatible) \
for (np = rt_ofw_find_node_by_compatible(RT_NULL, compatible); np; \
np = rt_ofw_find_node_by_compatible(np, compatible))

#define rt_ofw_foreach_node_by_ids_r(np, id, ids) \
for (np = rt_ofw_find_node_by_ids_r(RT_NULL, ids, id); \
1 change: 1 addition & 0 deletions components/drivers/include/drivers/ofw_fdt.h
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@ rt_err_t rt_fdt_boot_dump(void);
void rt_fdt_earlycon_output(const char *str);
void rt_fdt_earlycon_kick(int why);
rt_err_t rt_fdt_scan_chosen_stdout(void);
rt_err_t rt_fdt_bootargs_select(const char *key, int index, const char **out_result);
rt_err_t rt_fdt_unflatten(void);

struct rt_ofw_node *rt_fdt_unflatten_single(void *fdt);
21 changes: 21 additions & 0 deletions components/drivers/include/drivers/ofw_io.h
Original file line number Diff line number Diff line change
@@ -26,6 +26,27 @@ rt_err_t rt_ofw_get_address_by_name(struct rt_ofw_node *np, const char *name,
int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_regs);

rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address);
rt_uint64_t rt_ofw_reverse_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address);

rt_inline rt_uint64_t rt_ofw_translate_dma2cpu(struct rt_ofw_node *np, rt_uint64_t address)
{
rt_uint64_t bus_addr, cpu_addr;

bus_addr = rt_ofw_reverse_address(np, "dma-ranges", address);
cpu_addr = rt_ofw_translate_address(np, "ranges", bus_addr);

return cpu_addr != ~0ULL ? cpu_addr : address;
}

rt_inline rt_uint64_t rt_ofw_translate_cpu2dma(struct rt_ofw_node *np, rt_uint64_t address)
{
rt_uint64_t bus_addr, dma_addr;

bus_addr = rt_ofw_reverse_address(np, "ranges", address);
dma_addr = rt_ofw_translate_address(np, "dma-ranges", bus_addr);

return dma_addr != ~0ULL ? dma_addr : address;
}

void *rt_ofw_iomap(struct rt_ofw_node *np, int index);
void *rt_ofw_iomap_by_name(struct rt_ofw_node *np, const char *name);
2 changes: 1 addition & 1 deletion components/drivers/ofw/base.c
Original file line number Diff line number Diff line change
@@ -1412,7 +1412,7 @@ struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *
}
}

return np;
return rt_ofw_node_get(np);
}

rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value)
49 changes: 49 additions & 0 deletions components/drivers/ofw/fdt.c
Original file line number Diff line number Diff line change
@@ -793,6 +793,55 @@ rt_err_t rt_fdt_scan_chosen_stdout(void)
return err;
}

rt_err_t rt_fdt_bootargs_select(const char *key, int index, const char **out_result)
{
rt_err_t err;

if (key && index >= 0 && out_result)
{
int offset = fdt_path_offset(_fdt, "/chosen");

if (offset >= 0)
{
int len, key_len = rt_strlen(key);
const char *bootargs = fdt_getprop(_fdt, offset, "bootargs", &len), *end;

end = bootargs + len;
err = -RT_EEMPTY;

for (int i = 0; bootargs < end; ++i)
{
bootargs = rt_strstr(bootargs, key);

if (!bootargs)
{
break;
}

bootargs += key_len;

if (i == index)
{
*out_result = bootargs;

err = -RT_EOK;
break;
}
}
}
else
{
err = -RT_ERROR;
}
}
else
{
err = -RT_EINVAL;
}

return err;
}

static void system_node_init_flag(struct rt_ofw_node *np)
{
if (np)
69 changes: 69 additions & 0 deletions components/drivers/ofw/io.c
Original file line number Diff line number Diff line change
@@ -407,6 +407,75 @@ rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_t
return cpu_addr;
}

rt_uint64_t rt_ofw_reverse_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address)
{
rt_uint64_t bus_addr = address;

if (!range_type)
{
range_type = "ranges";
}

rt_ofw_foreach_parent_node(np)
{
rt_ssize_t len;
struct rt_ofw_prop *prop;
struct bus_ranges *ranges = RT_NULL;

prop = rt_ofw_get_prop(np, range_type, &len);

if (!prop || !len)
{
continue;
}

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)
{
ranges = ofw_bus_ranges(np, prop);
}

if (ranges)
{
for (int i = 0; i < ranges->nr; ++i)
{
rt_uint64_t parent_addr = ranges->parent_addr[i];
rt_uint64_t child_size = ranges->child_size[i];

if (address >= parent_addr && address < parent_addr + child_size)
{
bus_addr = ranges->child_addr[i] + (address - parent_addr);

break;
}
}
}
else
{
bus_addr = ~0ULL;
}

rt_ofw_node_put(np);

break;
}

return bus_addr;
}

#ifdef ARCH_CPU_64BIT
#define ofw_address_cpu_cast(np, address) (void *)(address)
#else
28 changes: 20 additions & 8 deletions components/drivers/ofw/ofw.c
Original file line number Diff line number Diff line change
@@ -103,14 +103,14 @@ static struct rt_object *ofw_parse_object(struct rt_ofw_node *np, const char *ce
{
item = &ofw_obj_cmp_list[i];

if (!rt_strcmp(item->cells_name, cells_name))
{
ret_obj = obj;
break;
}

if (!rt_strncmp(item->obj_name, obj->name, RT_NAME_MAX))
{
if (!rt_strcmp(item->cells_name, cells_name))
{
ret_obj = obj;
break;
}

obj = (struct rt_object *)((rt_ubase_t)obj + item->obj_size);
break;
}
@@ -134,7 +134,7 @@ struct rt_object *rt_ofw_parse_object(struct rt_ofw_node *np, const char *obj_na
if (np && (test_obj = rt_ofw_data(np)) && cells_name)
{
/* The composite object is rare, so we try to find this object as much as possible at once. */
if (obj_name && rt_strcmp(test_obj->name, obj_name))
if (obj_name && !rt_strcmp(test_obj->name, obj_name))
{
obj = test_obj;
}
@@ -386,6 +386,11 @@ const char *rt_ofw_bootargs_select(const char *key, int index)
{
*(char *)ch++ = '\0';
}
if (*ch == '\0')
{
/* space in the end */
--bootargs_nr;
}
--ch;
}

@@ -636,7 +641,14 @@ void rt_ofw_node_dump_dts(struct rt_ofw_node *np, rt_bool_t sibling_too)
struct fdt_info *header = (struct fdt_info *)np->name;
struct fdt_reserve_entry *rsvmap = header->rsvmap;

rt_kprintf("/dts-v%x/;\n\n", fdt_version(header->fdt));
/*
* Shall be present to identify the file as a version 1 DTS
* (dts files without this tag will be treated by dtc
* as being in the obsolete version 0, which uses
* a different format for integers in addition to
* other small but incompatible changes).
*/
rt_kprintf("/dts-v1/;\n\n");

for (int i = header->rsvmap_nr - 1; i >= 0; --i)
{