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 | 9 | ||||
-rw-r--r-- | drivers/of/of_mdio.c | 39 | ||||
-rw-r--r-- | drivers/of/of_pci.c | 1 |
5 files changed, 86 insertions, 25 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 7ee21ae305ae..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, diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 86829f8064a6..365dc7e83ab4 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -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; @@ -256,11 +284,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 +305,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 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) |