diff options
author | Oliver O'Halloran <oohall@gmail.com> | 2017-03-07 15:16:20 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-03-07 15:40:32 +1100 |
commit | fb27dd8ac6c4c80511e2ca674a6886cd504e1a2c (patch) | |
tree | 9d67ee536d6facbbb886f0c3ddca795ebca2b587 /core/test | |
parent | 0f28e38bbeaa11bda20b81f2247c82682d93d787 (diff) | |
download | skiboot-fb27dd8ac6c4c80511e2ca674a6886cd504e1a2c.zip skiboot-fb27dd8ac6c4c80511e2ca674a6886cd504e1a2c.tar.gz skiboot-fb27dd8ac6c4c80511e2ca674a6886cd504e1a2c.tar.bz2 |
device: implement dt_translate_address() properly
Currently this is implemented by calling dt_get_address() which only
works when a device is a child of the root node. This patch implements
the functionality to work with nested nodes when all parent nodes have
an appropriate "ranges" property.
This implementation only works for up to 64 bit addresses. Properly
supporting larger addressing schemes is a fair amount of (probably
pointless) work, so I'm leaving supporting that until we have an
actual a need for it.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Tested-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/test')
-rw-r--r-- | core/test/run-device.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/core/test/run-device.c b/core/test/run-device.c index 3da4a2f..e91e5a5 100644 --- a/core/test/run-device.c +++ b/core/test/run-device.c @@ -90,7 +90,7 @@ static bool is_sorted(const struct dt_node *root) int main(void) { - struct dt_node *root, *c1, *c2, *gc1, *gc2, *gc3, *ggc1; + struct dt_node *root, *c1, *c2, *gc1, *gc2, *gc3, *ggc1, *ggc2; struct dt_node *addrs, *addr1, *addr2; struct dt_node *i; const struct dt_property *p; @@ -366,6 +366,51 @@ int main(void) dt_free(root); + /* check dt_translate_address */ + + /* NB: the root bus has two address cells */ + root = dt_new_root(""); + + c1 = dt_new_addr(root, "some-32bit-bus", 0x80000000); + dt_add_property_cells(c1, "#address-cells", 1); + dt_add_property_cells(c1, "#size-cells", 1); + dt_add_property_cells(c1, "ranges", 0x0, 0x8, 0x0, 0x1000); + + gc1 = dt_new_addr(c1, "test", 0x0500); + dt_add_property_cells(gc1, "reg", 0x0500, 0x10); + + assert(dt_translate_address(gc1, 0, NULL) == 0x800000500ul); + + /* try three level translation */ + + gc2 = dt_new_addr(c1, "another-32bit-bus", 0x40000000); + dt_add_property_cells(gc2, "#address-cells", 1); + dt_add_property_cells(gc2, "#size-cells", 1); + dt_add_property_cells(gc2, "ranges", 0x0, 0x600, 0x100, + 0x100, 0x800, 0x100); + + ggc1 = dt_new_addr(gc2, "test", 0x50); + dt_add_property_cells(ggc1, "reg", 0x50, 0x10); + assert(dt_translate_address(ggc1, 0, NULL) == 0x800000650ul); + + /* test multiple ranges work */ + ggc2 = dt_new_addr(gc2, "test", 0x150); + dt_add_property_cells(ggc2, "reg", 0x150, 0x10); + assert(dt_translate_address(ggc2, 0, NULL) == 0x800000850ul); + + /* try 64bit -> 64bit */ + + c2 = dt_new_addr(root, "some-64bit-bus", 0xe00000000); + dt_add_property_cells(c2, "#address-cells", 2); + dt_add_property_cells(c2, "#size-cells", 2); + dt_add_property_cells(c2, "ranges", 0x0, 0x0, 0xe, 0x0, 0x2, 0x0); + + gc2 = dt_new_addr(c2, "test", 0x100000000ul); + dt_add_property_u64s(gc2, "reg", 0x100000000ul, 0x10ul); + assert(dt_translate_address(gc2, 0, NULL) == 0xf00000000ul); + + dt_free(root); + return 0; } |