summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/arm64/amba.c2
-rw-r--r--drivers/amba/bus.c5
-rw-r--r--drivers/of/address.c85
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/of/unittest-data/overlay_bad_unresolved.dtso2
-rw-r--r--drivers/of/unittest-data/tests-address.dtsi101
-rw-r--r--drivers/of/unittest.c77
7 files changed, 218 insertions, 56 deletions
diff --git a/drivers/acpi/arm64/amba.c b/drivers/acpi/arm64/amba.c
index 60be8ee1dbdc..171b5c2c7edd 100644
--- a/drivers/acpi/arm64/amba.c
+++ b/drivers/acpi/arm64/amba.c
@@ -101,7 +101,7 @@ static int amba_handler_attach(struct acpi_device *adev,
if (parent)
dev->dev.parent = acpi_get_first_physical_node(parent);
- ACPI_COMPANION_SET(&dev->dev, adev);
+ device_set_node(&dev->dev, acpi_fwnode_handle(adev));
ret = amba_device_add(dev, &iomem_resource);
if (ret) {
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 09e72967b8ab..a24c152bfaac 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -18,6 +18,7 @@
#include <linux/limits.h>
#include <linux/clk/clk-conf.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/reset.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
@@ -528,7 +529,7 @@ static void amba_device_release(struct device *dev)
{
struct amba_device *d = to_amba_device(dev);
- of_node_put(d->dev.of_node);
+ fwnode_handle_put(dev_fwnode(&d->dev));
if (d->res.parent)
release_resource(&d->res);
mutex_destroy(&d->periphid_lock);
@@ -548,6 +549,8 @@ int amba_device_add(struct amba_device *dev, struct resource *parent)
{
int ret;
+ fwnode_handle_get(dev_fwnode(&dev->dev));
+
ret = request_resource(parent, &dev->res);
if (ret)
return ret;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index e692809ff822..b59956310f66 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -43,9 +43,9 @@ struct of_bus {
void (*count_cells)(struct device_node *child,
int *addrc, int *sizec);
u64 (*map)(__be32 *addr, const __be32 *range,
- int na, int ns, int pna);
+ int na, int ns, int pna, int fna);
int (*translate)(__be32 *addr, u64 offset, int na);
- bool has_flags;
+ int flag_cells;
unsigned int (*get_flags)(const __be32 *addr);
};
@@ -63,13 +63,13 @@ static void of_bus_default_count_cells(struct device_node *dev,
}
static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
- int na, int ns, int pna)
+ int na, int ns, int pna, int fna)
{
u64 cp, s, da;
- cp = of_read_number(range, na);
+ cp = of_read_number(range + fna, na - fna);
s = of_read_number(range + na + pna, ns);
- da = of_read_number(addr, na);
+ da = of_read_number(addr + fna, na - fna);
pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
@@ -100,6 +100,21 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
return IORESOURCE_MEM;
}
+static u64 of_bus_default_flags_map(__be32 *addr, const __be32 *range, int na,
+ int ns, int pna, int fna)
+{
+ /* Check that flags match */
+ if (*addr != *range)
+ return OF_BAD_ADDR;
+
+ return of_bus_default_map(addr, range, na, ns, pna, fna);
+}
+
+static int of_bus_default_flags_translate(__be32 *addr, u64 offset, int na)
+{
+ /* Keep "flags" part (high cell) in translated address */
+ return of_bus_default_translate(addr + 1, offset, na - 1);
+}
#ifdef CONFIG_PCI
static unsigned int of_bus_pci_get_flags(const __be32 *addr)
@@ -166,9 +181,8 @@ static void of_bus_pci_count_cells(struct device_node *np,
}
static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
- int pna)
+ int pna, int fna)
{
- u64 cp, s, da;
unsigned int af, rf;
af = of_bus_pci_get_flags(addr);
@@ -178,22 +192,9 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
return OF_BAD_ADDR;
- /* Read address values, skipping high cell */
- cp = of_read_number(range + 1, na - 1);
- s = of_read_number(range + na + pna, ns);
- da = of_read_number(addr + 1, na - 1);
-
- pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
-
- if (da < cp || da >= (cp + s))
- return OF_BAD_ADDR;
- return da - cp;
+ return of_bus_default_map(addr, range, na, ns, pna, fna);
}
-static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
-{
- return of_bus_default_translate(addr + 1, offset, na - 1);
-}
#endif /* CONFIG_PCI */
/*
@@ -297,29 +298,13 @@ static void of_bus_isa_count_cells(struct device_node *child,
}
static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
- int pna)
+ int pna, int fna)
{
- u64 cp, s, da;
-
/* Check address type match */
if ((addr[0] ^ range[0]) & cpu_to_be32(1))
return OF_BAD_ADDR;
- /* Read address values, skipping high cell */
- cp = of_read_number(range + 1, na - 1);
- s = of_read_number(range + na + pna, ns);
- da = of_read_number(addr + 1, na - 1);
-
- pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
-
- if (da < cp || da >= (cp + s))
- return OF_BAD_ADDR;
- return da - cp;
-}
-
-static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
-{
- return of_bus_default_translate(addr + 1, offset, na - 1);
+ return of_bus_default_map(addr, range, na, ns, pna, fna);
}
static unsigned int of_bus_isa_get_flags(const __be32 *addr)
@@ -352,8 +337,8 @@ static struct of_bus of_busses[] = {
.match = of_bus_pci_match,
.count_cells = of_bus_pci_count_cells,
.map = of_bus_pci_map,
- .translate = of_bus_pci_translate,
- .has_flags = true,
+ .translate = of_bus_default_flags_translate,
+ .flag_cells = 1,
.get_flags = of_bus_pci_get_flags,
},
#endif /* CONFIG_PCI */
@@ -364,8 +349,8 @@ static struct of_bus of_busses[] = {
.match = of_bus_isa_match,
.count_cells = of_bus_isa_count_cells,
.map = of_bus_isa_map,
- .translate = of_bus_isa_translate,
- .has_flags = true,
+ .translate = of_bus_default_flags_translate,
+ .flag_cells = 1,
.get_flags = of_bus_isa_get_flags,
},
/* Default with flags cell */
@@ -374,9 +359,9 @@ static struct of_bus of_busses[] = {
.addresses = "reg",
.match = of_bus_default_flags_match,
.count_cells = of_bus_default_count_cells,
- .map = of_bus_default_map,
- .translate = of_bus_default_translate,
- .has_flags = true,
+ .map = of_bus_default_flags_map,
+ .translate = of_bus_default_flags_translate,
+ .flag_cells = 1,
.get_flags = of_bus_default_flags_get_flags,
},
/* Default */
@@ -469,7 +454,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
rlen /= 4;
rone = na + pna + ns;
for (; rlen >= rone; rlen -= rone, ranges += rone) {
- offset = bus->map(addr, ranges, na, ns, pna);
+ offset = bus->map(addr, ranges, na, ns, pna, bus->flag_cells);
if (offset != OF_BAD_ADDR)
break;
}
@@ -809,7 +794,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
int na = parser->na;
int ns = parser->ns;
int np = parser->pna + na + ns;
- int busflag_na = 0;
+ int busflag_na = parser->bus->flag_cells;
if (!range)
return NULL;
@@ -819,10 +804,6 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
range->flags = parser->bus->get_flags(parser->range);
- /* A extra cell for resource flags */
- if (parser->bus->has_flags)
- busflag_na = 1;
-
range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
if (parser->dma)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index f235ab55b91e..126d265aa7d8 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -273,7 +273,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
/* setup generic device info */
- device_set_node(&dev->dev, of_fwnode_handle(of_node_get(node)));
+ device_set_node(&dev->dev, of_fwnode_handle(node));
dev->dev.parent = parent ? : &platform_bus;
dev->dev.platform_data = platform_data;
if (bus_id)
diff --git a/drivers/of/unittest-data/overlay_bad_unresolved.dtso b/drivers/of/unittest-data/overlay_bad_unresolved.dtso
index 3b75a53ae8a4..f34d8780d42d 100644
--- a/drivers/of/unittest-data/overlay_bad_unresolved.dtso
+++ b/drivers/of/unittest-data/overlay_bad_unresolved.dtso
@@ -3,5 +3,5 @@
/plugin/;
&this_label_does_not_exist {
- status = "ok";
+ status = "okay";
};
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();