[OFW] Support ID map interface (#8994)
The OFW map id is always use in DMA, PCI, IOMMU bus system to find the device identity. this is a access interface. Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
parent
8c6c9205b0
commit
f035188094
|
@ -205,6 +205,9 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id);
|
|||
int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag);
|
||||
int rt_ofw_get_alias_last_id(const char *tag);
|
||||
|
||||
rt_err_t rt_ofw_map_id(struct rt_ofw_node *np, rt_uint32_t id, const char *map_name, const char *map_mask_name,
|
||||
struct rt_ofw_node **ref_np, rt_uint32_t *out_id);
|
||||
|
||||
struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name);
|
||||
rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value);
|
||||
|
||||
|
|
|
@ -1224,6 +1224,138 @@ int rt_ofw_get_alias_last_id(const char *tag)
|
|||
return id;
|
||||
}
|
||||
|
||||
static rt_err_t ofw_map_id(struct rt_ofw_node *np, rt_uint32_t id, const char *map_name, const char *map_mask_name,
|
||||
const fdt32_t *map, rt_ssize_t map_len, struct rt_ofw_node **ref_np, rt_uint32_t *out_id)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
rt_uint32_t masked_id, map_mask;
|
||||
|
||||
/* Select all bits default */
|
||||
map_mask = 0xffffffff;
|
||||
|
||||
if (map_mask_name)
|
||||
{
|
||||
rt_ofw_prop_read_u32(np, map_mask_name, &map_mask);
|
||||
}
|
||||
|
||||
masked_id = map_mask & id;
|
||||
|
||||
for (; map_len > 0; map_len -= 4 * sizeof(*map), map += 4)
|
||||
{
|
||||
struct rt_ofw_node *phandle_node;
|
||||
rt_uint32_t id_base = fdt32_to_cpu(*(map + 0));
|
||||
rt_uint32_t phandle = fdt32_to_cpu(*(map + 1));
|
||||
rt_uint32_t out_base = fdt32_to_cpu(*(map + 2));
|
||||
rt_uint32_t id_len = fdt32_to_cpu(*(map + 3));
|
||||
|
||||
if (id_base & ~map_mask)
|
||||
{
|
||||
LOG_E("%s: Invalid %s translation - %s(0x%x) for id-base = 0x%x",
|
||||
np->full_name, map_name, map_mask_name, map_mask, id_base);
|
||||
|
||||
err = -RT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (masked_id < id_base || masked_id >= id_base + id_len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
phandle_node = rt_ofw_find_node_by_phandle((rt_phandle)phandle);
|
||||
|
||||
if (!phandle_node)
|
||||
{
|
||||
err = -RT_EEMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ref_np)
|
||||
{
|
||||
if (*ref_np)
|
||||
{
|
||||
rt_ofw_node_put(phandle_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ref_np = phandle_node;
|
||||
}
|
||||
|
||||
if (*ref_np != phandle_node)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_id)
|
||||
{
|
||||
*out_id = masked_id - id_base + out_base;
|
||||
}
|
||||
|
||||
LOG_D("%s: Get %s translation - %s(0x%x) for id-base = 0x%x, out-base = 0x%x, length = %d, id: 0x%x -> 0x%x",
|
||||
np->full_name, map_name, map_mask_name, map_mask,
|
||||
id_base, out_base, id_len, id, masked_id - id_base + out_base);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (map_len <= 0)
|
||||
{
|
||||
LOG_I("%s: No %s translation for id(0x%x) on %s", np->full_name, map_name,
|
||||
id, ref_np && *ref_np ? *ref_np : RT_NULL);
|
||||
|
||||
/* Bypasses translation */
|
||||
if (out_id)
|
||||
{
|
||||
*out_id = id;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t rt_ofw_map_id(struct rt_ofw_node *np, rt_uint32_t id, const char *map_name, const char *map_mask_name,
|
||||
struct rt_ofw_node **ref_np, rt_uint32_t *out_id)
|
||||
{
|
||||
rt_err_t err;
|
||||
|
||||
if (np && map_name && (ref_np || out_id))
|
||||
{
|
||||
rt_ssize_t map_len;
|
||||
const fdt32_t *map = rt_ofw_prop_read_raw(np, map_name, &map_len);
|
||||
|
||||
if (!map)
|
||||
{
|
||||
if (ref_np)
|
||||
{
|
||||
err = -RT_EEMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out_id = id;
|
||||
}
|
||||
|
||||
err = RT_EOK;
|
||||
}
|
||||
else if (!map_len || map_len % (4 * sizeof(*map)))
|
||||
{
|
||||
LOG_E("%s: Invalid %s length = %u", np->full_name, map_name, map_len);
|
||||
|
||||
err = -RT_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = ofw_map_id(np, id, map_name, map_mask_name, map, map_len, ref_np, out_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name)
|
||||
{
|
||||
rt_phandle phandle;
|
||||
|
|
Loading…
Reference in New Issue