[FEATURE/OFW] add address reverse/translate for DMA/CPU's address
DMA and CPU address view is different, we need to convert them: +--------+ +--------+ +---------+ +--------+ | | | | | | | | | CPUs | | DEV0 | | IOMMU <----+ | DEV1 | | | | | | | | | | +----+---+ +----+---+ +----+----+ | +----+---+ | | | | | 0x200000 | 0x1000 | 0x1000 | | 0x8000 | | | | | | +-------------+-----------+ +----------+ | | +--------v----------------------------------------------------+ | | | Address BUS | | | +-------------------------------------------------------------+ Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
parent
117e6ed347
commit
2d026a316a
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue