diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/fdt.c | 51 | ||||
-rw-r--r-- | drivers/of/fdt_address.c | 11 | ||||
-rw-r--r-- | drivers/of/irq.c | 27 | ||||
-rw-r--r-- | drivers/of/of_mdio.c | 53 | ||||
-rw-r--r-- | drivers/of/of_pci.c | 1 |
5 files changed, 95 insertions, 48 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 655f79db7899..3349d2aa6634 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -760,6 +760,16 @@ const void * __init of_flat_dt_match_machine(const void *default_match, } #ifdef CONFIG_BLK_DEV_INITRD +#ifndef __early_init_dt_declare_initrd +static void __early_init_dt_declare_initrd(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + /** * early_init_dt_check_for_initrd - Decode initrd location from flat tree * @node: reference to node containing initrd location ('chosen') @@ -782,9 +792,7 @@ static void __init early_init_dt_check_for_initrd(unsigned long node) return; end = of_read_number(prop, len/4); - initrd_start = (unsigned long)__va(start); - initrd_end = (unsigned long)__va(end); - initrd_below_start_ok = 1; + __early_init_dt_declare_initrd(start, end); pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", (unsigned long long)start, (unsigned long long)end); @@ -796,14 +804,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SERIAL_EARLYCON -extern struct of_device_id __earlycon_of_table[]; static int __init early_init_dt_scan_chosen_serial(void) { int offset; - const char *p; + const char *p, *q, *options = NULL; int l; - const struct of_device_id *match = __earlycon_of_table; + const struct earlycon_id *match; const void *fdt = initial_boot_params; offset = fdt_path_offset(fdt, "/chosen"); @@ -818,27 +825,26 @@ static int __init early_init_dt_scan_chosen_serial(void) if (!p || !l) return -ENOENT; - /* Remove console options if present */ - l = strchrnul(p, ':') - p; + q = strchrnul(p, ':'); + if (*q != '\0') + options = q + 1; + l = q - p; /* Get the node specified by stdout-path */ offset = fdt_path_offset_namelen(fdt, p, l); - if (offset < 0) - return -ENODEV; - - while (match->compatible[0]) { - u64 addr; + if (offset < 0) { + pr_warn("earlycon: stdout-path %.*s not found\n", l, p); + return 0; + } - if (fdt_node_check_compatible(fdt, offset, match->compatible)) { - match++; + for (match = __earlycon_table; match < __earlycon_table_end; match++) { + if (!match->compatible[0]) continue; - } - addr = fdt_translate_address(fdt, offset); - if (addr == OF_BAD_ADDR) - return -ENXIO; + if (fdt_node_check_compatible(fdt, offset, match->compatible)) + continue; - of_setup_earlycon(addr, match->data); + of_setup_earlycon(match, offset, options); return 0; } return -ENODEV; @@ -976,13 +982,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, } #ifdef CONFIG_HAVE_MEMBLOCK +#ifndef MIN_MEMBLOCK_ADDR +#define MIN_MEMBLOCK_ADDR __pa(PAGE_OFFSET) +#endif #ifndef MAX_MEMBLOCK_ADDR #define MAX_MEMBLOCK_ADDR ((phys_addr_t)~0) #endif void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) { - const u64 phys_offset = __pa(PAGE_OFFSET); + const u64 phys_offset = MIN_MEMBLOCK_ADDR; if (!PAGE_ALIGNED(base)) { if (size < PAGE_SIZE - (base & ~PAGE_MASK)) { diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c index 8d3dc6fbdb7a..dca8f9b93745 100644 --- a/drivers/of/fdt_address.c +++ b/drivers/of/fdt_address.c @@ -161,7 +161,7 @@ static int __init fdt_translate_one(const void *blob, int parent, * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ -u64 __init fdt_translate_address(const void *blob, int node_offset) +static u64 __init fdt_translate_address(const void *blob, int node_offset) { int parent, len; const struct of_bus *bus, *pbus; @@ -239,3 +239,12 @@ u64 __init fdt_translate_address(const void *blob, int node_offset) bail: return result; } + +/** + * of_flat_dt_translate_address - translate DT addr into CPU phys addr + * @node: node in the flat blob + */ +u64 __init of_flat_dt_translate_address(unsigned long node) +{ + return fdt_translate_address(initial_boot_params, node); +} diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 706e3ff67f8b..e7bfc175b8e1 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -635,6 +635,13 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, msi_base = be32_to_cpup(msi_map + 2); rid_len = be32_to_cpup(msi_map + 3); + if (rid_base & ~map_mask) { + dev_err(parent_dev, + "Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n", + map_mask, rid_base); + return rid_out; + } + msi_controller_node = of_find_node_by_phandle(phandle); matched = (masked_rid >= rid_base && @@ -654,7 +661,7 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, if (!matched) return rid_out; - rid_out = masked_rid + msi_base; + rid_out = masked_rid - rid_base + msi_base; dev_dbg(dev, "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n", dev_name(parent_dev), map_mask, rid_base, msi_base, @@ -679,18 +686,6 @@ u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in) return __of_msi_map_rid(dev, &msi_np, rid_in); } -static struct irq_domain *__of_get_msi_domain(struct device_node *np, - enum irq_domain_bus_token token) -{ - struct irq_domain *d; - - d = irq_find_matching_host(np, token); - if (!d) - d = irq_find_host(np); - - return d; -} - /** * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain * @dev: device for which the mapping is to be done. @@ -706,7 +701,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid) struct device_node *np = NULL; __of_msi_map_rid(dev, &np, rid); - return __of_get_msi_domain(np, DOMAIN_BUS_PCI_MSI); + return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI); } /** @@ -730,7 +725,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev, /* Check for a single msi-parent property */ msi_np = of_parse_phandle(np, "msi-parent", 0); if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) { - d = __of_get_msi_domain(msi_np, token); + d = irq_find_matching_host(msi_np, token); if (!d) of_node_put(msi_np); return d; @@ -744,7 +739,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev, while (!of_parse_phandle_with_args(np, "msi-parent", "#msi-cells", index, &args)) { - d = __of_get_msi_domain(args.np, token); + d = irq_find_matching_host(args.np, token); if (d) return d; diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 86829f8064a6..8453f08d2ef4 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -56,7 +56,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi phy = phy_device_create(mdio, addr, phy_id, 0, NULL); else phy = get_phy_device(mdio, addr, is_c45); - if (!phy || IS_ERR(phy)) + if (IS_ERR_OR_NULL(phy)) return 1; rc = irq_of_parse_and_map(child, 0); @@ -98,7 +98,7 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, int rc; mdiodev = mdio_device_create(mdio, addr); - if (!mdiodev || IS_ERR(mdiodev)) + if (IS_ERR(mdiodev)) return 1; /* Associate the OF node with the device structure so it @@ -143,11 +143,32 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np) } EXPORT_SYMBOL(of_mdio_parse_addr); +/* The following is a list of PHY compatible strings which appear in + * some DTBs. The compatible string is never matched against a PHY + * driver, so is pointless. We only expect devices which are not PHYs + * to have a compatible string, so they can be matched to an MDIO + * driver. Encourage users to upgrade their DT blobs to remove these. + */ +static const struct of_device_id whitelist_phys[] = { + { .compatible = "brcm,40nm-ephy" }, + { .compatible = "marvell,88E1111", }, + { .compatible = "marvell,88e1116", }, + { .compatible = "marvell,88e1118", }, + { .compatible = "marvell,88e1145", }, + { .compatible = "marvell,88e1149r", }, + { .compatible = "marvell,88e1310", }, + { .compatible = "marvell,88E1510", }, + { .compatible = "marvell,88E1514", }, + { .compatible = "moxa,moxart-rtl8201cp", }, + {} +}; + /* * Return true if the child node is for a phy. It must either: * o Compatible string of "ethernet-phy-idX.X" * o Compatible string of "ethernet-phy-ieee802.3-c45" * o Compatible string of "ethernet-phy-ieee802.3-c22" + * o In the white list above (and issue a warning) * o No compatibility string * * A device which is not a phy is expected to have a compatible string @@ -166,6 +187,13 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22")) return true; + if (of_match_node(whitelist_phys, child)) { + pr_warn(FW_WARN + "%s: Whitelisted compatible string. Please remove\n", + child->full_name); + return true; + } + if (!of_find_property(child, "compatible", NULL)) return true; @@ -183,7 +211,6 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct device_node *child; - const __be32 *paddr; bool scanphys = false; int addr, rc; @@ -218,8 +245,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) { /* Skip PHYs with reg property set */ - paddr = of_get_property(child, "reg", NULL); - if (paddr) + if (of_find_property(child, "reg", NULL)) continue; for (addr = 0; addr < PHY_MAX_ADDR; addr++) { @@ -256,11 +282,19 @@ static int of_phy_match(struct device *dev, void *phy_np) struct phy_device *of_phy_find_device(struct device_node *phy_np) { struct device *d; + struct mdio_device *mdiodev; + if (!phy_np) return NULL; d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); - return d ? to_phy_device(d) : NULL; + if (d) { + mdiodev = to_mdio_device(d); + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) + return to_phy_device(d); + } + + return NULL; } EXPORT_SYMBOL(of_phy_find_device); @@ -269,6 +303,7 @@ EXPORT_SYMBOL(of_phy_find_device); * @dev: pointer to net_device claiming the phy * @phy_np: Pointer to device tree node for the PHY * @hndlr: Link state callback for the network device + * @flags: flags to pass to the PHY * @iface: PHY data interface type * * If successful, returns a pointer to the phy_device with the embedded @@ -377,7 +412,7 @@ int of_phy_register_fixed_link(struct device_node *np) if (strcmp(managed, "in-band-status") == 0) { /* status is zeroed, namely its .link member */ phy = fixed_phy_register(PHY_POLL, &status, -1, np); - return IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } } @@ -399,7 +434,7 @@ int of_phy_register_fixed_link(struct device_node *np) return -EPROBE_DEFER; phy = fixed_phy_register(PHY_POLL, &status, link_gpio, np); - return IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } /* Old binding */ @@ -411,7 +446,7 @@ int of_phy_register_fixed_link(struct device_node *np) status.pause = be32_to_cpu(fixed_link_prop[3]); status.asym_pause = be32_to_cpu(fixed_link_prop[4]); phy = fixed_phy_register(PHY_POLL, &status, -1, np); - return IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } return -ENODEV; diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index b1449f71601c..13f4fed38048 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -5,7 +5,6 @@ #include <linux/of_device.h> #include <linux/of_pci.h> #include <linux/slab.h> -#include <asm-generic/pci-bridge.h> static inline int __of_pci_pci_compare(struct device_node *node, unsigned int data) |