* [RFC 1/8] gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags()
2011-11-09 1:19 [RFC 0/8] Initial DT clock bindings Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-12-21 10:22 ` Michal Simek
2011-11-09 1:19 ` [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data Grant Likely
` (2 subsequent siblings)
3 siblings, 1 reply; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring
Cc: linux-kernel, Grant Likely, Michal Simek
of_reset_gpio_handle() is largely a cut-and-paste copy of
of_get_named_gpio_flags(). There really isn't any reason for the
split, so this patch deletes the duplicate function
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Michal Simek <monstr@monstr.eu>
---
arch/microblaze/kernel/reset.c | 43 +--------------------------------------
1 files changed, 2 insertions(+), 41 deletions(-)
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index bd8ccab..88a0163 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -19,50 +19,11 @@
static int handle; /* reset pin handle */
static unsigned int reset_val;
-static int of_reset_gpio_handle(void)
-{
- int ret; /* variable which stored handle reset gpio pin */
- struct device_node *root; /* root node */
- struct device_node *gpio; /* gpio node */
- struct gpio_chip *gc;
- u32 flags;
- const void *gpio_spec;
-
- /* find out root node */
- root = of_find_node_by_path("/");
-
- /* give me handle for gpio node to be possible allocate pin */
- ret = of_parse_phandles_with_args(root, "hard-reset-gpios",
- "#gpio-cells", 0, &gpio, &gpio_spec);
- if (ret) {
- pr_debug("%s: can't parse gpios property\n", __func__);
- goto err0;
- }
-
- gc = of_node_to_gpiochip(gpio);
- if (!gc) {
- pr_debug("%s: gpio controller %s isn't registered\n",
- root->full_name, gpio->full_name);
- ret = -ENODEV;
- goto err1;
- }
-
- ret = gc->of_xlate(gc, root, gpio_spec, &flags);
- if (ret < 0)
- goto err1;
-
- ret += gc->base;
-err1:
- of_node_put(gpio);
-err0:
- pr_debug("%s exited with status %d\n", __func__, ret);
- return ret;
-}
-
void of_platform_reset_gpio_probe(void)
{
int ret;
- handle = of_reset_gpio_handle();
+ handle = of_get_named_gpio(of_find_node_by_path("/"),
+ "hard-reset-gpios", 0);
if (!gpio_is_valid(handle)) {
printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n",
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [RFC 1/8] gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags()
2011-11-09 1:19 ` [RFC 1/8] gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags() Grant Likely
@ 2011-12-21 10:22 ` Michal Simek
2012-01-04 18:30 ` Grant Likely
0 siblings, 1 reply; 34+ messages in thread
From: Michal Simek @ 2011-12-21 10:22 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
linux-kernel
Grant Likely wrote:
> of_reset_gpio_handle() is largely a cut-and-paste copy of
> of_get_named_gpio_flags(). There really isn't any reason for the
> split, so this patch deletes the duplicate function
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> Cc: Michal Simek <monstr@monstr.eu>
> ---
> arch/microblaze/kernel/reset.c | 43 +--------------------------------------
> 1 files changed, 2 insertions(+), 41 deletions(-)
Sorry for taking to long.
Tested and applied to microblaze tree.
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 1/8] gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags()
2011-12-21 10:22 ` Michal Simek
@ 2012-01-04 18:30 ` Grant Likely
[not found] ` <20120104183057.GU15503-e0URQFbLeQY2iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
0 siblings, 1 reply; 34+ messages in thread
From: Grant Likely @ 2012-01-04 18:30 UTC (permalink / raw)
To: Michal Simek
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
linux-kernel
On Wed, Dec 21, 2011 at 11:22:34AM +0100, Michal Simek wrote:
> Grant Likely wrote:
> >of_reset_gpio_handle() is largely a cut-and-paste copy of
> >of_get_named_gpio_flags(). There really isn't any reason for the
> >split, so this patch deletes the duplicate function
> >
> >Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> >Cc: Michal Simek <monstr@monstr.eu>
> >---
> > arch/microblaze/kernel/reset.c | 43 +--------------------------------------
> > 1 files changed, 2 insertions(+), 41 deletions(-)
>
> Sorry for taking to long.
>
> Tested and applied to microblaze tree.
I'd rather take this one through the gpio tree if that is okay.
g.
>
> Thanks,
> Michal
>
> --
> Michal Simek, Ing. (M.Eng)
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
> Microblaze U-BOOT custodian
^ permalink raw reply [flat|nested] 34+ messages in thread
* [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data
2011-11-09 1:19 [RFC 0/8] Initial DT clock bindings Grant Likely
2011-11-09 1:19 ` [RFC 1/8] gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags() Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-11-14 3:59 ` Shawn Guo
2011-11-21 15:50 ` Shawn Guo
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 1:19 ` [RFC 8/8] dt/arm: versatile add clock parsing Grant Likely
3 siblings, 2 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring
Cc: linux-kernel, Grant Likely
of_parse_phandle_with_args() needs to return quite a bit of data. Rather
than making each datum a separate **out_ argument, this patch creates
struct of_phandle_args to contain all the returned data and reworks the
user of the function. This patch also enables of_parse_phandle_with_args()
to return the device node pointer for the phandle node.
This patch also ends up being fairly major surgery to
of_parse_handle_with_args(). The existing structure didn't work well
when extending to use of_phandle_args, and I discovered bugs during testing.
I also took the opportunity to rename the function to be like the
existing of_parse_phandle().
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/of/base.c | 136 +++++++++++++++++++++++--------------------
drivers/of/gpio.c | 43 ++++++--------
include/asm-generic/gpio.h | 5 +-
include/linux/of.h | 11 +++-
include/linux/of_gpio.h | 10 ++-
5 files changed, 110 insertions(+), 95 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 9b6588e..7fe8397 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -824,17 +824,16 @@ of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
EXPORT_SYMBOL(of_parse_phandle);
/**
- * 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.
*
* Example:
*
@@ -851,94 +850,105 @@ EXPORT_SYMBOL(of_parse_phandle);
* }
*
* 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", 2, &args);
*/
-int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
+int of_parse_phandle_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)
+ 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 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;
+ if (!list)
goto err0;
- }
list_end = list + size / sizeof(*list);
+ /*
+ * Loop over all the entries in the list, parsing the #cells property
+ * for each one to determine how long each argument list is
+ */
while (list < list_end) {
- const __be32 *cells;
- phandle phandle;
+ count = 0;
+ /*
+ * If phandle is null, then it is an empty entry with no args,
+ * 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\n",
- np->full_name);
- goto err0;
- }
+ if (phandle) {
+ /*
+ * Find the provider node and parse the #*-cells
+ * property to determine how long the arguements are
+ */
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ pr_debug("%s: could not find phandle\n",
+ np->full_name);
+ ret = -EINVAL;
+ goto err0;
+ }
+ if (of_property_read_u32(node, cells_name, &count)) {
+ pr_debug("%s: could not get %s for %s\n",
+ np->full_name, cells_name,
+ node->full_name);
+ ret = -EINVAL;
+ goto err1;
+ }
- 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;
+ /*
+ * Make sure that the arguments actually fit in the
+ * remaining property data length
+ */
+ if (list + count > list_end) {
+ pr_debug("%s: insufficient arguments length\n",
+ np->full_name);
+ goto err1;
+ }
}
- 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)
+ /*
+ * All of the error cases in the loop bail out to the err
+ * labels, so at this point, the parsing was successful, but
+ * it might be an empty entry
+ */
+ if (cur_index == index) {
+ ret = phandle ? 0 : -ENOENT;
break;
+ }
of_node_put(node);
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;
+ if (!node)
goto err0;
- }
-
- if (out_node)
- *out_node = node;
- if (out_args)
- *out_args = args;
+ 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++);
+ }
return 0;
-err1:
+
+ err1:
of_node_put(node);
-err0:
+ err0:
pr_debug("%s failed with status %d\n", __func__, ret);
return ret;
}
-EXPORT_SYMBOL(of_parse_phandles_with_args);
+EXPORT_SYMBOL(of_parse_phandle_with_args);
/**
* prom_add_property - Add a property to a node
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index ef0105f..244a2b0 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -35,32 +35,27 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
int index, enum of_gpio_flags *flags)
{
int ret;
- struct device_node *gpio_np;
struct gpio_chip *gc;
- int size;
- const void *gpio_spec;
- const __be32 *gpio_cells;
+ struct of_phandle_args gpiospec;
- 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,
+ &gpiospec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
goto err0;
}
- gc = of_node_to_gpiochip(gpio_np);
+ gc = of_node_to_gpiochip(gpiospec.np);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
- np->full_name, gpio_np->full_name);
+ np->full_name, gpiospec.np->full_name);
ret = -ENODEV;
goto err1;
}
- gpio_cells = of_get_property(gpio_np, "#gpio-cells", &size);
- if (!gpio_cells || size != sizeof(*gpio_cells) ||
- be32_to_cpup(gpio_cells) != gc->of_gpio_n_cells) {
+ if (gpiospec.args_count != gc->of_gpio_n_cells) {
pr_debug("%s: wrong #gpio-cells for %s\n",
- np->full_name, gpio_np->full_name);
+ np->full_name, gpiospec.np->full_name);
ret = -EINVAL;
goto err1;
}
@@ -69,13 +64,13 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
if (flags)
*flags = 0;
- ret = gc->of_xlate(gc, np, gpio_spec, flags);
+ ret = gc->of_xlate(gc, &gpiospec, flags);
if (ret < 0)
goto err1;
ret += gc->base;
err1:
- of_node_put(gpio_np);
+ of_node_put(gpiospec.np);
err0:
pr_debug("%s exited with status %d\n", __func__, ret);
return ret;
@@ -105,8 +100,8 @@ unsigned int of_gpio_count(struct device_node *np)
do {
int ret;
- ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells",
- cnt, NULL, NULL);
+ ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells",
+ cnt, NULL);
/* A hole in the gpios = <> counts anyway. */
if (ret < 0 && ret != -EEXIST)
break;
@@ -127,12 +122,9 @@ EXPORT_SYMBOL(of_gpio_count);
* gpio chips. This function performs only one sanity check: whether gpio
* is less than ngpios (that is specified in the gpio_chip).
*/
-int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags)
+int of_gpio_simple_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
{
- const __be32 *gpio = gpio_spec;
- const u32 n = be32_to_cpup(gpio);
-
/*
* We're discouraging gpio_cells < 2, since that way you'll have to
* write your own xlate function (that will have to retrive the GPIO
@@ -144,13 +136,16 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
return -EINVAL;
}
- if (n > gc->ngpio)
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+ return -EINVAL;
+
+ if (gpiospec->args[0] > gc->ngpio)
return -EINVAL;
if (flags)
- *flags = be32_to_cpu(gpio[1]);
+ *flags = gpiospec->args[1];
- return n;
+ return gpiospec->args[0];
}
EXPORT_SYMBOL(of_gpio_simple_xlate);
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 8c86210..1a2d518 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/of.h>
#ifdef CONFIG_GPIOLIB
@@ -128,8 +129,8 @@ struct gpio_chip {
*/
struct device_node *of_node;
int of_gpio_n_cells;
- int (*of_xlate)(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags);
+ int (*of_xlate)(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags);
#endif
};
diff --git a/include/linux/of.h b/include/linux/of.h
index 4948552..566deab 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -222,6 +222,13 @@ extern const void *of_get_property(const struct device_node *node,
#define for_each_property(pp, properties) \
for (pp = properties; pp != NULL; pp = pp->next)
+#define MAX_PHANDLE_ARGS 8
+struct of_phandle_args {
+ struct device_node *np;
+ int args_count;
+ uint32_t args[MAX_PHANDLE_ARGS];
+};
+
extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
@@ -230,9 +237,9 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
extern struct device_node *of_parse_phandle(struct device_node *np,
const char *phandle_name,
int index);
-extern int of_parse_phandles_with_args(struct device_node *np,
+extern int of_parse_phandle_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);
+ struct of_phandle_args *out_args);
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem);
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 52280a2..b254052 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/gpio.h>
+#include <linux/of.h>
struct device_node;
@@ -57,8 +58,9 @@ extern int of_mm_gpiochip_add(struct device_node *np,
extern void of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
-extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags);
+extern int of_gpio_simple_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags);
#else /* CONFIG_OF_GPIO */
@@ -75,8 +77,8 @@ static inline unsigned int of_gpio_count(struct device_node *np)
}
static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
- struct device_node *np,
- const void *gpio_spec, u32 *flags)
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
{
return -ENOSYS;
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data
2011-11-09 1:19 ` [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data Grant Likely
@ 2011-11-14 3:59 ` Shawn Guo
[not found] ` <20111114035908.GA10236-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-11-21 15:50 ` Shawn Guo
1 sibling, 1 reply; 34+ messages in thread
From: Shawn Guo @ 2011-11-14 3:59 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
linux-kernel
Hi Grant,
On Tue, Nov 08, 2011 at 06:19:38PM -0700, Grant Likely wrote:
[...]
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 4948552..566deab 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -222,6 +222,13 @@ extern const void *of_get_property(const struct device_node *node,
> #define for_each_property(pp, properties) \
> for (pp = properties; pp != NULL; pp = pp->next)
>
> +#define MAX_PHANDLE_ARGS 8
> +struct of_phandle_args {
> + struct device_node *np;
> + int args_count;
> + uint32_t args[MAX_PHANDLE_ARGS];
> +};
> +
I'm seeing a bunch of warnings like the one below when compiling imx
with the series. And moving the definition to somewhere before
'#include <asm/prom.h>' in linux/of.h removes the warnings for me.
CC arch/arm/kernel/devtree.o
In file included from arch/arm/plat-mxc/include/mach/irqs.h:14:0,
from arch/arm/include/asm/irq.h:4,
from arch/arm/include/asm/prom.h:17,
from include/linux/of.h:133,
from arch/arm/kernel/devtree.c:17:
include/asm-generic/gpio.h:133:24: warning: ‘struct of_phandle_args’ declared inside parameter list
include/asm-generic/gpio.h:133:24: warning: its scope is only this definition or declaration, which is probably not what you want
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data
2011-11-09 1:19 ` [RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data Grant Likely
2011-11-14 3:59 ` Shawn Guo
@ 2011-11-21 15:50 ` Shawn Guo
1 sibling, 0 replies; 34+ messages in thread
From: Shawn Guo @ 2011-11-21 15:50 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
linux-kernel
On Tue, Nov 08, 2011 at 06:19:38PM -0700, Grant Likely wrote:
[...]
> /**
> - * 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.
> *
> * Example:
> *
> @@ -851,94 +850,105 @@ EXPORT_SYMBOL(of_parse_phandle);
> * }
> *
> * 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", 2, &args);
Not introduced by this patch, but if I read the code correctly,
the fourth parameter should be 1?
> */
> -int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
> +int of_parse_phandle_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)
> + 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 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;
> + if (!list)
> goto err0;
> - }
> list_end = list + size / sizeof(*list);
>
> + /*
> + * Loop over all the entries in the list, parsing the #cells property
> + * for each one to determine how long each argument list is
> + */
> while (list < list_end) {
> - const __be32 *cells;
> - phandle phandle;
> + count = 0;
>
> + /*
> + * If phandle is null, then it is an empty entry with no args,
> + * 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\n",
> - np->full_name);
> - goto err0;
> - }
> + if (phandle) {
> + /*
> + * Find the provider node and parse the #*-cells
> + * property to determine how long the arguements are
> + */
> + node = of_find_node_by_phandle(phandle);
> + if (!node) {
> + pr_debug("%s: could not find phandle\n",
> + np->full_name);
> + ret = -EINVAL;
> + goto err0;
> + }
> + if (of_property_read_u32(node, cells_name, &count)) {
> + pr_debug("%s: could not get %s for %s\n",
> + np->full_name, cells_name,
> + node->full_name);
> + ret = -EINVAL;
> + goto err1;
> + }
>
> - 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;
> + /*
> + * Make sure that the arguments actually fit in the
> + * remaining property data length
> + */
> + if (list + count > list_end) {
> + pr_debug("%s: insufficient arguments length\n",
> + np->full_name);
> + goto err1;
> + }
> }
>
> - 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)
> + /*
> + * All of the error cases in the loop bail out to the err
> + * labels, so at this point, the parsing was successful, but
> + * it might be an empty entry
> + */
> + if (cur_index == index) {
> + ret = phandle ? 0 : -ENOENT;
We have some return code here ...
> break;
> + }
>
> of_node_put(node);
> 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;
> + if (!node)
> goto err0;
> - }
> -
> - if (out_node)
> - *out_node = node;
> - if (out_args)
> - *out_args = args;
>
> + 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++);
> + }
> return 0;
... should this be "return ret"?
> -err1:
> +
> + err1:
> of_node_put(node);
> -err0:
> + err0:
> pr_debug("%s failed with status %d\n", __func__, ret);
> return ret;
> }
> -EXPORT_SYMBOL(of_parse_phandles_with_args);
> +EXPORT_SYMBOL(of_parse_phandle_with_args);
>
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 34+ messages in thread
[parent not found: <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>]
* [RFC 2/8] gpio/powerpc: Eliminate duplication of of_get_named_gpio_flags()
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
@ 2011-11-09 1:19 ` Grant Likely
2011-11-09 1:19 ` [RFC 4/8] of: Add device tree selftests Grant Likely
` (3 subsequent siblings)
4 siblings, 0 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sascha Hauer,
Rob Herring
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA
A large chunk of qe_pin_request() is unnecessarily cut-and-paste
directly from of_get_named_gpio_flags(). This patch cuts out the
duplicate code and replaces it with a call to of_get_gpio().
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Cc: Kumar Gala <galak-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
---
arch/powerpc/sysdev/qe_lib/gpio.c | 42 +++++++-----------------------------
1 files changed, 8 insertions(+), 34 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
index e23f23c..521e67a 100644
--- a/arch/powerpc/sysdev/qe_lib/gpio.c
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -139,14 +139,10 @@ struct qe_pin {
struct qe_pin *qe_pin_request(struct device_node *np, int index)
{
struct qe_pin *qe_pin;
- struct device_node *gpio_np;
struct gpio_chip *gc;
struct of_mm_gpio_chip *mm_gc;
struct qe_gpio_chip *qe_gc;
int err;
- int size;
- const void *gpio_spec;
- const u32 *gpio_cells;
unsigned long flags;
qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL);
@@ -155,45 +151,25 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
return ERR_PTR(-ENOMEM);
}
- err = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
- &gpio_np, &gpio_spec);
- if (err) {
- pr_debug("%s: can't parse gpios property\n", __func__);
+ err = of_get_gpio(np, index);
+ if (err < 0)
+ goto err0;
+ gc = gpio_to_chip(err);
+ if (WARN_ON(!gc))
goto err0;
- }
- if (!of_device_is_compatible(gpio_np, "fsl,mpc8323-qe-pario-bank")) {
+ if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) {
pr_debug("%s: tried to get a non-qe pin\n", __func__);
err = -EINVAL;
- goto err1;
- }
-
- gc = of_node_to_gpiochip(gpio_np);
- if (!gc) {
- pr_debug("%s: gpio controller %s isn't registered\n",
- np->full_name, gpio_np->full_name);
- err = -ENODEV;
- goto err1;
- }
-
- gpio_cells = of_get_property(gpio_np, "#gpio-cells", &size);
- if (!gpio_cells || size != sizeof(*gpio_cells) ||
- *gpio_cells != gc->of_gpio_n_cells) {
- pr_debug("%s: wrong #gpio-cells for %s\n",
- np->full_name, gpio_np->full_name);
- err = -EINVAL;
- goto err1;
+ goto err0;
}
- err = gc->of_xlate(gc, np, gpio_spec, NULL);
- if (err < 0)
- goto err1;
-
mm_gc = to_of_mm_gpio_chip(gc);
qe_gc = to_qe_gpio_chip(mm_gc);
spin_lock_irqsave(&qe_gc->lock, flags);
+ err -= gc->base;
if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) {
qe_pin->controller = qe_gc;
qe_pin->num = err;
@@ -206,8 +182,6 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
if (!err)
return qe_pin;
-err1:
- of_node_put(gpio_np);
err0:
kfree(qe_pin);
pr_debug("%s failed with status %d\n", __func__, err);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [RFC 4/8] of: Add device tree selftests
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 1:19 ` [RFC 2/8] gpio/powerpc: Eliminate duplication of of_get_named_gpio_flags() Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-11-09 1:19 ` [RFC 5/8] of: Add of_property_match_string() to find index into a string list Grant Likely
` (2 subsequent siblings)
4 siblings, 0 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sascha Hauer,
Rob Herring
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add some runtime test cases for the library of device tree parsing functions.
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
arch/arm/boot/dts/testcases/tests-phandle.dtsi | 32 ++++++
arch/arm/boot/dts/testcases/tests.dtsi | 1 +
arch/arm/boot/dts/versatile-pb.dts | 2 +
drivers/of/Kconfig | 9 ++
drivers/of/Makefile | 1 +
drivers/of/selftest.c | 128 ++++++++++++++++++++++++
6 files changed, 173 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/testcases/tests-phandle.dtsi
create mode 100644 arch/arm/boot/dts/testcases/tests.dtsi
create mode 100644 drivers/of/selftest.c
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
new file mode 100644
index 0000000..d26fe99
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
@@ -0,0 +1,32 @@
+
+/ {
+ testcase-data {
+ phandle-tests {
+ provider1: provider1 {
+ #phandle-cells = <1>;
+ };
+
+ provider2: provider2 {
+ #phandle-cells = <2>;
+ };
+
+ provider3: provider3 {
+ #phandle-cells = <3>;
+ };
+
+ consumer-a {
+ phandle-list = <&provider1 1>,
+ <&provider2 2 0>,
+ <0>,
+ <&provider3 4 4 3>,
+ <&provider2 5 100>,
+ <&provider1 6>;
+ phandle-list-names = "first", "second", "third";
+
+ phandle-list-bad-phandle = <12345678 0 0>;
+ phandle-list-bad-args = <&provider2 1 0>,
+ <&provider3 0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
new file mode 100644
index 0000000..a7c5067
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests.dtsi
@@ -0,0 +1 @@
+/include/ "tests-phandle.dtsi"
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 8a614e3..1664610 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -46,3 +46,5 @@
};
};
};
+
+/include/ "testcases/tests.dtsi"
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index cac63c9..268163d 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -15,6 +15,15 @@ config PROC_DEVICETREE
an image of the device tree that the kernel copies from Open
Firmware or other boot firmware. If unsure, say Y here.
+config OF_SELFTEST
+ bool "Device Tree Runtime self tests"
+ help
+ This option builds in test cases for the device tree infrastructure
+ that are executed one at boot time, and the results dumped to the
+ console.
+
+ If unsure, say N here, but this option is safe to enable.
+
config OF_FLATTREE
bool
select DTC
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index dccb117..a73f5a5 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_NET) += of_net.o
obj-$(CONFIG_OF_SPI) += of_spi.o
+obj-$(CONFIG_OF_SELFTEST) += selftest.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
new file mode 100644
index 0000000..dc3b215
--- /dev/null
+++ b/drivers/of/selftest.c
@@ -0,0 +1,128 @@
+/*
+ * Self tests for device tree subsystem
+ */
+
+#define pr_fmt(fmt) "### %s(): " fmt, __func__
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+static bool selftest_passed = true;
+#define selftest(result, fmt, ...) { \
+ selftest_passed &= (result); \
+ if (!(result)) \
+ pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
+}
+
+static void __init of_selftest_parse_phandle_with_args(void)
+{
+ struct device_node *np;
+ struct of_phandle_args args;
+ int rc, i;
+ bool passed_all = true;
+
+ pr_info("start\n");
+ np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
+ if (!np) {
+ pr_err("No testcase data in device tree\n");
+ return;
+ }
+
+ for (i = 0; i < 7; i++) {
+ bool passed = true;
+ rc = of_parse_phandle_with_args(np, "phandle-list",
+ "#phandle-cells", i, &args);
+
+ /* Test the values from tests-phandle.dtsi */
+ switch (i) {
+ case 0:
+ passed &= !rc;
+ passed &= (args.args_count == 1);
+ passed &= (args.args[0] == (i + 1));
+ break;
+ case 1:
+ passed &= !rc;
+ passed &= (args.args_count == 2);
+ passed &= (args.args[0] == (i + 1));
+ passed &= (args.args[1] == 0);
+ break;
+ case 2:
+ passed &= (rc == -ENOENT);
+ break;
+ case 3:
+ passed &= !rc;
+ passed &= (args.args_count == 3);
+ passed &= (args.args[0] == (i + 1));
+ passed &= (args.args[1] == 4);
+ passed &= (args.args[2] == 3);
+ break;
+ case 4:
+ passed &= !rc;
+ passed &= (args.args_count == 2);
+ passed &= (args.args[0] == (i + 1));
+ passed &= (args.args[1] == 100);
+ break;
+ case 5:
+ passed &= !rc;
+ passed &= (args.args_count == 1);
+ passed &= (args.args[0] == (i + 1));
+ break;
+ case 6:
+ passed &= (rc == -EINVAL);
+ break;
+ default:
+ passed = false;
+ }
+
+ if (!passed) {
+ int j;
+ pr_err("index %i - data error on node %s rc=%i regs=[",
+ i, args.np->full_name, rc);
+ for (j = 0; j < args.args_count; j++)
+ printk(" %i", args.args[j]);
+ printk(" ]\n");
+ }
+
+ if (!passed)
+ passed_all = false;
+ }
+
+ /* Check for missing list property */
+ rc = of_parse_phandle_with_args(np, "phandle-list-missing",
+ "#phandle-cells", 0, &args);
+ passed_all &= (rc == -EINVAL);
+
+ /* Check for missing cells property */
+ rc = of_parse_phandle_with_args(np, "phandle-list",
+ "#phandle-cells-missing", 0, &args);
+ passed_all &= (rc == -EINVAL);
+
+ /* Check for bad phandle in list */
+ rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
+ "#phandle-cells", 0, &args);
+ passed_all &= (rc == -EINVAL);
+
+ /* Check for incorrectly formed argument list */
+ rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
+ "#phandle-cells", 1, &args);
+ passed_all &= (rc == -EINVAL);
+
+ pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
+}
+
+static int __init of_selftest(void)
+{
+ pr_info("start of selftest\n");
+ of_selftest_parse_phandle_with_args();
+ pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
+ return 0;
+}
+late_initcall(of_selftest);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [RFC 5/8] of: Add of_property_match_string() to find index into a string list
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 1:19 ` [RFC 2/8] gpio/powerpc: Eliminate duplication of of_get_named_gpio_flags() Grant Likely
2011-11-09 1:19 ` [RFC 4/8] of: Add device tree selftests Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-11-09 1:19 ` [RFC 6/8] of: add clock providers Grant Likely
2011-11-09 1:19 ` [RFC 7/8] arm/clkdev: lookup clocks from OF " Grant Likely
4 siblings, 0 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sascha Hauer,
Rob Herring
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add a helper function for finding the index of a string in a string
list property. This helper is useful for bindings that use a separate
*-name property for attaching names to tuples in another property such
as 'reg' or 'gpios'.
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
arch/arm/boot/dts/testcases/tests-phandle.dtsi | 2 +
drivers/of/base.c | 36 ++++++++++++++++++++++++
drivers/of/selftest.c | 29 +++++++++++++++++++
include/linux/of.h | 3 ++
4 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
index d26fe99..a464e48 100644
--- a/arch/arm/boot/dts/testcases/tests-phandle.dtsi
+++ b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
@@ -26,6 +26,8 @@
phandle-list-bad-phandle = <12345678 0 0>;
phandle-list-bad-args = <&provider2 1 0>,
<&provider3 0>;
+ empty-property;
+ unterminated-string = [40 41 42 43];
};
};
};
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 7fe8397..7d4f8b9 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -761,6 +761,42 @@ int of_property_read_string_index(struct device_node *np, const char *propname,
}
EXPORT_SYMBOL_GPL(of_property_read_string_index);
+/**
+ * of_property_match_string() - Find string in a list and return index
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ */
+int of_property_match_string(struct device_node *np, const char *propname,
+ const char *string)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ size_t l;
+ int i;
+ const char *p, *end;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ p = prop->value;
+ end = p + prop->length;
+
+ for (i = 0; p < end; i++, p += l) {
+ l = strlen(p) + 1;
+ if (p + l > end)
+ return -EILSEQ;
+ pr_debug("comparing %s with %s\n", string, p);
+ if (strcmp(string, p) == 0)
+ return i; /* Found it; return index */
+ }
+ return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_match_string);
/**
* of_property_count_strings - Find and return the number of strings from a
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index dc3b215..851e0cd 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -118,10 +118,39 @@ static void __init of_selftest_parse_phandle_with_args(void)
pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
}
+static void __init of_selftest_property_match_string(void)
+{
+ struct device_node *np;
+ int rc;
+
+ pr_info("start\n");
+ np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
+ if (!np) {
+ pr_err("No testcase data in device tree\n");
+ return;
+ }
+
+ rc = of_property_match_string(np, "phandle-list-names", "first");
+ selftest(rc == 0, "first expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "second");
+ selftest(rc == 1, "second expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "third");
+ selftest(rc == 2, "third expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "fourth");
+ selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
+ rc = of_property_match_string(np, "missing-property", "blah");
+ selftest(rc == -EINVAL, "missing property; rc=%i", rc);
+ rc = of_property_match_string(np, "empty-property", "blah");
+ selftest(rc == -ENODATA, "empty property; rc=%i", rc);
+ rc = of_property_match_string(np, "unterminated-string", "blah");
+ selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
+}
+
static int __init of_selftest(void)
{
pr_info("start of selftest\n");
of_selftest_parse_phandle_with_args();
+ of_selftest_property_match_string();
pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
return 0;
}
diff --git a/include/linux/of.h b/include/linux/of.h
index 566deab..7bdfc15 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -211,6 +211,9 @@ extern int of_property_read_string(struct device_node *np,
extern int of_property_read_string_index(struct device_node *np,
const char *propname,
int index, const char **output);
+extern int of_property_match_string(struct device_node *np,
+ const char *propname,
+ const char *string);
extern int of_property_count_strings(struct device_node *np,
const char *propname);
extern int of_device_is_compatible(const struct device_node *device,
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [RFC 6/8] of: add clock providers
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
` (2 preceding siblings ...)
2011-11-09 1:19 ` [RFC 5/8] of: Add of_property_match_string() to find index into a string list Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-11-09 18:39 ` Tony Lindgren
[not found] ` <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 1:19 ` [RFC 7/8] arm/clkdev: lookup clocks from OF " Grant Likely
4 siblings, 2 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sascha Hauer,
Rob Herring
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
of_clk_get function to allow platforms to retrieve clock data from the
device tree.
Platform register a provider through of_clk_add_provider, which will be
called when a device references the provider's OF node for a clock
reference.
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
.../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
drivers/of/Kconfig | 6 +
drivers/of/Makefile | 1 +
drivers/of/clock.c | 129 ++++++++++++++++++++
include/linux/of_clk.h | 37 ++++++
5 files changed, 282 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
create mode 100644 drivers/of/clock.c
create mode 100644 include/linux/of_clk.h
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
new file mode 100644
index 0000000..4770c7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -0,0 +1,109 @@
+This binding is a work-in-progress, and are based on some experimental
+work by benh[1].
+
+Sources of clock signal can be represented by any node in the device
+tree. Those nodes are designated as clock providers. Clock consumer
+nodes use a phandle and clock specifier pair to connect clock provider
+outputs to clock inputs. Similar to the gpio specifiers, a clock
+specifier is an array of one more more cells identifying the clock
+output on a device. The length of a clock specifier is defined by the
+value of a #clock-cells property in the clock provider node.
+
+[1] http://patchwork.ozlabs.org/patch/31551/
+
+==Clock providers==
+
+Required properties:
+#clock-cells: Number of cells in a clock specifier; typically will be
+ set to 1
+
+Optional properties:
+clock-output-name: Recommended to be a list of strings of clock output signal
+ names indexed by the first cell in the clock specifier.
+ However, the meaning of clock-output-names is domain
+ specific to the clock provider, and is only provided to
+ encourage using the same meaning for the majority of clock
+ providers. This format may not work for clock providers
+ using a complex clock specifier format. In those cases it
+ is recommended to omit this property and create a binding
+ specific names property.
+
+ Clock consumer nodes must never directly reference
+ the provider's clock-output-names property.
+
+For example:
+
+ oscillator {
+ #clock-cells = <1>;
+ clock-output-name = "ckil", "ckih";
+ };
+
+- this node defines a device with two clock outputs, the first named
+ "ckil" and the second named "ckih". Consumer nodes always reference
+ clocks by index. The names should reflect the clock output signal
+ names for the device.
+
+==Clock consumers==
+
+Required properties:
+clock-input: List of phandle and clock specifier pairs, one pair
+ for each clock input to the device.
+clock-input-name: List of clock input name strings sorted in the same
+ order as the clock-input property. Consumers drivers
+ will use clock-input-name to match clock input names
+ with clock-input specifiers.
+
+For example:
+
+ uart {
+ clock-input = <&osc 1> <&ref 0>;
+ clock-input-name = "baud", "register";
+ };
+
+
+This represents a device with two clock inputs, named "baud" and "register".
+The baud clock is connected to output 1 of the &osc device, and the register
+clock is connected to output 0 of the &ref.
+
+==Example==
+
+ /* external oscillator */
+ osc: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <1>;
+ frequency = <32678>;
+ clock-output-name = "osc";
+ };
+
+ /* phase-locked-loop device, generates a higher frequency clock
+ * from the external oscillator reference */
+ pll: pll {
+ compatible = "some-pll-interface"
+ #clock-cells = <1>;
+ clock-input = <&osc 0>;
+ clock-input-name = "ref";
+ reg = <0x4c000 0x1000>;
+ clock-output-name = "pll", "pll-switched";
+ };
+
+ /* UART, using the low frequency oscillator for the baud clock,
+ * and the high frequency switched PLL output for register
+ * clocking */
+ uart {
+ compatible = "fsl,imx-uart";
+ reg = <0xa000 0x1000>;
+ interrupts = <33>;
+ clock-input = <&osc 0>, <&pll 1>;
+ clock-input-name = "baud", "register";
+ };
+
+This DT fragment defines three devices: an external oscillator to provide a
+low-frequency reference clock, a PLL device to generate a higher frequency
+clock signal, and a UART.
+
+* The oscillator is fixed-frequency, and provides one clock output, named "osc".
+* The PLL is both a clock provider and a clock consumer. It uses the clock
+ signal generated by the external oscillator, and provides two output signals
+ ("pll" and "pll-switched").
+* The UART has its baud clock connected the external oscillator and its
+ register clock connected to the PLL clock (the "pll-switched" signal)
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 268163d..b49ab9c 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -47,6 +47,12 @@ config OF_IRQ
def_bool y
depends on !SPARC
+config OF_CLOCK
+ def_bool y
+ depends on HAVE_CLK
+ help
+ OpenFirmware clock accessors
+
config OF_DEVICE
def_bool y
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index a73f5a5..e7ad1e9 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_OF_ADDRESS) += address.o
obj-$(CONFIG_OF_IRQ) += irq.o
obj-$(CONFIG_OF_DEVICE) += device.o platform.o
obj-$(CONFIG_OF_GPIO) += gpio.o
+obj-$(CONFIG_OF_CLOCK) += clock.o
obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_NET) += of_net.o
obj-$(CONFIG_OF_SPI) += of_spi.o
diff --git a/drivers/of/clock.c b/drivers/of/clock.c
new file mode 100644
index 0000000..542b9e4
--- /dev/null
+++ b/drivers/of/clock.c
@@ -0,0 +1,129 @@
+/*
+ * Clock infrastructure for device tree platforms
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+/**
+ * struct of_clk_provider - Clock provider registration structure
+ * @link: Entry in global list of clock providers
+ * @node: Pointer to device tree node of clock provider
+ * @get: Get clock callback. Returns NULL or a struct clk for the
+ * given clock specifier
+ * @data: context pointer to be passed into @get callback
+ */
+struct of_clk_provider {
+ struct list_head link;
+
+ struct device_node *node;
+ struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+ void *data;
+};
+
+static LIST_HEAD(of_clk_providers);
+static DEFINE_MUTEX(of_clk_lock);
+
+/**
+ * of_clk_add_provider() - Register a clock provider for a node
+ * @np: Device node pointer associated with clock provider
+ * @clk_src_get: callback for decoding clock
+ * @data: context pointer for @clk_src_get callback.
+ */
+int of_clk_add_provider(struct device_node *np,
+ struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
+ void *data),
+ void *data)
+{
+ struct of_clk_provider *cp;
+
+ cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
+ if (!cp)
+ return -ENOMEM;
+
+ cp->node = of_node_get(np);
+ cp->data = data;
+ cp->get = clk_src_get;
+
+ mutex_lock(&of_clk_lock);
+ list_add(&cp->link, &of_clk_providers);
+ mutex_unlock(&of_clk_lock);
+ pr_debug("Added clock from %s\n", np->full_name);
+
+ return 0;
+}
+
+/**
+ * of_clk_del_provider() - Remove a previously registered clock provider
+ * @np: Device node pointer associated with clock provider
+ */
+void of_clk_del_provider(struct device_node *np)
+{
+ struct of_clk_provider *cp;
+
+ mutex_lock(&of_clk_lock);
+ list_for_each_entry(cp, &of_clk_providers, link) {
+ if (cp->node == np) {
+ list_del(&cp->link);
+ of_node_put(cp->node);
+ kfree(cp);
+ break;
+ }
+ }
+ mutex_unlock(&of_clk_lock);
+}
+
+static struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
+{
+ struct of_clk_provider *provider;
+ struct clk *clk = NULL;
+
+ /* Check if we have such a provider in our array */
+ mutex_lock(&of_clk_lock);
+ list_for_each_entry(provider, &of_clk_providers, link) {
+ if (provider->node == clkspec->np)
+ clk = provider->get(clkspec, provider->data);
+ if (clk)
+ break;
+ }
+ mutex_unlock(&of_clk_lock);
+
+ return clk;
+}
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+ struct of_phandle_args clkspec;
+ struct clk *clk;
+ int rc;
+
+ if (index < 0)
+ return NULL;
+
+ rc = of_parse_phandle_with_args(np, "clock", "#clock-cells", index,
+ &clkspec);
+ if (rc)
+ return NULL;
+
+ clk = __of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ return clk;
+}
+
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+ int index = 0;
+
+ if (name)
+ index = of_property_match_string(np, "clock-input-names", name);
+ return of_clk_get(np, index);
+}
+
diff --git a/include/linux/of_clk.h b/include/linux/of_clk.h
new file mode 100644
index 0000000..e476a5f
--- /dev/null
+++ b/include/linux/of_clk.h
@@ -0,0 +1,37 @@
+/*
+ * Clock infrastructure for device tree platforms
+ */
+#ifndef __OF_CLK_H
+#define __OF_CLK_H
+
+struct device;
+struct clk;
+
+#ifdef CONFIG_OF_CLOCK
+
+struct device_node;
+
+int of_clk_add_provider(struct device_node *np,
+ struct clk *(*clk_src_get)(struct of_phandle_args *args,
+ void *data),
+ void *data);
+
+void of_clk_del_provider(struct device_node *np);
+
+struct clk *of_clk_get(struct device_node *np, int index);
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
+
+#else
+static struct clk *of_clk_get(struct device_node *np, int index);
+{
+ return NULL;
+}
+
+static struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+ return NULL;
+}
+#endif
+
+#endif /* __OF_CLK_H */
+
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
2011-11-09 1:19 ` [RFC 6/8] of: add clock providers Grant Likely
@ 2011-11-09 18:39 ` Tony Lindgren
[not found] ` <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
1 sibling, 0 replies; 34+ messages in thread
From: Tony Lindgren @ 2011-11-09 18:39 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
linux-kernel
* Grant Likely <grant.likely@secretlab.ca> [111108 16:51]:
> +
> + /* external oscillator */
> + osc: oscillator {
> + compatible = "fixed-clock";
> + #clock-cells = <1>;
> + frequency = <32678>;
> + clock-output-name = "osc";
> + };
> +
> + /* phase-locked-loop device, generates a higher frequency clock
> + * from the external oscillator reference */
> + pll: pll {
> + compatible = "some-pll-interface"
> + #clock-cells = <1>;
> + clock-input = <&osc 0>;
> + clock-input-name = "ref";
> + reg = <0x4c000 0x1000>;
> + clock-output-name = "pll", "pll-switched";
> + };
I think for the clocks we need something describing which bits
in the clock register the "pll" and "pll-switched" belong to.
Otherwise we'll end up having to map all that data in the clock
driver for various SoC variants.
> + /* UART, using the low frequency oscillator for the baud clock,
> + * and the high frequency switched PLL output for register
> + * clocking */
> + uart {
> + compatible = "fsl,imx-uart";
> + reg = <0xa000 0x1000>;
> + interrupts = <33>;
> + clock-input = <&osc 0>, <&pll 1>;
> + clock-input-name = "baud", "register";
> + };
> +
Here I think we need a better solution for finding the
clocks by name. Doing clock-input = <&osc 0>, <&pll 1> means
that we have redefine the uart for similar SoC many times.
How about using source + option in the name instead:
clock-source-name = "osc.osc", "pll.pll-switched";
This same solution would also work for the pinctrl names:
pinctrl-source-name = "uart1_rx.uart1_rx", "dss_data7.uart1_tx";
The reason I'm worried here is that just for omap2/3/4 we already
have 3 options for uart1 clock and 19 options for uart1_rx pin!
Using the signal names for both clocks and pinctrl would
allow defining the uart entry for for each reg address instead
of for each clock and pinctrl option.
Regards,
Tony
^ permalink raw reply [flat|nested] 34+ messages in thread
[parent not found: <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>]
* Re: [RFC 6/8] of: add clock providers
[not found] ` <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
@ 2011-11-09 2:49 ` Rob Herring
2011-11-14 2:14 ` Richard Zhao
2011-11-09 9:13 ` Sascha Hauer
2011-11-21 15:37 ` Shawn Guo
2 siblings, 1 reply; 34+ messages in thread
From: Rob Herring @ 2011-11-09 2:49 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Sascha Hauer,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 11/08/2011 07:19 PM, Grant Likely wrote:
> Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
> of_clk_get function to allow platforms to retrieve clock data from the
> device tree.
>
> Platform register a provider through of_clk_add_provider, which will be
> called when a device references the provider's OF node for a clock
> reference.
>
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> .../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
> drivers/of/Kconfig | 6 +
> drivers/of/Makefile | 1 +
> drivers/of/clock.c | 129 ++++++++++++++++++++
> include/linux/of_clk.h | 37 ++++++
> 5 files changed, 282 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
> create mode 100644 drivers/of/clock.c
> create mode 100644 include/linux/of_clk.h
>
> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> new file mode 100644
> index 0000000..4770c7e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> @@ -0,0 +1,109 @@
> +This binding is a work-in-progress, and are based on some experimental
> +work by benh[1].
> +
> +Sources of clock signal can be represented by any node in the device
> +tree. Those nodes are designated as clock providers. Clock consumer
> +nodes use a phandle and clock specifier pair to connect clock provider
> +outputs to clock inputs. Similar to the gpio specifiers, a clock
> +specifier is an array of one more more cells identifying the clock
> +output on a device. The length of a clock specifier is defined by the
> +value of a #clock-cells property in the clock provider node.
> +
> +[1] http://patchwork.ozlabs.org/patch/31551/
> +
> +==Clock providers==
> +
> +Required properties:
> +#clock-cells: Number of cells in a clock specifier; typically will be
> + set to 1
> +
> +Optional properties:
> +clock-output-name: Recommended to be a list of strings of clock output signal
> + names indexed by the first cell in the clock specifier.
> + However, the meaning of clock-output-names is domain
> + specific to the clock provider, and is only provided to
> + encourage using the same meaning for the majority of clock
> + providers. This format may not work for clock providers
> + using a complex clock specifier format. In those cases it
> + is recommended to omit this property and create a binding
> + specific names property.
> +
> + Clock consumer nodes must never directly reference
> + the provider's clock-output-names property.
> +
> +For example:
> +
> + oscillator {
> + #clock-cells = <1>;
> + clock-output-name = "ckil", "ckih";
> + };
> +
> +- this node defines a device with two clock outputs, the first named
> + "ckil" and the second named "ckih". Consumer nodes always reference
> + clocks by index. The names should reflect the clock output signal
> + names for the device.
> +
> +==Clock consumers==
> +
> +Required properties:
> +clock-input: List of phandle and clock specifier pairs, one pair
> + for each clock input to the device.
> +clock-input-name: List of clock input name strings sorted in the same
> + order as the clock-input property. Consumers drivers
> + will use clock-input-name to match clock input names
> + with clock-input specifiers.
> +
> +For example:
> +
> + uart {
> + clock-input = <&osc 1> <&ref 0>;
> + clock-input-name = "baud", "register";
> + };
This is duplicated below.
> +
> +
> +This represents a device with two clock inputs, named "baud" and "register".
> +The baud clock is connected to output 1 of the &osc device, and the register
> +clock is connected to output 0 of the &ref.
> +
> +==Example==
> +
> + /* external oscillator */
> + osc: oscillator {
> + compatible = "fixed-clock";
> + #clock-cells = <1>;
> + frequency = <32678>;
The code is using "clock-frequency" here.
> + clock-output-name = "osc";
> + };
> +
> + /* phase-locked-loop device, generates a higher frequency clock
> + * from the external oscillator reference */
> + pll: pll {
> + compatible = "some-pll-interface"
> + #clock-cells = <1>;
> + clock-input = <&osc 0>;
There's a mismatch in #clock-cells size and this.
> + clock-input-name = "ref";
> + reg = <0x4c000 0x1000>;
> + clock-output-name = "pll", "pll-switched";
> + };
> +
> + /* UART, using the low frequency oscillator for the baud clock,
> + * and the high frequency switched PLL output for register
> + * clocking */
> + uart {
> + compatible = "fsl,imx-uart";
> + reg = <0xa000 0x1000>;
> + interrupts = <33>;
> + clock-input = <&osc 0>, <&pll 1>;
> + clock-input-name = "baud", "register";
> + };
> +
> +This DT fragment defines three devices: an external oscillator to provide a
> +low-frequency reference clock, a PLL device to generate a higher frequency
> +clock signal, and a UART.
> +
> +* The oscillator is fixed-frequency, and provides one clock output, named "osc".
> +* The PLL is both a clock provider and a clock consumer. It uses the clock
> + signal generated by the external oscillator, and provides two output signals
> + ("pll" and "pll-switched").
> +* The UART has its baud clock connected the external oscillator and its
> + register clock connected to the PLL clock (the "pll-switched" signal)
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index 268163d..b49ab9c 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -47,6 +47,12 @@ config OF_IRQ
> def_bool y
> depends on !SPARC
>
> +config OF_CLOCK
> + def_bool y
> + depends on HAVE_CLK
> + help
> + OpenFirmware clock accessors
> +
> config OF_DEVICE
> def_bool y
>
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index a73f5a5..e7ad1e9 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -5,6 +5,7 @@ obj-$(CONFIG_OF_ADDRESS) += address.o
> obj-$(CONFIG_OF_IRQ) += irq.o
> obj-$(CONFIG_OF_DEVICE) += device.o platform.o
> obj-$(CONFIG_OF_GPIO) += gpio.o
> +obj-$(CONFIG_OF_CLOCK) += clock.o
> obj-$(CONFIG_OF_I2C) += of_i2c.o
> obj-$(CONFIG_OF_NET) += of_net.o
> obj-$(CONFIG_OF_SPI) += of_spi.o
> diff --git a/drivers/of/clock.c b/drivers/of/clock.c
> new file mode 100644
> index 0000000..542b9e4
> --- /dev/null
> +++ b/drivers/of/clock.c
> @@ -0,0 +1,129 @@
> +/*
> + * Clock infrastructure for device tree platforms
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_clk.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/device.h>
> +
> +/**
> + * struct of_clk_provider - Clock provider registration structure
> + * @link: Entry in global list of clock providers
> + * @node: Pointer to device tree node of clock provider
> + * @get: Get clock callback. Returns NULL or a struct clk for the
> + * given clock specifier
> + * @data: context pointer to be passed into @get callback
> + */
> +struct of_clk_provider {
> + struct list_head link;
> +
> + struct device_node *node;
> + struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
> + void *data;
> +};
> +
> +static LIST_HEAD(of_clk_providers);
> +static DEFINE_MUTEX(of_clk_lock);
> +
> +/**
> + * of_clk_add_provider() - Register a clock provider for a node
> + * @np: Device node pointer associated with clock provider
> + * @clk_src_get: callback for decoding clock
> + * @data: context pointer for @clk_src_get callback.
> + */
> +int of_clk_add_provider(struct device_node *np,
> + struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
> + void *data),
> + void *data)
> +{
> + struct of_clk_provider *cp;
> +
> + cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
> + if (!cp)
> + return -ENOMEM;
> +
> + cp->node = of_node_get(np);
> + cp->data = data;
> + cp->get = clk_src_get;
> +
> + mutex_lock(&of_clk_lock);
> + list_add(&cp->link, &of_clk_providers);
> + mutex_unlock(&of_clk_lock);
> + pr_debug("Added clock from %s\n", np->full_name);
> +
> + return 0;
> +}
> +
> +/**
> + * of_clk_del_provider() - Remove a previously registered clock provider
> + * @np: Device node pointer associated with clock provider
> + */
> +void of_clk_del_provider(struct device_node *np)
> +{
> + struct of_clk_provider *cp;
> +
> + mutex_lock(&of_clk_lock);
> + list_for_each_entry(cp, &of_clk_providers, link) {
> + if (cp->node == np) {
> + list_del(&cp->link);
> + of_node_put(cp->node);
> + kfree(cp);
> + break;
> + }
> + }
> + mutex_unlock(&of_clk_lock);
> +}
> +
> +static struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
> +{
> + struct of_clk_provider *provider;
> + struct clk *clk = NULL;
> +
> + /* Check if we have such a provider in our array */
> + mutex_lock(&of_clk_lock);
> + list_for_each_entry(provider, &of_clk_providers, link) {
> + if (provider->node == clkspec->np)
> + clk = provider->get(clkspec, provider->data);
How about:
if (provider->get)
clk = provider->get(clkspec, provider->data);
else
clk = provider->data;
Or a default get function can do this.
> + if (clk)
> + break;
> + }
> + mutex_unlock(&of_clk_lock);
> +
> + return clk;
> +}
> +
> +struct clk *of_clk_get(struct device_node *np, int index)
> +{
> + struct of_phandle_args clkspec;
> + struct clk *clk;
> + int rc;
> +
> + if (index < 0)
> + return NULL;
> +
> + rc = of_parse_phandle_with_args(np, "clock", "#clock-cells", index,
> + &clkspec);
> + if (rc)
> + return NULL;
> +
> + clk = __of_clk_get_from_provider(&clkspec);
> + of_node_put(clkspec.np);
> + return clk;
> +}
> +
> +struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
> +{
> + int index = 0;
> +
> + if (name)
> + index = of_property_match_string(np, "clock-input-names", name);
> + return of_clk_get(np, index);
> +}
> +
> diff --git a/include/linux/of_clk.h b/include/linux/of_clk.h
> new file mode 100644
> index 0000000..e476a5f
> --- /dev/null
> +++ b/include/linux/of_clk.h
> @@ -0,0 +1,37 @@
> +/*
> + * Clock infrastructure for device tree platforms
> + */
> +#ifndef __OF_CLK_H
> +#define __OF_CLK_H
> +
> +struct device;
> +struct clk;
> +
> +#ifdef CONFIG_OF_CLOCK
> +
> +struct device_node;
> +
> +int of_clk_add_provider(struct device_node *np,
> + struct clk *(*clk_src_get)(struct of_phandle_args *args,
> + void *data),
> + void *data);
> +
> +void of_clk_del_provider(struct device_node *np);
> +
> +struct clk *of_clk_get(struct device_node *np, int index);
> +struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
> +
> +#else
> +static struct clk *of_clk_get(struct device_node *np, int index);
> +{
> + return NULL;
> +}
> +
> +static struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
> +{
> + return NULL;
> +}
> +#endif
> +
> +#endif /* __OF_CLK_H */
> +
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
2011-11-09 2:49 ` Rob Herring
@ 2011-11-14 2:14 ` Richard Zhao
2011-11-16 19:06 ` Grant Likely
0 siblings, 1 reply; 34+ messages in thread
From: Richard Zhao @ 2011-11-14 2:14 UTC (permalink / raw)
To: Rob Herring
Cc: Grant Likely, devicetree-discuss, linux-arm-kernel, Sascha Hauer,
linux-kernel
On Tue, Nov 08, 2011 at 08:49:42PM -0600, Rob Herring wrote:
> On 11/08/2011 07:19 PM, Grant Likely wrote:
> > Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
> > of_clk_get function to allow platforms to retrieve clock data from the
> > device tree.
> >
> > Platform register a provider through of_clk_add_provider, which will be
> > called when a device references the provider's OF node for a clock
> > reference.
> >
> > Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> > ---
> > .../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
> > drivers/of/Kconfig | 6 +
> > drivers/of/Makefile | 1 +
> > drivers/of/clock.c | 129 ++++++++++++++++++++
> > include/linux/of_clk.h | 37 ++++++
> > 5 files changed, 282 insertions(+), 0 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
> > create mode 100644 drivers/of/clock.c
> > create mode 100644 include/linux/of_clk.h
> >
> > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > new file mode 100644
> > index 0000000..4770c7e
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > @@ -0,0 +1,109 @@
> > +This binding is a work-in-progress, and are based on some experimental
> > +work by benh[1].
> > +
> > +Sources of clock signal can be represented by any node in the device
> > +tree. Those nodes are designated as clock providers. Clock consumer
> > +nodes use a phandle and clock specifier pair to connect clock provider
> > +outputs to clock inputs. Similar to the gpio specifiers, a clock
> > +specifier is an array of one more more cells identifying the clock
> > +output on a device. The length of a clock specifier is defined by the
> > +value of a #clock-cells property in the clock provider node.
> > +
> > +[1] http://patchwork.ozlabs.org/patch/31551/
> > +
> > +==Clock providers==
> > +
> > +Required properties:
> > +#clock-cells: Number of cells in a clock specifier; typically will be
> > + set to 1
> > +
> > +Optional properties:
> > +clock-output-name: Recommended to be a list of strings of clock output signal
> > + names indexed by the first cell in the clock specifier.
> > + However, the meaning of clock-output-names is domain
> > + specific to the clock provider, and is only provided to
> > + encourage using the same meaning for the majority of clock
> > + providers. This format may not work for clock providers
> > + using a complex clock specifier format. In those cases it
> > + is recommended to omit this property and create a binding
> > + specific names property.
> > +
> > + Clock consumer nodes must never directly reference
> > + the provider's clock-output-names property.
> > +
> > +For example:
> > +
> > + oscillator {
> > + #clock-cells = <1>;
> > + clock-output-name = "ckil", "ckih";
> > + };
> > +
> > +- this node defines a device with two clock outputs, the first named
> > + "ckil" and the second named "ckih". Consumer nodes always reference
> > + clocks by index. The names should reflect the clock output signal
> > + names for the device.
> > +
> > +==Clock consumers==
> > +
> > +Required properties:
> > +clock-input: List of phandle and clock specifier pairs, one pair
> > + for each clock input to the device.
> > +clock-input-name: List of clock input name strings sorted in the same
> > + order as the clock-input property. Consumers drivers
> > + will use clock-input-name to match clock input names
> > + with clock-input specifiers.
> > +
> > +For example:
> > +
> > + uart {
> > + clock-input = <&osc 1> <&ref 0>;
> > + clock-input-name = "baud", "register";
> > + };
>
> This is duplicated below.
>
> > +
> > +
> > +This represents a device with two clock inputs, named "baud" and "register".
> > +The baud clock is connected to output 1 of the &osc device, and the register
> > +clock is connected to output 0 of the &ref.
> > +
> > +==Example==
> > +
> > + /* external oscillator */
> > + osc: oscillator {
> > + compatible = "fixed-clock";
> > + #clock-cells = <1>;
> > + frequency = <32678>;
>
> The code is using "clock-frequency" here.
>
> > + clock-output-name = "osc";
> > + };
> > +
> > + /* phase-locked-loop device, generates a higher frequency clock
> > + * from the external oscillator reference */
> > + pll: pll {
> > + compatible = "some-pll-interface"
> > + #clock-cells = <1>;
> > + clock-input = <&osc 0>;
>
> There's a mismatch in #clock-cells size and this.
osc #clock-cells is 1. "0" is one cell too. Nothing wrong. Correct my understanding?
>
> > + clock-input-name = "ref";
> > + reg = <0x4c000 0x1000>;
> > + clock-output-name = "pll", "pll-switched";
> > + };
> > +
> > + /* UART, using the low frequency oscillator for the baud clock,
> > + * and the high frequency switched PLL output for register
> > + * clocking */
> > + uart {
> > + compatible = "fsl,imx-uart";
> > + reg = <0xa000 0x1000>;
> > + interrupts = <33>;
> > + clock-input = <&osc 0>, <&pll 1>;
> > + clock-input-name = "baud", "register";
> > + };
> > +
> > +This DT fragment defines three devices: an external oscillator to provide a
> > +low-frequency reference clock, a PLL device to generate a higher frequency
> > +clock signal, and a UART.
> > +
> > +* The oscillator is fixed-frequency, and provides one clock output, named "osc".
> > +* The PLL is both a clock provider and a clock consumer. It uses the clock
> > + signal generated by the external oscillator, and provides two output signals
> > + ("pll" and "pll-switched").
> > +* The UART has its baud clock connected the external oscillator and its
> > + register clock connected to the PLL clock (the "pll-switched" signal)
> > diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> > index 268163d..b49ab9c 100644
> > --- a/drivers/of/Kconfig
> > +++ b/drivers/of/Kconfig
> > @@ -47,6 +47,12 @@ config OF_IRQ
> > def_bool y
> > depends on !SPARC
> >
> > +config OF_CLOCK
> > + def_bool y
> > + depends on HAVE_CLK
> > + help
> > + OpenFirmware clock accessors
> > +
> > config OF_DEVICE
> > def_bool y
> >
> > diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> > index a73f5a5..e7ad1e9 100644
> > --- a/drivers/of/Makefile
> > +++ b/drivers/of/Makefile
> > @@ -5,6 +5,7 @@ obj-$(CONFIG_OF_ADDRESS) += address.o
> > obj-$(CONFIG_OF_IRQ) += irq.o
> > obj-$(CONFIG_OF_DEVICE) += device.o platform.o
> > obj-$(CONFIG_OF_GPIO) += gpio.o
> > +obj-$(CONFIG_OF_CLOCK) += clock.o
> > obj-$(CONFIG_OF_I2C) += of_i2c.o
> > obj-$(CONFIG_OF_NET) += of_net.o
> > obj-$(CONFIG_OF_SPI) += of_spi.o
> > diff --git a/drivers/of/clock.c b/drivers/of/clock.c
> > new file mode 100644
> > index 0000000..542b9e4
> > --- /dev/null
> > +++ b/drivers/of/clock.c
> > @@ -0,0 +1,129 @@
> > +/*
> > + * Clock infrastructure for device tree platforms
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/err.h>
> > +#include <linux/errno.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_clk.h>
> > +#include <linux/list.h>
> > +#include <linux/mutex.h>
> > +#include <linux/slab.h>
> > +#include <linux/device.h>
> > +
> > +/**
> > + * struct of_clk_provider - Clock provider registration structure
> > + * @link: Entry in global list of clock providers
> > + * @node: Pointer to device tree node of clock provider
> > + * @get: Get clock callback. Returns NULL or a struct clk for the
> > + * given clock specifier
> > + * @data: context pointer to be passed into @get callback
> > + */
> > +struct of_clk_provider {
> > + struct list_head link;
> > +
> > + struct device_node *node;
> > + struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
> > + void *data;
> > +};
> > +
> > +static LIST_HEAD(of_clk_providers);
> > +static DEFINE_MUTEX(of_clk_lock);
> > +
> > +/**
> > + * of_clk_add_provider() - Register a clock provider for a node
> > + * @np: Device node pointer associated with clock provider
> > + * @clk_src_get: callback for decoding clock
> > + * @data: context pointer for @clk_src_get callback.
> > + */
> > +int of_clk_add_provider(struct device_node *np,
> > + struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
> > + void *data),
> > + void *data)
> > +{
> > + struct of_clk_provider *cp;
> > +
> > + cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
> > + if (!cp)
> > + return -ENOMEM;
> > +
> > + cp->node = of_node_get(np);
> > + cp->data = data;
> > + cp->get = clk_src_get;
> > +
> > + mutex_lock(&of_clk_lock);
> > + list_add(&cp->link, &of_clk_providers);
> > + mutex_unlock(&of_clk_lock);
> > + pr_debug("Added clock from %s\n", np->full_name);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * of_clk_del_provider() - Remove a previously registered clock provider
> > + * @np: Device node pointer associated with clock provider
> > + */
> > +void of_clk_del_provider(struct device_node *np)
> > +{
> > + struct of_clk_provider *cp;
> > +
> > + mutex_lock(&of_clk_lock);
> > + list_for_each_entry(cp, &of_clk_providers, link) {
> > + if (cp->node == np) {
> > + list_del(&cp->link);
> > + of_node_put(cp->node);
> > + kfree(cp);
> > + break;
> > + }
> > + }
> > + mutex_unlock(&of_clk_lock);
> > +}
> > +
> > +static struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
> > +{
> > + struct of_clk_provider *provider;
> > + struct clk *clk = NULL;
> > +
> > + /* Check if we have such a provider in our array */
> > + mutex_lock(&of_clk_lock);
> > + list_for_each_entry(provider, &of_clk_providers, link) {
> > + if (provider->node == clkspec->np)
> > + clk = provider->get(clkspec, provider->data);
>
> How about:
>
> if (provider->get)
> clk = provider->get(clkspec, provider->data);
> else
> clk = provider->data;
>
>
> Or a default get function can do this.
>
> > + if (clk)
> > + break;
> > + }
> > + mutex_unlock(&of_clk_lock);
> > +
> > + return clk;
> > +}
> > +
> > +struct clk *of_clk_get(struct device_node *np, int index)
> > +{
> > + struct of_phandle_args clkspec;
> > + struct clk *clk;
> > + int rc;
> > +
> > + if (index < 0)
> > + return NULL;
> > +
> > + rc = of_parse_phandle_with_args(np, "clock", "#clock-cells", index,
> > + &clkspec);
> > + if (rc)
> > + return NULL;
> > +
> > + clk = __of_clk_get_from_provider(&clkspec);
> > + of_node_put(clkspec.np);
> > + return clk;
> > +}
> > +
> > +struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
> > +{
> > + int index = 0;
> > +
> > + if (name)
> > + index = of_property_match_string(np, "clock-input-names", name);
> > + return of_clk_get(np, index);
> > +}
> > +
> > diff --git a/include/linux/of_clk.h b/include/linux/of_clk.h
> > new file mode 100644
> > index 0000000..e476a5f
> > --- /dev/null
> > +++ b/include/linux/of_clk.h
> > @@ -0,0 +1,37 @@
> > +/*
> > + * Clock infrastructure for device tree platforms
> > + */
> > +#ifndef __OF_CLK_H
> > +#define __OF_CLK_H
> > +
> > +struct device;
> > +struct clk;
> > +
> > +#ifdef CONFIG_OF_CLOCK
> > +
> > +struct device_node;
> > +
> > +int of_clk_add_provider(struct device_node *np,
> > + struct clk *(*clk_src_get)(struct of_phandle_args *args,
> > + void *data),
> > + void *data);
> > +
> > +void of_clk_del_provider(struct device_node *np);
> > +
> > +struct clk *of_clk_get(struct device_node *np, int index);
> > +struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
> > +
> > +#else
> > +static struct clk *of_clk_get(struct device_node *np, int index);
> > +{
> > + return NULL;
> > +}
> > +
> > +static struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
> > +{
> > + return NULL;
> > +}
> > +#endif
> > +
> > +#endif /* __OF_CLK_H */
> > +
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
2011-11-14 2:14 ` Richard Zhao
@ 2011-11-16 19:06 ` Grant Likely
0 siblings, 0 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-16 19:06 UTC (permalink / raw)
To: Richard Zhao
Cc: Rob Herring, devicetree-discuss, Sascha Hauer, linux-arm-kernel,
linux-kernel
On Sun, Nov 13, 2011 at 7:14 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> On Tue, Nov 08, 2011 at 08:49:42PM -0600, Rob Herring wrote:
>> > +For example:
>> > +
>> > + oscillator {
>> > + #clock-cells = <1>;
>> > + clock-output-name = "ckil", "ckih";
>> > + };
>> > +
>> > +- this node defines a device with two clock outputs, the first named
>> > + "ckil" and the second named "ckih". Consumer nodes always reference
>> > + clocks by index. The names should reflect the clock output signal
>> > + names for the device.
>> > +
>> > +==Clock consumers==
>> > +
>> > +Required properties:
>> > +clock-input: List of phandle and clock specifier pairs, one pair
>> > + for each clock input to the device.
>> > +clock-input-name: List of clock input name strings sorted in the same
>> > + order as the clock-input property. Consumers drivers
>> > + will use clock-input-name to match clock input names
>> > + with clock-input specifiers.
>> > +
>> > +For example:
>> > +
>> > + uart {
>> > + clock-input = <&osc 1> <&ref 0>;
>> > + clock-input-name = "baud", "register";
>> > + };
>>
>> This is duplicated below.
I'm okay with that. It's not entirely the same, and I think having
several examples is helpful.
>> > + /* external oscillator */
>> > + osc: oscillator {
>> > + compatible = "fixed-clock";
>> > + #clock-cells = <1>;
>> > + frequency = <32678>;
>>
>> The code is using "clock-frequency" here.
Fixed
>>
>> > + clock-output-name = "osc";
>> > + };
>> > +
>> > + /* phase-locked-loop device, generates a higher frequency clock
>> > + * from the external oscillator reference */
>> > + pll: pll {
>> > + compatible = "some-pll-interface"
>> > + #clock-cells = <1>;
>> > + clock-input = <&osc 0>;
>>
>> There's a mismatch in #clock-cells size and this.
>
> osc #clock-cells is 1. "0" is one cell too. Nothing wrong. Correct my understanding?
Richard is correct. The #clock-cells value needs to be 1, which in
the clock binding means one cell for the phandle and one cell for the
attached arguments. Exactly the same as the gpio binding.
>> > +static struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
>> > +{
>> > + struct of_clk_provider *provider;
>> > + struct clk *clk = NULL;
>> > +
>> > + /* Check if we have such a provider in our array */
>> > + mutex_lock(&of_clk_lock);
>> > + list_for_each_entry(provider, &of_clk_providers, link) {
>> > + if (provider->node == clkspec->np)
>> > + clk = provider->get(clkspec, provider->data);
>>
>> How about:
>>
>> if (provider->get)
>> clk = provider->get(clkspec, provider->data);
>> else
>> clk = provider->data;
I'd rather make it a requirement for every clock driver to provide the
get hook; even if it uses a stock version that simply returns ->data.
Thanks for the review.
g.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
[not found] ` <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 2:49 ` Rob Herring
@ 2011-11-09 9:13 ` Sascha Hauer
[not found] ` <20111109091328.GY16886-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2011-11-09 13:31 ` Rob Herring
2011-11-21 15:37 ` Shawn Guo
2 siblings, 2 replies; 34+ messages in thread
From: Sascha Hauer @ 2011-11-09 9:13 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Sascha Hauer, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tue, Nov 08, 2011 at 06:19:41PM -0700, Grant Likely wrote:
> Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
> of_clk_get function to allow platforms to retrieve clock data from the
> device tree.
>
> Platform register a provider through of_clk_add_provider, which will be
> called when a device references the provider's OF node for a clock
> reference.
>
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> .../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
> drivers/of/Kconfig | 6 +
> drivers/of/Makefile | 1 +
> drivers/of/clock.c | 129 ++++++++++++++++++++
> include/linux/of_clk.h | 37 ++++++
> 5 files changed, 282 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
> create mode 100644 drivers/of/clock.c
> create mode 100644 include/linux/of_clk.h
>
> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> new file mode 100644
> index 0000000..4770c7e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> @@ -0,0 +1,109 @@
> +This binding is a work-in-progress, and are based on some experimental
> +work by benh[1].
> +
> +Sources of clock signal can be represented by any node in the device
> +tree. Those nodes are designated as clock providers. Clock consumer
> +nodes use a phandle and clock specifier pair to connect clock provider
> +outputs to clock inputs. Similar to the gpio specifiers, a clock
> +specifier is an array of one more more cells identifying the clock
> +output on a device. The length of a clock specifier is defined by the
> +value of a #clock-cells property in the clock provider node.
> +
> +[1] http://patchwork.ozlabs.org/patch/31551/
> +
> +==Clock providers==
> +
> +Required properties:
> +#clock-cells: Number of cells in a clock specifier; typically will be
> + set to 1
> +
> +Optional properties:
> +clock-output-name: Recommended to be a list of strings of clock output signal
> + names indexed by the first cell in the clock specifier.
> + However, the meaning of clock-output-names is domain
> + specific to the clock provider, and is only provided to
> + encourage using the same meaning for the majority of clock
> + providers. This format may not work for clock providers
> + using a complex clock specifier format. In those cases it
> + is recommended to omit this property and create a binding
> + specific names property.
If the clock-output-name property is omitted, does this mean a clock
provider only has a single output or does it mean that it's not known
how many clock outputs a provider actually has?
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 34+ messages in thread
[parent not found: <20111109091328.GY16886-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>]
* Re: [RFC 6/8] of: add clock providers
[not found] ` <20111109091328.GY16886-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2011-11-09 11:23 ` Cousson, Benoit
[not found] ` <4EBA62AD.3000407-l0cyMroinI0@public.gmane.org>
0 siblings, 1 reply; 34+ messages in thread
From: Cousson, Benoit @ 2011-11-09 11:23 UTC (permalink / raw)
To: Sascha Hauer
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Sascha Hauer,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
On 11/9/2011 10:13 AM, Sascha Hauer wrote:
> On Tue, Nov 08, 2011 at 06:19:41PM -0700, Grant Likely wrote:
[...]
>> +Sources of clock signal can be represented by any node in the device
>> +tree. Those nodes are designated as clock providers. Clock consumer
>> +nodes use a phandle and clock specifier pair to connect clock provider
>> +outputs to clock inputs. Similar to the gpio specifiers, a clock
>> +specifier is an array of one more more cells identifying the clock
>> +output on a device. The length of a clock specifier is defined by the
>> +value of a #clock-cells property in the clock provider node.
>> +
>> +[1] http://patchwork.ozlabs.org/patch/31551/
>> +
>> +==Clock providers==
>> +
>> +Required properties:
>> +#clock-cells: Number of cells in a clock specifier; typically will be
>> + set to 1
>> +
>> +Optional properties:
>> +clock-output-name: Recommended to be a list of strings of clock output signal
>> + names indexed by the first cell in the clock specifier.
>> + However, the meaning of clock-output-names is domain
>> + specific to the clock provider, and is only provided to
>> + encourage using the same meaning for the majority of clock
>> + providers. This format may not work for clock providers
>> + using a complex clock specifier format. In those cases it
>> + is recommended to omit this property and create a binding
>> + specific names property.
>
> If the clock-output-name property is omitted, does this mean a clock
> provider only has a single output or does it mean that it's not known
> how many clock outputs a provider actually has?
Allowing several outputs for a single clock node might lead to a lot of
confusion. What will be the meaning of a clock rate if you have several
outputs at different frequency?
I think it will be better to define a clock node as a single source of
clock. If several outputs are needed, then we should define several
clock nodes.
If we let a clock node be any kind of big clock blob, we will never be
able to define some generic reusable clock node API. Everybody will
define its own custom clock blobs.
Regards,
Benoit
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
2011-11-09 9:13 ` Sascha Hauer
[not found] ` <20111109091328.GY16886-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2011-11-09 13:31 ` Rob Herring
1 sibling, 0 replies; 34+ messages in thread
From: Rob Herring @ 2011-11-09 13:31 UTC (permalink / raw)
To: Sascha Hauer
Cc: Grant Likely, devicetree-discuss, linux-arm-kernel, Sascha Hauer,
linux-kernel
On 11/09/2011 03:13 AM, Sascha Hauer wrote:
> On Tue, Nov 08, 2011 at 06:19:41PM -0700, Grant Likely wrote:
>> Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
>> of_clk_get function to allow platforms to retrieve clock data from the
>> device tree.
>>
>> Platform register a provider through of_clk_add_provider, which will be
>> called when a device references the provider's OF node for a clock
>> reference.
>>
>> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>> ---
>> .../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
>> drivers/of/Kconfig | 6 +
>> drivers/of/Makefile | 1 +
>> drivers/of/clock.c | 129 ++++++++++++++++++++
>> include/linux/of_clk.h | 37 ++++++
>> 5 files changed, 282 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
>> create mode 100644 drivers/of/clock.c
>> create mode 100644 include/linux/of_clk.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
>> new file mode 100644
>> index 0000000..4770c7e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
>> @@ -0,0 +1,109 @@
>> +This binding is a work-in-progress, and are based on some experimental
>> +work by benh[1].
>> +
>> +Sources of clock signal can be represented by any node in the device
>> +tree. Those nodes are designated as clock providers. Clock consumer
>> +nodes use a phandle and clock specifier pair to connect clock provider
>> +outputs to clock inputs. Similar to the gpio specifiers, a clock
>> +specifier is an array of one more more cells identifying the clock
>> +output on a device. The length of a clock specifier is defined by the
>> +value of a #clock-cells property in the clock provider node.
>> +
>> +[1] http://patchwork.ozlabs.org/patch/31551/
>> +
>> +==Clock providers==
>> +
>> +Required properties:
>> +#clock-cells: Number of cells in a clock specifier; typically will be
>> + set to 1
>> +
>> +Optional properties:
>> +clock-output-name: Recommended to be a list of strings of clock output signal
>> + names indexed by the first cell in the clock specifier.
>> + However, the meaning of clock-output-names is domain
>> + specific to the clock provider, and is only provided to
>> + encourage using the same meaning for the majority of clock
>> + providers. This format may not work for clock providers
>> + using a complex clock specifier format. In those cases it
>> + is recommended to omit this property and create a binding
>> + specific names property.
>
> If the clock-output-name property is omitted, does this mean a clock
> provider only has a single output or does it mean that it's not known
> how many clock outputs a provider actually has?
Neither. It's similar to how interrupt bindings work. For a clock
consumer, you have a phandle to the parent and some number of cells to
describe the connection. Often this is just the index or local interrupt
number. Obviously, interrupt numbers make more sense than clock numbers,
so having names is more useful in the clocks case if you have many outputs.
The name strings are just additional information. Keep in mind that the
clock node name can also be used if you need to attach a name to a clock.
Rob
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 6/8] of: add clock providers
[not found] ` <1320801583-12774-7-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2011-11-09 2:49 ` Rob Herring
2011-11-09 9:13 ` Sascha Hauer
@ 2011-11-21 15:37 ` Shawn Guo
[not found] ` <20111121153716.GA16417-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2 siblings, 1 reply; 34+ messages in thread
From: Shawn Guo @ 2011-11-21 15:37 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Sascha Hauer, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tue, Nov 08, 2011 at 06:19:41PM -0700, Grant Likely wrote:
> Based on work by Ben Herrenschmidt and Jeremy Kerr, this patch adds an
> of_clk_get function to allow platforms to retrieve clock data from the
> device tree.
>
> Platform register a provider through of_clk_add_provider, which will be
> called when a device references the provider's OF node for a clock
> reference.
>
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> .../devicetree/bindings/clock/clock-bindings.txt | 109 +++++++++++++++++
> drivers/of/Kconfig | 6 +
> drivers/of/Makefile | 1 +
> drivers/of/clock.c | 129 ++++++++++++++++++++
> include/linux/of_clk.h | 37 ++++++
> 5 files changed, 282 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt
> create mode 100644 drivers/of/clock.c
> create mode 100644 include/linux/of_clk.h
>
> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> new file mode 100644
> index 0000000..4770c7e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> @@ -0,0 +1,109 @@
> +This binding is a work-in-progress, and are based on some experimental
> +work by benh[1].
> +
> +Sources of clock signal can be represented by any node in the device
> +tree. Those nodes are designated as clock providers. Clock consumer
> +nodes use a phandle and clock specifier pair to connect clock provider
> +outputs to clock inputs. Similar to the gpio specifiers, a clock
> +specifier is an array of one more more cells identifying the clock
> +output on a device. The length of a clock specifier is defined by the
> +value of a #clock-cells property in the clock provider node.
> +
> +[1] http://patchwork.ozlabs.org/patch/31551/
> +
> +==Clock providers==
> +
> +Required properties:
> +#clock-cells: Number of cells in a clock specifier; typically will be
> + set to 1
> +
> +Optional properties:
> +clock-output-name: Recommended to be a list of strings of clock output signal
> + names indexed by the first cell in the clock specifier.
> + However, the meaning of clock-output-names is domain
s/clock-output-names/clock-output-name?
> + specific to the clock provider, and is only provided to
> + encourage using the same meaning for the majority of clock
> + providers. This format may not work for clock providers
> + using a complex clock specifier format. In those cases it
> + is recommended to omit this property and create a binding
> + specific names property.
> +
> + Clock consumer nodes must never directly reference
> + the provider's clock-output-names property.
s/clock-output-names/clock-output-name?
> +
> +For example:
> +
> + oscillator {
> + #clock-cells = <1>;
> + clock-output-name = "ckil", "ckih";
> + };
> +
> +- this node defines a device with two clock outputs, the first named
> + "ckil" and the second named "ckih". Consumer nodes always reference
> + clocks by index. The names should reflect the clock output signal
> + names for the device.
> +
> +==Clock consumers==
> +
> +Required properties:
> +clock-input: List of phandle and clock specifier pairs, one pair
> + for each clock input to the device.
> +clock-input-name: List of clock input name strings sorted in the same
> + order as the clock-input property. Consumers drivers
> + will use clock-input-name to match clock input names
> + with clock-input specifiers.
> +
> +For example:
> +
> + uart {
> + clock-input = <&osc 1> <&ref 0>;
^
Comma is missed?
> + clock-input-name = "baud", "register";
> + };
[...]
> +struct clk *of_clk_get(struct device_node *np, int index)
> +{
> + struct of_phandle_args clkspec;
> + struct clk *clk;
> + int rc;
> +
> + if (index < 0)
> + return NULL;
> +
> + rc = of_parse_phandle_with_args(np, "clock", "#clock-cells", index,
According to binding document above, s/clock/clock-input?
> + &clkspec);
> + if (rc)
> + return NULL;
> +
> + clk = __of_clk_get_from_provider(&clkspec);
> + of_node_put(clkspec.np);
> + return clk;
> +}
> +
> +struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
> +{
> + int index = 0;
> +
> + if (name)
> + index = of_property_match_string(np, "clock-input-names", name);
If it fails to match name, we may want to force 'index' back to 0.
Also according to binding document above,
s/clock-input-names/clock-input-name? Hope you do not want to
change binding document to get them aligned. I have written code
per binding document :)
Regards,
Shawn
> + return of_clk_get(np, index);
> +}
^ permalink raw reply [flat|nested] 34+ messages in thread
* [RFC 7/8] arm/clkdev: lookup clocks from OF clock providers
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
` (3 preceding siblings ...)
2011-11-09 1:19 ` [RFC 6/8] of: add clock providers Grant Likely
@ 2011-11-09 1:19 ` Grant Likely
2011-11-09 2:36 ` Rob Herring
4 siblings, 1 reply; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sascha Hauer,
Rob Herring
Cc: Jeremy Kerr, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Hook the OF clock provider infrastructure to clk_get.
Signed-off-by: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
drivers/clk/clkdev.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 6db161f..63f81c9 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,6 +19,8 @@
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
@@ -78,6 +80,11 @@ EXPORT_SYMBOL(clk_get_sys);
struct clk *clk_get(struct device *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
+ struct clk *clk;
+
+ clk = of_clk_get_by_name(dev->of_node, con_id);
+ if (clk && __clk_get(clk))
+ return clk;
return clk_get_sys(dev_id, con_id);
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [RFC 7/8] arm/clkdev: lookup clocks from OF clock providers
2011-11-09 1:19 ` [RFC 7/8] arm/clkdev: lookup clocks from OF " Grant Likely
@ 2011-11-09 2:36 ` Rob Herring
2011-11-16 18:54 ` Grant Likely
0 siblings, 1 reply; 34+ messages in thread
From: Rob Herring @ 2011-11-09 2:36 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
Jeremy Kerr, linux-kernel
On 11/08/2011 07:19 PM, Grant Likely wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> Hook the OF clock provider infrastructure to clk_get.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> drivers/clk/clkdev.c | 7 +++++++
> 1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..63f81c9 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -19,6 +19,8 @@
> #include <linux/mutex.h>
> #include <linux/clk.h>
> #include <linux/clkdev.h>
> +#include <linux/of.h>
> +#include <linux/of_clk.h>
>
> static LIST_HEAD(clocks);
> static DEFINE_MUTEX(clocks_mutex);
> @@ -78,6 +80,11 @@ EXPORT_SYMBOL(clk_get_sys);
> struct clk *clk_get(struct device *dev, const char *con_id)
> {
> const char *dev_id = dev ? dev_name(dev) : NULL;
> + struct clk *clk;
> +
Need NULL check for dev (and then init clk to NULL):
if (dev && dev->of_node)
> + clk = of_clk_get_by_name(dev->of_node, con_id);
> + if (clk && __clk_get(clk))
> + return clk;
>
> return clk_get_sys(dev_id, con_id);
> }
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC 7/8] arm/clkdev: lookup clocks from OF clock providers
2011-11-09 2:36 ` Rob Herring
@ 2011-11-16 18:54 ` Grant Likely
0 siblings, 0 replies; 34+ messages in thread
From: Grant Likely @ 2011-11-16 18:54 UTC (permalink / raw)
To: Rob Herring
Cc: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring,
Jeremy Kerr, linux-kernel
On Tue, Nov 8, 2011 at 7:36 PM, Rob Herring <robherring2@gmail.com> wrote:
> On 11/08/2011 07:19 PM, Grant Likely wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> Hook the OF clock provider infrastructure to clk_get.
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>> ---
>> drivers/clk/clkdev.c | 7 +++++++
>> 1 files changed, 7 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
>> index 6db161f..63f81c9 100644
>> --- a/drivers/clk/clkdev.c
>> +++ b/drivers/clk/clkdev.c
>> @@ -19,6 +19,8 @@
>> #include <linux/mutex.h>
>> #include <linux/clk.h>
>> #include <linux/clkdev.h>
>> +#include <linux/of.h>
>> +#include <linux/of_clk.h>
>>
>> static LIST_HEAD(clocks);
>> static DEFINE_MUTEX(clocks_mutex);
>> @@ -78,6 +80,11 @@ EXPORT_SYMBOL(clk_get_sys);
>> struct clk *clk_get(struct device *dev, const char *con_id)
>> {
>> const char *dev_id = dev ? dev_name(dev) : NULL;
>> + struct clk *clk;
>> +
>
> Need NULL check for dev (and then init clk to NULL):
>
> if (dev && dev->of_node)
>> + clk = of_clk_get_by_name(dev->of_node, con_id);
>
>> + if (clk && __clk_get(clk))
>> + return clk;
Fixed, thanks.
g.
^ permalink raw reply [flat|nested] 34+ messages in thread
* [RFC 8/8] dt/arm: versatile add clock parsing
2011-11-09 1:19 [RFC 0/8] Initial DT clock bindings Grant Likely
` (2 preceding siblings ...)
[not found] ` <1320801583-12774-1-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
@ 2011-11-09 1:19 ` Grant Likely
[not found] ` <1320801583-12774-9-git-send-email-grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
3 siblings, 1 reply; 34+ messages in thread
From: Grant Likely @ 2011-11-09 1:19 UTC (permalink / raw)
To: devicetree-discuss, linux-arm-kernel, Sascha Hauer, Rob Herring
Cc: linux-kernel, Grant Likely
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/arm/boot/dts/versatile-ab.dts | 37 ++++++++++++++++++++++++++++++++
arch/arm/boot/dts/versatile-pb.dts | 2 +
arch/arm/mach-versatile/core.c | 37 +------------------------------
arch/arm/mach-versatile/versatile_dt.c | 33 ++++++++++++++++++++++++++++
4 files changed, 74 insertions(+), 35 deletions(-)
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
index 0b32925..cb8a49e 100644
--- a/arch/arm/boot/dts/versatile-ab.dts
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -19,6 +19,35 @@
reg = <0x0 0x08000000>;
};
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ref24_clk: clock0 {
+ compatible = "fixed-clock";
+ #clock-cells = <1>;
+ clock-frequency = <24000000>;
+ clock-output-names = "ref";
+ };
+
+ sp804_clk: clock1 {
+ compatible = "fixed-clock";
+ #clock-cells = <1>;
+ clock-frequency = <1000000>;
+ clock-output-names = "ref";
+ };
+
+ osc4_clk: clock3 {
+ compatible = "ics,icst307";
+ #clock-cells = <1>;
+ ref = <24000>;
+ vco-max = <200000>;
+ vd-range = <12 519>;
+ rd-range = <3 129>;
+ clock-output-names = "osc4";
+ };
+ };
+
flash@34000000 {
compatible = "arm,versatile-flash";
reg = <0x34000000 0x4000000>;
@@ -80,18 +109,21 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f1000 0x1000>;
interrupts = <12>;
+ clock = <&ref24_clk 0>;
};
uart1: uart@101f2000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f2000 0x1000>;
interrupts = <13>;
+ clock = <&ref24_clk 0>;
};
uart2: uart@101f3000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f3000 0x1000>;
interrupts = <14>;
+ clock = <&ref24_clk 0>;
};
smc@10100000 {
@@ -108,6 +140,7 @@
compatible = "arm,pl110", "arm,primecell";
reg = <0x10120000 0x1000>;
interrupts = <16>;
+ clock = <&osc4_clk 0>;
};
sctl@101e0000 {
@@ -157,6 +190,7 @@
compatible = "arm,pl022", "arm,primecell";
reg = <0x101f4000 0x1000>;
interrupts = <11>;
+ clock = <&ref24_clk 0>;
};
fpga {
@@ -174,18 +208,21 @@
compatible = "arm,primecell";
reg = < 0x5000 0x1000>;
interrupts = <22>;
+ clock = <&ref24_clk 0>;
};
kmi@6000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x6000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <3>;
+ clock = <&ref24_clk 0>;
};
kmi@7000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x7000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <4>;
+ clock = <&ref24_clk 0>;
};
};
};
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 1664610..05e014a 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -31,6 +31,7 @@
reg = <0x9000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <6>;
+ clock = <&ref24_clk 0>;
};
sci@a000 {
compatible = "arm,primecell";
@@ -42,6 +43,7 @@
compatible = "arm,primecell";
reg = <0xb000 0x1000>;
interrupts = <23>;
+ clock = <&ref24_clk 0>;
};
};
};
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e340a54..4cd9822 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -666,44 +666,11 @@ static struct amba_device *amba_devs[] __initdata = {
/*
* Lookup table for attaching a specific name and platform_data pointer to
* devices as they get created by of_platform_populate(). Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
+ * would not exist, but some devices still need platform data.
*/
struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL),
-
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL),
-#if 0
- /*
- * These entries are unnecessary because no clocks referencing
- * them. I've left them in for now as place holders in case
- * any of them need to be added back, but they should be
- * removed before actually committing this patch. --gcl
- */
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_AACI_BASE, "fpga:04", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI1_BASE, "fpga:0a", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SMC_BASE, "dev:00", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MPMC_BASE, "dev:10", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_DMAC_BASE, "dev:30", NULL),
-
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCTL_BASE, "dev:e0", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_WATCHDOG_BASE, "dev:e1", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO0_BASE, "dev:e4", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO1_BASE, "dev:e5", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO2_BASE, "dev:e6", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO3_BASE, "dev:e7", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_RTC_BASE, "dev:e8", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI_BASE, "dev:f0", NULL),
-#endif
+ OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, NULL, &clcd_plat_data),
{}
};
#endif
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
index 54e037c..f11f6d0 100644
--- a/arch/arm/mach-versatile/versatile_dt.c
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -24,13 +24,46 @@
#include <linux/init.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/of_clk.h>
+#include <linux/slab.h>
+
+#include <mach/hardware.h>
+#include <mach/clkdev.h>
+#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "core.h"
+/* Scan for fixed clocks */
+static struct clk *versatile_dt_clk_get(struct of_phandle_args *a, void *data)
+{
+ return data;
+}
+
static void __init versatile_dt_init(void)
{
+ struct device_node *node;
+ struct clk *clk;
+ int rc;
+
+ for_each_compatible_node(node, NULL, "fixed-clock") {
+ u32 rate;
+ if (of_property_read_u32(node, "clock-frequency", &rate))
+ continue;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ panic("out of memory\n");
+ clk->rate = rate;
+
+ rc = of_clk_add_provider(node, versatile_dt_clk_get, clk);
+ if (rc) {
+ kfree(clk);
+ pr_err("error adding fixed clk %s\n", node->name);
+ }
+ }
+
of_platform_populate(NULL, of_default_bus_match_table,
versatile_auxdata_lookup, NULL);
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 34+ messages in thread