aboutsummaryrefslogtreecommitdiff
path: root/core/test
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2017-03-07 15:16:20 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-03-07 15:40:32 +1100
commitfb27dd8ac6c4c80511e2ca674a6886cd504e1a2c (patch)
tree9d67ee536d6facbbb886f0c3ddca795ebca2b587 /core/test
parent0f28e38bbeaa11bda20b81f2247c82682d93d787 (diff)
downloadskiboot-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.c47
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;
}