diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 40 | ||||
-rw-r--r-- | drivers/of/base.c | 5 | ||||
-rw-r--r-- | drivers/of/device.c | 2 | ||||
-rw-r--r-- | drivers/of/fdt.c | 2 | ||||
-rw-r--r-- | drivers/of/irq.c | 2 | ||||
-rw-r--r-- | drivers/of/of_net.c | 55 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 22 | ||||
-rw-r--r-- | drivers/of/property.c | 2 | ||||
-rw-r--r-- | drivers/of/unittest.c | 13 |
9 files changed, 113 insertions, 30 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 2270373b30ab..978427a9d5e6 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -569,6 +569,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * relative to that node. */ static u64 __of_translate_address(struct device_node *dev, + struct device_node *(*get_parent)(const struct device_node *), const __be32 *in_addr, const char *rprop, struct device_node **host) { @@ -585,7 +586,7 @@ static u64 __of_translate_address(struct device_node *dev, *host = NULL; /* Get parent & match bus type */ - parent = of_get_parent(dev); + parent = get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); @@ -609,7 +610,7 @@ static u64 __of_translate_address(struct device_node *dev, /* Switch to parent bus */ of_node_put(dev); dev = parent; - parent = of_get_parent(dev); + parent = get_parent(dev); /* If root, we have finished */ if (parent == NULL) { @@ -665,7 +666,8 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) struct device_node *host; u64 ret; - ret = __of_translate_address(dev, in_addr, "ranges", &host); + ret = __of_translate_address(dev, of_get_parent, + in_addr, "ranges", &host); if (host) { of_node_put(host); return OF_BAD_ADDR; @@ -675,12 +677,31 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) } EXPORT_SYMBOL(of_translate_address); +static struct device_node *__of_get_dma_parent(const struct device_node *np) +{ + struct of_phandle_args args; + int ret, index; + + index = of_property_match_string(np, "interconnect-names", "dma-mem"); + if (index < 0) + return of_get_parent(np); + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", + index, &args); + if (ret < 0) + return of_get_parent(np); + + return of_node_get(args.np); +} + u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) { struct device_node *host; u64 ret; - ret = __of_translate_address(dev, in_addr, "dma-ranges", &host); + ret = __of_translate_address(dev, __of_get_dma_parent, + in_addr, "dma-ranges", &host); if (host) { of_node_put(host); @@ -736,7 +757,8 @@ static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, unsigned long port; struct device_node *host; - taddr = __of_translate_address(dev, in_addr, "ranges", &host); + taddr = __of_translate_address(dev, of_get_parent, + in_addr, "ranges", &host); if (host) { /* host-specific port access */ port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); @@ -908,9 +930,15 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz return -EINVAL; while (1) { + struct device_node *parent; + naddr = of_n_addr_cells(node); nsize = of_n_size_cells(node); - node = of_get_next_parent(node); + + parent = __of_get_dma_parent(node); + of_node_put(node); + + node = parent; if (!node) break; diff --git a/drivers/of/base.c b/drivers/of/base.c index 5226e898476e..20e0e7ee4edf 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1350,8 +1350,9 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) * property data length */ if (it->cur + count > it->list_end) { - pr_err("%pOF: arguments longer than property\n", - it->parent); + pr_err("%pOF: %s = %d found %d\n", + it->parent, it->cells_name, + count, it->cell_count); goto err; } } diff --git a/drivers/of/device.c b/drivers/of/device.c index 3717f2a20d0d..da8158392010 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -17,7 +17,7 @@ /** * of_match_device - Tell if a struct device matches an of_device_id list - * @ids: array of of device match structures to search in + * @matches: array of of device match structures to search in * @dev: the of device structure to match against * * Used by a driver to check whether an platform_device present in the diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 4734223ab702..de893c9616a1 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1091,7 +1091,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, /* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) - strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); /* * CONFIG_CMDLINE is meant to be a default in case nothing else diff --git a/drivers/of/irq.c b/drivers/of/irq.c index e1f6f392a4c0..7f84bb4903ca 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -500,7 +500,7 @@ void __init of_irq_init(const struct of_device_id *matches) * pointer, interrupt-parent device_node etc. */ desc = kzalloc(sizeof(*desc), GFP_KERNEL); - if (WARN_ON(!desc)) { + if (!desc) { of_node_put(np); goto err; } diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c index 810ab0fbcccb..9649cd53e955 100644 --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c @@ -7,10 +7,11 @@ */ #include <linux/etherdevice.h> #include <linux/kernel.h> -#include <linux/nvmem-consumer.h> #include <linux/of_net.h> +#include <linux/of_platform.h> #include <linux/phy.h> #include <linux/export.h> +#include <linux/device.h> /** * of_get_phy_mode - Get phy mode for given device_node @@ -48,12 +49,52 @@ static const void *of_get_mac_addr(struct device_node *np, const char *name) return NULL; } +static const void *of_get_mac_addr_nvmem(struct device_node *np) +{ + int ret; + u8 mac[ETH_ALEN]; + struct property *pp; + struct platform_device *pdev = of_find_device_by_node(np); + + if (!pdev) + return ERR_PTR(-ENODEV); + + ret = nvmem_get_mac_address(&pdev->dev, &mac); + if (ret) + return ERR_PTR(ret); + + pp = devm_kzalloc(&pdev->dev, sizeof(*pp), GFP_KERNEL); + if (!pp) + return ERR_PTR(-ENOMEM); + + pp->name = "nvmem-mac-address"; + pp->length = ETH_ALEN; + pp->value = devm_kmemdup(&pdev->dev, mac, ETH_ALEN, GFP_KERNEL); + if (!pp->value) { + ret = -ENOMEM; + goto free; + } + + ret = of_add_property(np, pp); + if (ret) + goto free; + + return pp->value; +free: + devm_kfree(&pdev->dev, pp->value); + devm_kfree(&pdev->dev, pp); + + return ERR_PTR(ret); +} + /** * Search the device tree for the best MAC address to use. 'mac-address' is * checked first, because that is supposed to contain to "most recent" MAC * address. If that isn't set, then 'local-mac-address' is checked next, - * because that is the default address. If that isn't set, then the obsolete - * 'address' is checked, just in case we're using an old device tree. + * because that is the default address. If that isn't set, then the obsolete + * 'address' is checked, just in case we're using an old device tree. If any + * of the above isn't set, then try to get MAC address from nvmem cell named + * 'mac-address'. * * Note that the 'address' property is supposed to contain a virtual address of * the register set, but some DTS files have redefined that property to be the @@ -65,6 +106,8 @@ static const void *of_get_mac_addr(struct device_node *np, const char *name) * addresses. Some older U-Boots only initialized 'local-mac-address'. In * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists * but is all zeros. + * + * Return: Will be a valid pointer on success and ERR_PTR in case of error. */ const void *of_get_mac_address(struct device_node *np) { @@ -78,6 +121,10 @@ const void *of_get_mac_address(struct device_node *np) if (addr) return addr; - return of_get_mac_addr(np, "address"); + addr = of_get_mac_addr(np, "address"); + if (addr) + return addr; + + return of_get_mac_addr_nvmem(np); } EXPORT_SYMBOL(of_get_mac_address); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 6a36bc0b3d64..89e190e94af7 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -171,6 +171,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) { extern const struct of_device_id __reservedmem_of_table[]; const struct of_device_id *i; + int ret = -ENOENT; for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { reservedmem_of_init_fn initfn = i->data; @@ -179,13 +180,14 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) continue; - if (initfn(rmem) == 0) { + ret = initfn(rmem); + if (ret == 0) { pr_info("initialized node %s, compatible id %s\n", rmem->name, compat); - return 0; + break; } } - return -ENOENT; + return ret; } static int __init __rmem_cmp(const void *a, const void *b) @@ -245,7 +247,9 @@ void __init fdt_init_reserved_mem(void) int len; const __be32 *prop; int err = 0; + int nomap; + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; prop = of_get_flat_dt_prop(node, "phandle", &len); if (!prop) prop = of_get_flat_dt_prop(node, "linux,phandle", &len); @@ -255,8 +259,16 @@ void __init fdt_init_reserved_mem(void) if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); - if (err == 0) - __reserved_mem_init_node(rmem); + if (err == 0) { + err = __reserved_mem_init_node(rmem); + if (err != 0 && err != -ENOENT) { + pr_info("node %s compatible matching fail\n", + rmem->name); + memblock_free(rmem->base, rmem->size); + if (nomap) + memblock_add(rmem->base, rmem->size); + } + } } } diff --git a/drivers/of/property.c b/drivers/of/property.c index 8631efa1daa1..d7fa75e31f22 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -659,7 +659,7 @@ EXPORT_SYMBOL(of_graph_get_next_endpoint); * * Return: An 'endpoint' node pointer which is identified by reg and at the same * is the child of a port node identified by port_reg. reg and port_reg are - * ignored when they are -1. + * ignored when they are -1. Use of_node_put() on the pointer when done. */ struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index cccde756b510..3832a5de4602 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -344,7 +344,7 @@ static void __init of_unittest_check_phandles(void) } nh = kzalloc(sizeof(*nh), GFP_KERNEL); - if (WARN_ON(!nh)) + if (!nh) return; nh->np = np; @@ -1199,12 +1199,9 @@ static int __init unittest_data_add(void) /* creating copy */ unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); - - if (!unittest_data) { - pr_warn("%s: Failed to allocate memory for unittest_data; " - "not running tests\n", __func__); + if (!unittest_data) return -ENOMEM; - } + of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); if (!unittest_data_node) { pr_warn("%s: No tree to attach; not running tests\n", __func__); @@ -1845,10 +1842,8 @@ static int unittest_i2c_bus_probe(struct platform_device *pdev) dev_dbg(dev, "%s for node @%pOF\n", __func__, np); std = devm_kzalloc(dev, sizeof(*std), GFP_KERNEL); - if (!std) { - dev_err(dev, "Failed to allocate unittest i2c data\n"); + if (!std) return -ENOMEM; - } /* link them together */ std->pdev = pdev; |