diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 5 | ||||
-rw-r--r-- | drivers/of/fdt.c | 7 | ||||
-rw-r--r-- | drivers/of/irq.c | 3 | ||||
-rw-r--r-- | drivers/of/of_mdio.c | 95 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 8 |
5 files changed, 92 insertions, 26 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 5289c80..91a469d 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -485,9 +485,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, int rone; u64 offset = OF_BAD_ADDR; - /* Normally, an absence of a "ranges" property means we are + /* + * Normally, an absence of a "ranges" property means we are * crossing a non-translatable boundary, and thus the addresses - * below the current not cannot be converted to CPU physical ones. + * below the current cannot be converted to CPU physical ones. * Unfortunately, while this is very clear in the spec, it's not * what Apple understood, and they do have things like /uni-n or * /ht nodes with no "ranges" property and a lot of perfectly diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index d243029..655f79d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/initrd.h> #include <linux/memblock.h> +#include <linux/mutex.h> #include <linux/of.h> #include <linux/of_fdt.h> #include <linux/of_reserved_mem.h> @@ -436,6 +437,8 @@ static void *kernel_tree_alloc(u64 size, u64 align) return kzalloc(size, GFP_KERNEL); } +static DEFINE_MUTEX(of_fdt_unflatten_mutex); + /** * of_fdt_unflatten_tree - create tree of device_nodes from flat blob * @@ -447,7 +450,9 @@ static void *kernel_tree_alloc(u64 size, u64 align) void of_fdt_unflatten_tree(const unsigned long *blob, struct device_node **mynodes) { + mutex_lock(&of_fdt_unflatten_mutex); __unflatten_device_tree(blob, mynodes, &kernel_tree_alloc); + mutex_unlock(&of_fdt_unflatten_mutex); } EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); @@ -1041,7 +1046,7 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { - pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n", + pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n", &base, &size, nomap ? " (nomap)" : ""); return -ENOSYS; } diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 4c0da87..706e3ff 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); * Returns a pointer to the interrupt parent node, or NULL if the interrupt * parent could not be determined. */ -static struct device_node *of_irq_find_parent(struct device_node *child) +struct device_node *of_irq_find_parent(struct device_node *child) { struct device_node *p; const __be32 *parp; @@ -77,6 +77,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child) return p; } +EXPORT_SYMBOL_GPL(of_irq_find_parent); /** * of_irq_parse_raw - Low level interrupt tree parsing diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index a87a868..86829f8 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -62,11 +62,9 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi rc = irq_of_parse_and_map(child, 0); if (rc > 0) { phy->irq = rc; - if (mdio->irq) - mdio->irq[addr] = rc; + mdio->irq[addr] = rc; } else { - if (mdio->irq) - phy->irq = mdio->irq[addr]; + phy->irq = mdio->irq[addr]; } if (of_property_read_bool(child, "broken-turn-around")) @@ -75,7 +73,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); - phy->dev.of_node = child; + phy->mdio.dev.of_node = child; /* All data is now stored in the phy struct; * register it */ @@ -92,6 +90,37 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi return 0; } +static int of_mdiobus_register_device(struct mii_bus *mdio, + struct device_node *child, + u32 addr) +{ + struct mdio_device *mdiodev; + int rc; + + mdiodev = mdio_device_create(mdio, addr); + if (!mdiodev || IS_ERR(mdiodev)) + return 1; + + /* Associate the OF node with the device structure so it + * can be looked up later. + */ + of_node_get(child); + mdiodev->dev.of_node = child; + + /* All data is now stored in the mdiodev struct; register it. */ + rc = mdio_device_register(mdiodev); + if (rc) { + mdio_device_free(mdiodev); + of_node_put(child); + return 1; + } + + dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n", + child->name, addr); + + return 0; +} + int of_mdio_parse_addr(struct device *dev, const struct device_node *np) { u32 addr; @@ -114,6 +143,35 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np) } EXPORT_SYMBOL(of_mdio_parse_addr); +/* + * 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 No compatibility string + * + * A device which is not a phy is expected to have a compatible string + * indicating what sort of device it is. + */ +static bool of_mdiobus_child_is_phy(struct device_node *child) +{ + u32 phy_id; + + if (of_get_phy_id(child, &phy_id) != -EINVAL) + return true; + + if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45")) + return true; + + if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22")) + return true; + + if (!of_find_property(child, "compatible", NULL)) + return true; + + return false; +} + /** * of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure @@ -127,17 +185,12 @@ 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, i; + int addr, rc; /* Mask out all PHYs from auto probing. Instead the PHYs listed in * the device tree are populated after the bus has been registered */ mdio->phy_mask = ~0; - /* Clear all the IRQ properties */ - if (mdio->irq) - for (i=0; i<PHY_MAX_ADDR; i++) - mdio->irq[i] = PHY_POLL; - mdio->dev.of_node = np; /* Register the MDIO bus */ @@ -145,7 +198,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) if (rc) return rc; - /* Loop over the child nodes and register a phy_device for each one */ + /* Loop over the child nodes and register a phy_device for each phy */ for_each_available_child_of_node(np, child) { addr = of_mdio_parse_addr(&mdio->dev, child); if (addr < 0) { @@ -153,9 +206,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) continue; } - rc = of_mdiobus_register_phy(mdio, child, addr); - if (rc) - continue; + if (of_mdiobus_child_is_phy(child)) + of_mdiobus_register_phy(mdio, child, addr); + else + of_mdiobus_register_device(mdio, child, addr); } if (!scanphys) @@ -170,16 +224,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) for (addr = 0; addr < PHY_MAX_ADDR; addr++) { /* skip already registered PHYs */ - if (mdio->phy_map[addr]) + if (mdiobus_is_registered_device(mdio, addr)) continue; /* be noisy to encourage people to set reg property */ dev_info(&mdio->dev, "scan phy %s at address %i\n", child->name, addr); - rc = of_mdiobus_register_phy(mdio, child, addr); - if (rc) - continue; + if (of_mdiobus_child_is_phy(child)) + of_mdiobus_register_phy(mdio, child, addr); } } @@ -238,7 +291,7 @@ struct phy_device *of_phy_connect(struct net_device *dev, ret = phy_connect_direct(dev, phy, hndlr, iface); /* refcount is held by phy_connect_direct() on success */ - put_device(&phy->dev); + put_device(&phy->mdio.dev); return ret ? NULL : phy; } @@ -268,7 +321,7 @@ struct phy_device *of_phy_attach(struct net_device *dev, ret = phy_attach_direct(dev, phy, flags, iface); /* refcount is held by phy_attach_direct() on success */ - put_device(&phy->dev); + put_device(&phy->mdio.dev); return ret ? NULL : phy; } diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index be77e75..1a3556a 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -206,7 +206,13 @@ static int __init __rmem_cmp(const void *a, const void *b) { const struct reserved_mem *ra = a, *rb = b; - return ra->base - rb->base; + if (ra->base < rb->base) + return -1; + + if (ra->base > rb->base) + return 1; + + return 0; } static void __init __rmem_check_for_overlap(void) |