diff options
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r-- | drivers/of/address.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index b4559c5..39016a0 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -97,8 +97,13 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) static int of_bus_pci_match(struct device_node *np) { - /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ - return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); + /* + * "pciex" is PCI Express + * "vci" is for the /chaos bridge on 1st-gen PCI powermacs + * "ht" is hypertransport + */ + return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") || + !strcmp(np->type, "vci") || !strcmp(np->type, "ht"); } static void of_bus_pci_count_cells(struct device_node *np, @@ -328,6 +333,22 @@ static struct of_bus *of_match_bus(struct device_node *np) return NULL; } +static int of_empty_ranges_quirk(void) +{ +#ifdef CONFIG_PPC + /* To save cycles, we cache the result */ + static int quirk_state = -1; + + if (quirk_state < 0) + quirk_state = + of_machine_is_compatible("Power Macintosh") || + of_machine_is_compatible("MacRISC"); + return quirk_state; +#else + return false; +#endif +} + static int of_translate_one(struct device_node *parent, struct of_bus *bus, struct of_bus *pbus, u32 *addr, int na, int ns, int pna, const char *rprop) @@ -353,12 +374,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * This code is only enabled on powerpc. --gcl */ ranges = of_get_property(parent, rprop, &rlen); -#if !defined(CONFIG_PPC) - if (ranges == NULL) { + if (ranges == NULL && !of_empty_ranges_quirk()) { pr_err("OF: no ranges; cannot translate\n"); return 1; } -#endif /* !defined(CONFIG_PPC) */ if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); @@ -577,6 +596,24 @@ int of_address_to_resource(struct device_node *dev, int index, } EXPORT_SYMBOL_GPL(of_address_to_resource); +struct device_node *of_find_matching_node_by_address(struct device_node *from, + const struct of_device_id *matches, + u64 base_address) +{ + struct device_node *dn = of_find_matching_node(from, matches); + struct resource res; + + while (dn) { + if (!of_address_to_resource(dn, 0, &res) && + res.start == base_address) + return dn; + + dn = of_find_matching_node(dn, matches); + } + + return NULL; +} + /** * of_iomap - Maps the memory mapped IO for a given device_node @@ -592,6 +629,6 @@ void __iomem *of_iomap(struct device_node *np, int index) if (of_address_to_resource(np, index, &res)) return NULL; - return ioremap(res.start, 1 + res.end - res.start); + return ioremap(res.start, resource_size(&res)); } EXPORT_SYMBOL(of_iomap); |