From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 09 Dec 2023 07:24:11 +0000 Subject: [PATCH] add stmac read mac form eeprom --- kernel/drivers/of/property.c | 286 +++++++++++++++++++++++++++++++++----------------------- 1 files changed, 168 insertions(+), 118 deletions(-) diff --git a/kernel/drivers/of/property.c b/kernel/drivers/of/property.c index 162c88d..12fec0e 100644 --- a/kernel/drivers/of/property.c +++ b/kernel/drivers/of/property.c @@ -24,10 +24,34 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_graph.h> +#include <linux/of_irq.h> #include <linux/string.h> #include <linux/moduleparam.h> #include "of_private.h" + +/** + * of_graph_is_present() - check graph's presence + * @node: pointer to device_node containing graph port + * + * Return: True if @node has a port or ports (with a port) sub-node, + * false otherwise. + */ +bool of_graph_is_present(const struct device_node *node) +{ + struct device_node *ports, *port; + + ports = of_get_child_by_name(node, "ports"); + if (ports) + node = ports; + + port = of_get_child_by_name(node, "port"); + of_node_put(ports); + of_node_put(port); + + return !!port; +} +EXPORT_SYMBOL(of_graph_is_present); /** * of_property_count_elems_of_size - Count the number of elements in a property @@ -165,7 +189,7 @@ * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. - * @out_values: pointer to return value, modified only if return value is 0. + * @out_values: pointer to found values. * @sz_min: minimum number of array elements to read * @sz_max: maximum number of array elements to read, if zero there is no * upper limit on the number of elements in the dts entry but only @@ -213,7 +237,7 @@ * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. - * @out_values: pointer to return value, modified only if return value is 0. + * @out_values: pointer to found values. * @sz_min: minimum number of array elements to read * @sz_max: maximum number of array elements to read, if zero there is no * upper limit on the number of elements in the dts entry but only @@ -261,7 +285,7 @@ * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. - * @out_values: pointer to return value, modified only if return value is 0. + * @out_values: pointer to return found values. * @sz_min: minimum number of array elements to read * @sz_max: maximum number of array elements to read, if zero there is no * upper limit on the number of elements in the dts entry but only @@ -335,7 +359,7 @@ * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. - * @out_values: pointer to return value, modified only if return value is 0. + * @out_values: pointer to found values. * @sz_min: minimum number of array elements to read * @sz_max: maximum number of array elements to read, if zero there is no * upper limit on the number of elements in the dts entry but only @@ -572,7 +596,7 @@ for_each_child_of_node(parent, port) { u32 port_id = 0; - if (of_node_cmp(port->name, "port") != 0) + if (!of_node_name_eq(port, "port")) continue; of_property_read_u32(port, "reg", &port_id); if (id == port_id) @@ -647,7 +671,7 @@ port = of_get_next_child(parent, port); if (!port) return NULL; - } while (of_node_cmp(port->name, "port")); + } while (!of_node_name_eq(port, "port")); } } EXPORT_SYMBOL(of_graph_get_next_endpoint); @@ -660,7 +684,7 @@ * * 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) @@ -716,7 +740,7 @@ /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && node; depth--) { node = of_get_next_parent(node); - if (depth == 2 && of_node_cmp(node->name, "ports")) + if (depth == 2 && !of_node_name_eq(node, "ports")) break; } return node; @@ -873,6 +897,20 @@ of_property_count_strings(node, propname); } +static const char *of_fwnode_get_name(const struct fwnode_handle *fwnode) +{ + return kbasename(to_of_node(fwnode)->full_name); +} + +static const char *of_fwnode_get_name_prefix(const struct fwnode_handle *fwnode) +{ + /* Root needs no prefix here (its name is "/"). */ + if (!to_of_node(fwnode)->parent) + return ""; + + return "/"; +} + static struct fwnode_handle * of_fwnode_get_parent(const struct fwnode_handle *fwnode) { @@ -895,7 +933,7 @@ struct device_node *child; for_each_available_child_of_node(node, child) - if (!of_node_cmp(child->name, childname)) + if (of_node_name_eq(child, childname)) return of_fwnode_handle(child); return NULL; @@ -919,8 +957,10 @@ nargs, index, &of_args); if (ret < 0) return ret; - if (!args) + if (!args) { + of_node_put(of_args.np); return 0; + } args->nargs = of_args.args_count; args->fwnode = of_fwnode_handle(of_args.np); @@ -957,7 +997,7 @@ return NULL; /* Is this the "ports" node? If not, it's the port parent. */ - if (of_node_cmp(np->name, "ports")) + if (!of_node_name_eq(np, "ports")) return of_fwnode_handle(np); return of_fwnode_handle(of_get_next_parent(np)); @@ -1001,9 +1041,9 @@ } /** - * of_link_to_phandle - Add device link to supplier from supplier phandle - * @dev: consumer device - * @sup_np: phandle to supplier device tree node + * of_link_to_phandle - Add fwnode link to supplier from supplier phandle + * @con_np: consumer device tree node + * @sup_np: supplier device tree node * * Given a phandle to a supplier device tree node (@sup_np), this function * finds the device that owns the supplier device tree node and creates a @@ -1013,18 +1053,15 @@ * cases, it returns an error. * * Returns: - * - 0 if link successfully created to supplier - * - -EAGAIN if linking to the supplier should be reattempted + * - 0 if fwnode link successfully created to supplier * - -EINVAL if the supplier link is invalid and should not be created - * - -ENODEV if there is no device that corresponds to the supplier phandle + * - -ENODEV if struct device will never be create for supplier */ -static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, - u32 dl_flags) +static int of_link_to_phandle(struct device_node *con_np, + struct device_node *sup_np) { struct device *sup_dev; - int ret = 0; struct device_node *tmp_np = sup_np; - int is_populated; of_node_get(sup_np); /* @@ -1046,7 +1083,8 @@ } if (!sup_np) { - dev_dbg(dev, "Not linking to %pOFP - No device\n", tmp_np); + pr_debug("Not linking %pOFP to %pOFP - No device\n", + con_np, tmp_np); return -ENODEV; } @@ -1055,26 +1093,32 @@ * descendant nodes. By definition, a child node can't be a functional * dependency for the parent node. */ - if (of_is_ancestor_of(dev->of_node, sup_np)) { - dev_dbg(dev, "Not linking to %pOFP - is descendant\n", sup_np); + if (of_is_ancestor_of(con_np, sup_np)) { + pr_debug("Not linking %pOFP to %pOFP - is descendant\n", + con_np, sup_np); of_node_put(sup_np); return -EINVAL; } + + /* + * Don't create links to "early devices" that won't have struct devices + * created for them. + */ sup_dev = get_dev_from_fwnode(&sup_np->fwnode); - is_populated = of_node_check_flag(sup_np, OF_POPULATED); - of_node_put(sup_np); - if (!sup_dev && is_populated) { - /* Early device without struct device. */ - dev_dbg(dev, "Not linking to %pOFP - No struct device\n", - sup_np); + if (!sup_dev && + (of_node_check_flag(sup_np, OF_POPULATED) || + sup_np->fwnode.flags & FWNODE_FLAG_NOT_DEVICE)) { + pr_debug("Not linking %pOFP to %pOFP - No struct device\n", + con_np, sup_np); + of_node_put(sup_np); return -ENODEV; - } else if (!sup_dev) { - return -EAGAIN; } - if (!device_link_add(dev, sup_dev, dl_flags)) - ret = -EAGAIN; put_device(sup_dev); - return ret; + + fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np)); + of_node_put(sup_np); + + return 0; } /** @@ -1174,35 +1218,6 @@ return parse_suffix_prop_cells(np, prop_name, index, suffix, cells); \ } -static struct device_node *parse_msm_bus_name(struct device_node *np, - const char *prop_name, int index) -{ - static struct device_node *bus_dev_np; - - if (index || strcmp(prop_name, "qcom,msm-bus,name")) - return NULL; - - if (!bus_dev_np) - bus_dev_np = of_find_compatible_node(NULL, NULL, - "qcom,msm-bus-device"); - - return bus_dev_np; -} - -/* Force ignore of any qcom properties. */ -static struct device_node *parse_qcom_any(struct device_node *np, - const char *prop_name, int index) -{ - if (index || strncmp(prop_name, "qcom,", strlen("qcom,"))) - return NULL; - - /* - * Returning np will cause this property to be matched and then - * ignored. - */ - return np; -} - /** * struct supplier_bindings - Property parsing functions for suppliers * @@ -1222,9 +1237,9 @@ struct supplier_bindings { struct device_node *(*parse_prop)(struct device_node *np, const char *prop_name, int index); + bool optional; }; -DEFINE_SIMPLE_PROP(qcom_wrapper_core, "qcom,wrapper-core", NULL) DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells") DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells") @@ -1235,14 +1250,30 @@ DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) +DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") +DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) DEFINE_SIMPLE_PROP(pinctrl1, "pinctrl-1", NULL) DEFINE_SIMPLE_PROP(pinctrl2, "pinctrl-2", NULL) DEFINE_SIMPLE_PROP(pinctrl3, "pinctrl-3", NULL) +DEFINE_SIMPLE_PROP(pinctrl4, "pinctrl-4", NULL) +DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) +DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) +DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) +DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") + +static struct device_node *parse_gpios(struct device_node *np, + const char *prop_name, int index) +{ + if (!strcmp_suffix(prop_name, ",nr-gpios")) + return NULL; + + return parse_suffix_prop_cells(np, prop_name, index, "-gpios", + "#gpio-cells"); +} static struct device_node *parse_iommu_maps(struct device_node *np, const char *prop_name, int index) @@ -1253,26 +1284,69 @@ return of_parse_phandle(np, prop_name, (index * 4) + 1); } +static struct device_node *parse_gpio_compat(struct device_node *np, + const char *prop_name, int index) +{ + struct of_phandle_args sup_args; + + if (strcmp(prop_name, "gpio") && strcmp(prop_name, "gpios")) + return NULL; + + /* + * Ignore node with gpio-hog property since its gpios are all provided + * by its parent. + */ + if (of_find_property(np, "gpio-hog", NULL)) + return NULL; + + if (of_parse_phandle_with_args(np, prop_name, "#gpio-cells", index, + &sup_args)) + return NULL; + + return sup_args.np; +} + +static struct device_node *parse_interrupts(struct device_node *np, + const char *prop_name, int index) +{ + struct of_phandle_args sup_args; + + if (!IS_ENABLED(CONFIG_OF_IRQ) || IS_ENABLED(CONFIG_PPC)) + return NULL; + + if (strcmp(prop_name, "interrupts") && + strcmp(prop_name, "interrupts-extended")) + return NULL; + + return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np; +} + static const struct supplier_bindings of_supplier_bindings[] = { - { .parse_prop = parse_msm_bus_name, }, - { .parse_prop = parse_qcom_wrapper_core, }, - { .parse_prop = parse_qcom_any, }, { .parse_prop = parse_clocks, }, { .parse_prop = parse_interconnects, }, - { .parse_prop = parse_iommus, }, - { .parse_prop = parse_iommu_maps, }, + { .parse_prop = parse_iommus, .optional = true, }, + { .parse_prop = parse_iommu_maps, .optional = true, }, { .parse_prop = parse_mboxes, }, { .parse_prop = parse_io_channels, }, { .parse_prop = parse_interrupt_parent, }, - { .parse_prop = parse_dmas, }, + { .parse_prop = parse_dmas, .optional = true, }, { .parse_prop = parse_power_domains, }, { .parse_prop = parse_hwlocks, }, { .parse_prop = parse_extcon, }, + { .parse_prop = parse_nvmem_cells, }, { .parse_prop = parse_phys, }, + { .parse_prop = parse_wakeup_parent, }, { .parse_prop = parse_pinctrl0, }, { .parse_prop = parse_pinctrl1, }, { .parse_prop = parse_pinctrl2, }, { .parse_prop = parse_pinctrl3, }, + { .parse_prop = parse_pinctrl4, }, + { .parse_prop = parse_pinctrl5, }, + { .parse_prop = parse_pinctrl6, }, + { .parse_prop = parse_pinctrl7, }, + { .parse_prop = parse_pinctrl8, }, + { .parse_prop = parse_gpio_compat, }, + { .parse_prop = parse_interrupts, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_gpio, }, { .parse_prop = parse_gpios, }, @@ -1290,37 +1364,34 @@ * that list phandles to suppliers. If @prop_name isn't one, this function * doesn't do anything. * - * If @prop_name is one, this function attempts to create device links from the - * consumer device @dev to all the devices of the suppliers listed in - * @prop_name. + * If @prop_name is one, this function attempts to create fwnode links from the + * consumer device tree node @con_np to all the suppliers device tree nodes + * listed in @prop_name. * - * Any failed attempt to create a device link will NOT result in an immediate + * Any failed attempt to create a fwnode link will NOT result in an immediate * return. of_link_property() must create links to all the available supplier - * devices even when attempts to create a link to one or more suppliers fail. + * device tree nodes even when attempts to create a link to one or more + * suppliers fail. */ -static int of_link_property(struct device *dev, struct device_node *con_np, - const char *prop_name) +static int of_link_property(struct device_node *con_np, const char *prop_name) { struct device_node *phandle; const struct supplier_bindings *s = of_supplier_bindings; unsigned int i = 0; bool matched = false; int ret = 0; - u32 dl_flags; - - if (dev->of_node == con_np) - dl_flags = 0; - else - dl_flags = DL_FLAG_SYNC_STATE_ONLY; /* Do not stop at first failed link, link all available suppliers. */ while (!matched && s->parse_prop) { + if (s->optional && !fw_devlink_is_strict()) { + s++; + continue; + } + while ((phandle = s->parse_prop(con_np, prop_name, i))) { matched = true; i++; - if (of_link_to_phandle(dev, phandle, dl_flags) - == -EAGAIN) - ret = -EAGAIN; + of_link_to_phandle(con_np, phandle); of_node_put(phandle); } s++; @@ -1328,41 +1399,18 @@ return ret; } -static int of_link_to_suppliers(struct device *dev, - struct device_node *con_np) +static int of_fwnode_add_links(struct fwnode_handle *fwnode) { - struct device_node *child; struct property *p; - int ret = 0; + struct device_node *con_np = to_of_node(fwnode); + + if (!con_np) + return -EINVAL; for_each_property_of_node(con_np, p) - if (of_link_property(dev, con_np, p->name)) - ret = -ENODEV; + of_link_property(con_np, p->name); - for_each_available_child_of_node(con_np, child) - if (of_link_to_suppliers(dev, child) && !ret) - ret = -EAGAIN; - - return ret; -} - -#ifdef CONFIG_ARCH_ROCKCHIP -static bool of_devlink; -#else -static bool of_devlink = true; -#endif -core_param(of_devlink, of_devlink, bool, 0); - -static int of_fwnode_add_links(const struct fwnode_handle *fwnode, - struct device *dev) -{ - if (!of_devlink) - return 0; - - if (unlikely(!is_of_node(fwnode))) - return 0; - - return of_link_to_suppliers(dev, to_of_node(fwnode)); + return 0; } const struct fwnode_operations of_fwnode_ops = { @@ -1373,6 +1421,8 @@ .property_present = of_fwnode_property_present, .property_read_int_array = of_fwnode_property_read_int_array, .property_read_string_array = of_fwnode_property_read_string_array, + .get_name = of_fwnode_get_name, + .get_name_prefix = of_fwnode_get_name_prefix, .get_parent = of_fwnode_get_parent, .get_next_child_node = of_fwnode_get_next_child_node, .get_named_child_node = of_fwnode_get_named_child_node, -- Gitblit v1.6.2