diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi index bc0029cbf8ea..3344f15c3755 100644 --- a/drivers/of/unittest-data/tests-address.dtsi +++ b/drivers/of/unittest-data/tests-address.dtsi @@ -51,5 +51,106 @@ }; }; + + address-tests2 { + #address-cells = <2>; + #size-cells = <1>; + + ranges = <0x10000000 0x01000000 0xa0000000 0x01000000>, + <0x10000000 0x02000000 0xb0000000 0x01000000>, + <0x20000000 0x01000000 0xc0000000 0x01000000>, + <0x20000000 0x02000000 0xd0000000 0x01000000>, + <0x00000000 0xd1000000 0xd1000000 0x01000000>, + <0x00000000 0xe8000000 0xe8000000 0x07f00000>, + <0x00000000 0xefff0000 0xefff0000 0x00010000>; + + bus-2cell@10000000 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x100000 0x10000 0x10000000 0x1a00000 0x10000>, + <0x100000 0x20000 0x10000000 0x1b00000 0x10000>, + <0x200000 0x10000 0x20000000 0x1c00000 0x10000>, + <0x200000 0x20000 0x20000000 0x2d00000 0x10000>; + + device@100000 { + reg = <0x100000 0x11000 0x100>, + <0x100000 0x12000 0x100>, + <0x200000 0x11000 0x100>, + <0x200000 0x21000 0x100>; + }; + }; + + bus-3cell@20000000 { + #address-cells = <3>; + #size-cells = <1>; + ranges = <0x1 0x100000 0x10000 0x10000000 0x1a00000 0x10000>, + <0x2 0x100000 0x10000 0x10000000 0x1b00000 0x10000>, + <0x3 0x200000 0x10000 0x20000000 0x1c00000 0x10000>, + <0x4 0x200000 0x20000 0x20000000 0x2d00000 0x10000>; + + local-bus@100000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xf1000000 0x1 0x100000 0x10000 0x10000>, + <0xf2000000 0x2 0x100000 0x10000 0x10000>, + <0xf3000000 0x3 0x200000 0x10000 0x08000>, + <0xf3800000 0x3 0x200000 0x18000 0x08000>, + <0xf4000000 0x4 0x200000 0x20000 0x10000>; + + device@f1001000 { + reg = <0xf1001000 0x100>, + <0xf2002000 0x100>, + <0xf3001000 0x100>, + <0xf3801000 0x100>, + <0xf4001000 0x100>; + }; + }; + }; + + pcie@d1070000 { + #address-cells = <0x03>; + #size-cells = <0x02>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x7f00000>, + <0x81000000 0 0x00000000 0 0xefff0000 0 0x0010000>; + reg = <0x00000000 0xd1070000 0x20000>; + + pci@0,0 { + #address-cells = <0x03>; + #size-cells = <0x02>; + bus-range = <0x01 0x01>; + device_type = "pci"; + ranges = <0x82000000 0 0xe8000000 + 0x82000000 0 0xe8000000 + 0 0x4400000>; + reg = <0x00 0x00 0x00 0x00 0x00>; + + dev@0,0 { + #address-cells = <0x03>; + #size-cells = <0x02>; + ranges = <0 0 0 0x82010000 0 0xe8000000 0 0x2000000>, + <1 0 0 0x82010000 0 0xea000000 0 0x1000000>, + <2 0 0 0x82010000 0 0xeb000000 0 0x0800000>, + <3 0 0 0x82010000 0 0xeb800000 0 0x0800000>, + <4 0 0 0x82010000 0 0xec000000 0 0x0020000>, + <5 0 0 0x82010000 0 0xec020000 0 0x0002000>; + reg = <0x10000 0x00 0x00 0x00 0x00>; + + local-bus@0 { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0xa0000000 0 0 0 0x2000000>, + <0xb0000000 1 0 0 0x1000000>; + + dev@e0000000 { + reg = <0xa0001000 0x1000>, + <0xb0002000 0x2000>; + }; + }; + }; + }; + }; + }; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index ad2b7879cc67..e9e90e96600e 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1186,6 +1186,82 @@ static void __init of_unittest_reg(void) of_node_put(np); } +struct of_unittest_expected_res { + int index; + struct resource res; +}; + +static void __init of_unittest_check_addr(const char *node_path, + const struct of_unittest_expected_res *tab_exp, + unsigned int tab_exp_count) +{ + const struct of_unittest_expected_res *expected; + struct device_node *np; + struct resource res; + unsigned int count; + int ret; + + if (!IS_ENABLED(CONFIG_OF_ADDRESS)) + return; + + np = of_find_node_by_path(node_path); + if (!np) { + pr_err("missing testcase data (%s)\n", node_path); + return; + } + + expected = tab_exp; + count = tab_exp_count; + while (count--) { + ret = of_address_to_resource(np, expected->index, &res); + unittest(!ret, "of_address_to_resource(%pOF, %d) returned error %d\n", + np, expected->index, ret); + unittest(resource_type(&res) == resource_type(&expected->res) && + res.start == expected->res.start && + resource_size(&res) == resource_size(&expected->res), + "of_address_to_resource(%pOF, %d) wrong resource %pR, expected %pR\n", + np, expected->index, &res, &expected->res); + expected++; + } + + of_node_put(np); +} + +static const struct of_unittest_expected_res of_unittest_reg_2cell_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xa0a01000, 0x100) }, + {.index = 1, .res = DEFINE_RES_MEM(0xa0a02000, 0x100) }, + {.index = 2, .res = DEFINE_RES_MEM(0xc0c01000, 0x100) }, + {.index = 3, .res = DEFINE_RES_MEM(0xd0d01000, 0x100) }, +}; + +static const struct of_unittest_expected_res of_unittest_reg_3cell_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xa0a01000, 0x100) }, + {.index = 1, .res = DEFINE_RES_MEM(0xa0b02000, 0x100) }, + {.index = 2, .res = DEFINE_RES_MEM(0xc0c01000, 0x100) }, + {.index = 3, .res = DEFINE_RES_MEM(0xc0c09000, 0x100) }, + {.index = 4, .res = DEFINE_RES_MEM(0xd0d01000, 0x100) }, +}; + +static const struct of_unittest_expected_res of_unittest_reg_pci_expected_res[] = { + {.index = 0, .res = DEFINE_RES_MEM(0xe8001000, 0x1000) }, + {.index = 1, .res = DEFINE_RES_MEM(0xea002000, 0x2000) }, +}; + +static void __init of_unittest_translate_addr(void) +{ + of_unittest_check_addr("/testcase-data/address-tests2/bus-2cell@10000000/device@100000", + of_unittest_reg_2cell_expected_res, + ARRAY_SIZE(of_unittest_reg_2cell_expected_res)); + + of_unittest_check_addr("/testcase-data/address-tests2/bus-3cell@20000000/local-bus@100000/device@f1001000", + of_unittest_reg_3cell_expected_res, + ARRAY_SIZE(of_unittest_reg_3cell_expected_res)); + + of_unittest_check_addr("/testcase-data/address-tests2/pcie@d1070000/pci@0,0/dev@0,0/local-bus@0/dev@e0000000", + of_unittest_reg_pci_expected_res, + ARRAY_SIZE(of_unittest_reg_pci_expected_res)); +} + static void __init of_unittest_parse_interrupts(void) { struct device_node *np; @@ -4034,6 +4110,7 @@ static int __init of_unittest(void) of_unittest_bus_ranges(); of_unittest_bus_3cell_ranges(); of_unittest_reg(); + of_unittest_translate_addr(); of_unittest_match_node(); of_unittest_platform_populate(); of_unittest_overlay();