From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
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