From: Lucas Stach <dev@lynxeye.de>
To: barebox@lists.infradead.org
Subject: [PATCH 1/3] of: update of_parse_phandle_with_args to latest linux code
Date: Tue, 4 Jun 2013 09:29:09 +0200 [thread overview]
Message-ID: <1370330951-3548-1-git-send-email-dev@lynxeye.de> (raw)
Signed-off-by: Lucas Stach <dev@lynxeye.de>
---
drivers/of/base.c | 168 +++++++++++++++++++++++++++++++-----------------------
drivers/of/gpio.c | 9 ++-
include/of.h | 14 +++--
3 files changed, 111 insertions(+), 80 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 4241e65..b3d012c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -406,17 +406,19 @@ int of_property_write_u32_array(struct device_node *np,
}
/**
- * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
* @np: pointer to a device tree node containing a list
* @list_name: property name that contains a list
* @cells_name: property name that specifies phandles' arguments count
* @index: index of a phandle to parse out
- * @out_node: optional pointer to device_node struct pointer (will be filled)
- * @out_args: optional pointer to arguments pointer (will be filled)
+ * @out_args: optional pointer to output arguments structure (will be filled)
*
* This function is useful to parse lists of phandles and their arguments.
- * Returns 0 on success and fills out_node and out_args, on error returns
- * appropriate errno value.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
+ *
+ * Caller is responsible to call of_node_put() on the returned out_args->node
+ * pointer.
*
* Example:
*
@@ -433,92 +435,116 @@ int of_property_write_u32_array(struct device_node *np,
* }
*
* To get a device_node of the `node2' node you may call this:
- * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
*/
-int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
- const char *cells_name, int index,
- struct device_node **out_node,
- const void **out_args)
+static int __of_parse_phandle_with_args(const struct device_node *np,
+ const char *list_name,
+ const char *cells_name, int index,
+ struct of_phandle_args *out_args)
{
- int ret = -EINVAL;
- const __be32 *list;
- const __be32 *list_end;
- int size;
- int cur_index = 0;
+ const __be32 *list, *list_end;
+ int rc = 0, size, cur_index = 0;
+ uint32_t count = 0;
struct device_node *node = NULL;
- const void *args = NULL;
+ phandle phandle;
+ /* Retrieve the phandle list property */
list = of_get_property(np, list_name, &size);
- if (!list) {
- ret = -ENOENT;
- goto err0;
- }
+ if (!list)
+ return -ENOENT;
list_end = list + size / sizeof(*list);
+ /* Loop over the phandles until all the requested entry is found */
while (list < list_end) {
- const __be32 *cells;
- phandle phandle;
+ rc = -EINVAL;
+ count = 0;
+ /*
+ * If phandle is 0, then it is an empty entry with no
+ * arguments. Skip forward to the next entry.
+ */
phandle = be32_to_cpup(list++);
- args = list;
-
- /* one cell hole in the list = <>; */
- if (!phandle)
- goto next;
-
- node = of_find_node_by_phandle(phandle);
- if (!node) {
- pr_debug("%s: could not find phandle %d\n",
- np->full_name, phandle);
- goto err0;
+ if (phandle) {
+ /*
+ * Find the provider node and parse the #*-cells
+ * property to determine the argument length
+ */
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ pr_err("%s: could not find phandle\n",
+ np->full_name);
+ goto err;
+ }
+ if (of_property_read_u32(node, cells_name, &count)) {
+ pr_err("%s: could not get %s for %s\n",
+ np->full_name, cells_name,
+ node->full_name);
+ goto err;
+ }
+
+ /*
+ * Make sure that the arguments actually fit in the
+ * remaining property data length
+ */
+ if (list + count > list_end) {
+ pr_err("%s: arguments longer than property\n",
+ np->full_name);
+ goto err;
+ }
}
- cells = of_get_property(node, cells_name, &size);
- if (!cells || size != sizeof(*cells)) {
- pr_debug("%s: could not get %s for %s\n",
- np->full_name, cells_name, node->full_name);
- goto err1;
+ /*
+ * All of the error cases above bail out of the loop, so at
+ * this point, the parsing is successful. If the requested
+ * index matches, then fill the out_args structure and return,
+ * or return -ENOENT for an empty entry.
+ */
+ rc = -ENOENT;
+ if (cur_index == index) {
+ if (!phandle)
+ goto err;
+
+ if (out_args) {
+ int i;
+ if (WARN_ON(count > MAX_PHANDLE_ARGS))
+ count = MAX_PHANDLE_ARGS;
+ out_args->np = node;
+ out_args->args_count = count;
+ for (i = 0; i < count; i++)
+ out_args->args[i] = be32_to_cpup(list++);
+ }
+
+ /* Found it! return success */
+ return 0;
}
- list += be32_to_cpup(cells);
- if (list > list_end) {
- pr_debug("%s: insufficient arguments length\n",
- np->full_name);
- goto err1;
- }
-next:
- if (cur_index == index)
- break;
-
node = NULL;
- args = NULL;
+ list += count;
cur_index++;
}
- if (!node) {
- /*
- * args w/o node indicates that the loop above has stopped at
- * the 'hole' cell. Report this differently.
- */
- if (args)
- ret = -EEXIST;
- else
- ret = -ENOENT;
- goto err0;
- }
-
- if (out_node)
- *out_node = node;
- if (out_args)
- *out_args = args;
+ /*
+ * Unlock node before returning result; will be one of:
+ * -ENOENT : index is for empty phandle
+ * -EINVAL : parsing error on data
+ * [1..n] : Number of phandle (count mode; when index = -1)
+ */
+ rc = index < 0 ? cur_index : -ENOENT;
+ err:
+ return rc;
+}
- return 0;
-err1:
-err0:
- pr_debug("%s failed with status %d\n", __func__, ret);
- return ret;
+int of_parse_phandle_with_args(const struct device_node *np,
+ const char *list_name,
+ const char *cells_name, int index,
+ struct of_phandle_args *out_args)
+{
+ if (index < 0)
+ return -EINVAL;
+ return __of_parse_phandle_with_args(np, list_name, cells_name,
+ index, out_args);
}
-EXPORT_SYMBOL(of_parse_phandles_with_args);
+EXPORT_SYMBOL(of_parse_phandle_with_args);
/**
* of_machine_is_compatible - Test root of device tree for a given compatible value
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 83b72c0..cd3e1b7 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -9,17 +9,16 @@ int of_get_named_gpio(struct device_node *np,
const char *propname, int index)
{
int ret;
- struct device_node *gpio_np;
- const void *gpio_spec;
+ struct of_phandle_args gpio_spec;
- ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
- &gpio_np, &gpio_spec);
+ ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
+ &gpio_spec);
if (ret) {
pr_debug("%s: can't parse gpios property: %d\n", __func__, ret);
return -EINVAL;
}
- ret = gpio_get_num(gpio_np->device, be32_to_cpup(gpio_spec));
+ ret = gpio_get_num(gpio_spec.np->device, gpio_spec.args[0]);
if (ret < 0)
return ret;
diff --git a/include/of.h b/include/of.h
index 300b706..f00d1b4 100644
--- a/include/of.h
+++ b/include/of.h
@@ -32,6 +32,13 @@ struct device_node {
phandle phandle;
};
+#define MAX_PHANDLE_ARGS 8
+struct of_phandle_args {
+ struct device_node *np;
+ int args_count;
+ uint32_t args[MAX_PHANDLE_ARGS];
+};
+
struct of_device_id {
char *compatible;
unsigned long data;
@@ -130,10 +137,9 @@ static inline int of_property_write_u32(struct device_node *np,
const void *of_get_property(const struct device_node *np, const char *name,
int *lenp);
-int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
- const char *cells_name, int index,
- struct device_node **out_node,
- const void **out_args);
+int of_parse_phandle_with_args(const struct device_node *np,
+ const char *list_name, const char *cells_name,
+ int index, struct of_phandle_args *out_args);
int of_get_named_gpio(struct device_node *np,
const char *propname, int index);
--
1.8.2.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next reply other threads:[~2013-06-04 7:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-04 7:29 Lucas Stach [this message]
2013-06-04 7:29 ` [PATCH 2/3] of: import of_property_match_string from Linux Lucas Stach
2013-06-04 7:29 ` [PATCH 3/3] clk: add clock lookup from devicetree Lucas Stach
2013-06-05 6:47 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370330951-3548-1-git-send-email-dev@lynxeye.de \
--to=dev@lynxeye.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox