From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from ns.km20343-01.keymachine.de ([84.19.182.79] helo=km20343-01.keymachine.de) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ujlgl-0004V6-Am for barebox@lists.infradead.org; Tue, 04 Jun 2013 07:29:56 +0000 Received: from antimon.pengutronix.de (port-212-202-120-50.static.qsc.de [212.202.120.50]) by km20343-01.keymachine.de (Postfix) with ESMTPA id 290B57D416E for ; Tue, 4 Jun 2013 09:29:15 +0200 (CEST) From: Lucas Stach Date: Tue, 4 Jun 2013 09:29:09 +0200 Message-Id: <1370330951-3548-1-git-send-email-dev@lynxeye.de> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH 1/3] of: update of_parse_phandle_with_args to latest linux code To: barebox@lists.infradead.org Signed-off-by: Lucas Stach --- 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