From a81dd364de50bc1eb1519af0ecfa100753a09351 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 21 Sep 2011 09:19:16 -0600 Subject: devicetree: Add a registry of vendor prefixes There is no centralized listing for the in-use vendor prefixes used in compatible strings and property names. This patch adds one. New prefixes should get added to this list to reduce the likelyhood of namespace collisions. Signed-off-by: Grant Likely --- .../devicetree/bindings/vendor-prefixes.txt | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/vendor-prefixes.txt diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt new file mode 100644 index 00000000000..81465c1cc6b --- /dev/null +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -0,0 +1,38 @@ +Device tree binding vendor prefix registry. Keep list in alphabetical order. + +This isn't an exhaustive list, but you should add new prefixes to it before +using them to avoid name-space collisions. + +adi Analog Devices, Inc. +amcc Applied Micro Circuits Corporation (APM, formally AMCC) +apm Applied Micro Circuits Corporation (APM) +arm ARM Ltd. +chrp Common Hardware Reference Platform +dallas Maxim Integrated Products (formerly Dallas Semiconductor) +denx Denx Software Engineering +epson Seiko Epson Corp. +est ESTeem Wireless Modems +fsl Freescale Semiconductor +GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. +gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. +hp Hewlett Packard +ibm International Business Machines (IBM) +idt Integrated Device Technologies, Inc. +intercontrol Inter Control Group +linux Linux-specific binding +marvell Marvell Technology Group Ltd. +maxim Maxim Integrated Products +mosaixtech Mosaix Technologies, Inc. +national National Semiconductor +nintendo Nintendo +nvidia NVIDIA +nxp NXP Semiconductors +powervr Imagination Technologies +ramtron Ramtron International +samsung Samsung Semiconductor +schindler Schindler +simtek +sirf SiRF Technology, Inc. +stericsson ST-Ericsson +ti Texas Instruments +xlnx Xilinx -- cgit v1.2.3 From 611cad720148c899db5a383c1c676fd820df7023 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 15 Aug 2011 15:28:14 +0800 Subject: dt: add of_alias_scan and of_alias_get_id The patch adds function of_alias_scan to populate a global lookup table with the properties of 'aliases' node and function of_alias_get_id for drivers to find alias id from the lookup table. v3: Split out automatic addition of aliases on id lookup so that it can be debated separately from the core functionality. v2: - Add of_chosen/of_aliases populating and of_alias_scan() invocation for OF_PROMTREE. - Add locking - rework parse loop Signed-off-by: Shawn Guo Acked-by: David S. Miller Signed-off-by: Grant Likely --- drivers/of/base.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/of/fdt.c | 6 +-- drivers/of/pdt.c | 8 ++++ include/linux/of.h | 7 ++++ 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 3ff22e32b60..8abde58cbe8 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -17,14 +17,39 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include #include #include +/** + * struct alias_prop - Alias property in 'aliases' node + * @link: List node to link the structure in aliases_lookup list + * @alias: Alias property name + * @np: Pointer to device_node that the alias stands for + * @id: Index value from end of alias name + * @stem: Alias string without the index + * + * The structure represents one alias property of 'aliases' node as + * an entry in aliases_lookup list. + */ +struct alias_prop { + struct list_head link; + const char *alias; + struct device_node *np; + int id; + char stem[0]; +}; + +static LIST_HEAD(aliases_lookup); + struct device_node *allnodes; struct device_node *of_chosen; +struct device_node *of_aliases; + +static DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. @@ -988,3 +1013,99 @@ out_unlock: } #endif /* defined(CONFIG_OF_DYNAMIC) */ +static void of_alias_add(struct alias_prop *ap, struct device_node *np, + int id, const char *stem, int stem_len) +{ + ap->np = np; + ap->id = id; + strncpy(ap->stem, stem, stem_len); + ap->stem[stem_len] = 0; + list_add_tail(&ap->link, &aliases_lookup); + pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", + ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); +} + +/** + * of_alias_scan - Scan all properties of 'aliases' node + * + * The function scans all the properties of 'aliases' node and populate + * the the global lookup table with the properties. It returns the + * number of alias_prop found, or error code in error case. + * + * @dt_alloc: An allocator that provides a virtual address to memory + * for the resulting tree + */ +void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) +{ + struct property *pp; + + of_chosen = of_find_node_by_path("/chosen"); + if (of_chosen == NULL) + of_chosen = of_find_node_by_path("/chosen@0"); + of_aliases = of_find_node_by_path("/aliases"); + if (!of_aliases) + return; + + for_each_property(pp, of_aliases->properties) { + const char *start = pp->name; + const char *end = start + strlen(start); + struct device_node *np; + struct alias_prop *ap; + int id, len; + + /* Skip those we do not want to proceed */ + if (!strcmp(pp->name, "name") || + !strcmp(pp->name, "phandle") || + !strcmp(pp->name, "linux,phandle")) + continue; + + np = of_find_node_by_path(pp->value); + if (!np) + continue; + + /* walk the alias backwards to extract the id and work out + * the 'stem' string */ + while (isdigit(*(end-1)) && end > start) + end--; + len = end - start; + + if (kstrtoint(end, 10, &id) < 0) + continue; + + /* Allocate an alias_prop with enough space for the stem */ + ap = dt_alloc(sizeof(*ap) + len + 1, 4); + if (!ap) + continue; + ap->alias = start; + of_alias_add(ap, np, id, start, len); + } +} + +/** + * of_alias_get_id - Get alias id for the given device_node + * @np: Pointer to the given device_node + * @stem: Alias stem of the given device_node + * + * The function travels the lookup table to get alias id for the given + * device_node and alias stem. It returns the alias id if find it. + */ +int of_alias_get_id(struct device_node *np, const char *stem) +{ + struct alias_prop *app; + int id = -ENODEV; + + mutex_lock(&of_aliases_mutex); + list_for_each_entry(app, &aliases_lookup, link) { + if (strcmp(app->stem, stem) != 0) + continue; + + if (np == app->np) { + id = app->id; + break; + } + } + mutex_unlock(&of_aliases_mutex); + + return id; +} +EXPORT_SYMBOL_GPL(of_alias_get_id); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 65200af29c5..aeec35bc378 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -707,10 +707,8 @@ void __init unflatten_device_tree(void) __unflatten_device_tree(initial_boot_params, &allnodes, early_init_dt_alloc_memory_arch); - /* Get pointer to OF "/chosen" node for use everywhere */ - of_chosen = of_find_node_by_path("/chosen"); - if (of_chosen == NULL) - of_chosen = of_find_node_by_path("/chosen@0"); + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */ + of_alias_scan(early_init_dt_alloc_memory_arch); } #endif /* CONFIG_OF_EARLY_FLATTREE */ diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 4d87b5dc928..bc5b3990f6e 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent, return ret; } +static void *kernel_tree_alloc(u64 size, u64 align) +{ + return prom_early_alloc(size); +} + void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) { struct device_node **nextp; @@ -245,4 +250,7 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) nextp = &allnodes->allnext; allnodes->child = of_pdt_build_tree(allnodes, of_pdt_prom_ops->getchild(allnodes->phandle), &nextp); + + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */ + of_alias_scan(kernel_tree_alloc); } diff --git a/include/linux/of.h b/include/linux/of.h index 9180dc5cb00..8b6383d876c 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -68,6 +68,7 @@ struct device_node { /* Pointer for first entry in chain of all nodes. */ extern struct device_node *allnodes; extern struct device_node *of_chosen; +extern struct device_node *of_aliases; extern rwlock_t devtree_lock; static inline bool of_have_populated_dt(void) @@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device); extern const void *of_get_property(const struct device_node *node, const char *name, int *lenp); +#define for_each_property(pp, properties) \ + for (pp = properties; pp != NULL; pp = pp->next) + 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( @@ -221,6 +225,9 @@ extern int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct device_node **out_node, const void **out_args); +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); + extern int of_machine_is_compatible(const char *compat); extern int prom_add_property(struct device_node* np, struct property* prop); -- cgit v1.2.3 From ff05967a07225ab675f6e03eb2d9c155d8c8671c Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 22 Sep 2011 14:48:13 +0800 Subject: serial/imx: add of_alias_get_id() reference back As of_alias_get_id() gets fixed and ready for use, the patch adds the of_alias_get_id() reference back to imx serial driver. Signed-off-by: Shawn Guo [grant.likely: changed pr_err() to dev_err(), dropped unnecessary else] Signed-off-by: Grant Likely --- drivers/tty/serial/imx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 7e91b3d368c..99898773706 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1286,17 +1286,20 @@ static int serial_imx_resume(struct platform_device *dev) static int serial_imx_probe_dt(struct imx_port *sport, struct platform_device *pdev) { - static int portnum = 0; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(imx_uart_dt_ids, &pdev->dev); + int ret; if (!np) return -ENODEV; - sport->port.line = portnum++; - if (sport->port.line >= UART_NR) - return -EINVAL; + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); + return -ENODEV; + } + sport->port.line = ret; if (of_get_property(np, "fsl,uart-has-rtscts", NULL)) sport->have_rtscts = 1; -- cgit v1.2.3 From 987bfad6429aa3aefbc196bd0fc90fc48409a87b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 21 Sep 2011 14:54:29 -0600 Subject: devicetree: Document Qualcomm and Atmel prefixes Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/vendor-prefixes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 81465c1cc6b..e8552782b44 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -7,6 +7,7 @@ adi Analog Devices, Inc. amcc Applied Micro Circuits Corporation (APM, formally AMCC) apm Applied Micro Circuits Corporation (APM) arm ARM Ltd. +atmel Atmel Corporation chrp Common Hardware Reference Platform dallas Maxim Integrated Products (formerly Dallas Semiconductor) denx Denx Software Engineering @@ -28,6 +29,7 @@ nintendo Nintendo nvidia NVIDIA nxp NXP Semiconductors powervr Imagination Technologies +qcom Qualcomm, Inc. ramtron Ramtron International samsung Samsung Semiconductor schindler Schindler -- cgit v1.2.3 From aba3dfff9a75eb272c4f47994f16eb5d548a5af1 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 21 Sep 2011 13:23:10 -0600 Subject: dt: add empty for_each_child_of_node, of_find_property The patch adds a couple empty functions for non-dt build, so that drivers migrating to dt can save some '#ifdef CONFIG_OF'. Signed-off-by: Stephen Warren Signed-off-by: Grant Likely --- include/linux/of.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 8b6383d876c..83a61f3b443 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -249,6 +249,16 @@ static inline bool of_have_populated_dt(void) return false; } +#define for_each_child_of_node(parent, child) \ + while (0) + +static inline struct property *of_find_property(const struct device_node *np, + const char *name, + int *lenp) +{ + return NULL; +} + static inline int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz) -- cgit v1.2.3 From 3a1e362e3f3cd571b3974b8d44b8e358ec7a098c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 3 Aug 2011 10:11:42 +0100 Subject: OF: Add of_match_ptr() macro Add a macro of_match_ptr() that allows the .of_match_table entry in the driver structures to be assigned without having an #ifdef xxx NULL for the case that OF is not enabled Signed-off-by: Ben Dooks Signed-off-by: Grant Likely --- include/linux/of.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 83a61f3b443..53107b09cbd 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -242,6 +242,7 @@ extern void of_attach_node(struct device_node *); extern void of_detach_node(struct device_node *); #endif +#define of_match_ptr(_ptr) (_ptr) #else /* CONFIG_OF */ static inline bool of_have_populated_dt(void) @@ -280,6 +281,7 @@ static inline const void *of_get_property(const struct device_node *node, return NULL; } +#define of_match_ptr(_ptr) NULL #endif /* CONFIG_OF */ static inline int of_property_read_u32(const struct device_node *np, -- cgit v1.2.3 From 85888069cf5d0f21312e3ee730458a5e3a553509 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 3 Aug 2011 10:11:43 +0100 Subject: tty: use of_match_ptr() for of_match_table entry Use the new of_match_ptr() macro for the of_match_table pointer entry to avoid having to #dfine match NULL Signed-off-by: Ben Dooks Signed-off-by: Grant Likely --- drivers/tty/serial/altera_jtaguart.c | 4 +--- drivers/tty/serial/altera_uart.c | 4 +--- drivers/tty/serial/uartlite.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 60e049b041a..20752006925 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -472,8 +472,6 @@ static struct of_device_id altera_jtaguart_match[] = { {}, }; MODULE_DEVICE_TABLE(of, altera_jtaguart_match); -#else -#define altera_jtaguart_match NULL #endif /* CONFIG_OF */ static struct platform_driver altera_jtaguart_platform_driver = { @@ -482,7 +480,7 @@ static struct platform_driver altera_jtaguart_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .of_match_table = altera_jtaguart_match, + .of_match_table = of_match_ptr(altera_jtaguart_match), }, }; diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 50bc5a5ac65..0abd31d2361 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -616,8 +616,6 @@ static struct of_device_id altera_uart_match[] = { {}, }; MODULE_DEVICE_TABLE(of, altera_uart_match); -#else -#define altera_uart_match NULL #endif /* CONFIG_OF */ static struct platform_driver altera_uart_platform_driver = { @@ -626,7 +624,7 @@ static struct platform_driver altera_uart_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .of_match_table = altera_uart_match, + .of_match_table = of_match_ptr(altera_uart_match), }, }; diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 8af1ed83a4c..0aed022d21b 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -568,8 +568,6 @@ static struct of_device_id ulite_of_match[] __devinitdata = { {} }; MODULE_DEVICE_TABLE(of, ulite_of_match); -#else /* CONFIG_OF */ -#define ulite_of_match NULL #endif /* CONFIG_OF */ static int __devinit ulite_probe(struct platform_device *pdev) @@ -609,7 +607,7 @@ static struct platform_driver ulite_platform_driver = { .driver = { .owner = THIS_MODULE, .name = "uartlite", - .of_match_table = ulite_of_match, + .of_match_table = of_match_ptr(ulite_of_match), }, }; -- cgit v1.2.3 From 4cd7f7a31178ff8a15ad2bc1258b9b2bf2cf51a4 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Wed, 14 Sep 2011 20:49:59 +0100 Subject: dt: add helper to read 64-bit integers Add a helper similar to of_property_read_u32() that handles 64-bit integers. v2/v3: constify device node and property name parameters. Cc: Grant Likely Reviewed-by: Rob Herring Signed-off-by: Jamie Iles Signed-off-by: Grant Likely --- drivers/of/base.c | 29 +++++++++++++++++++++++++++++ include/linux/of.h | 8 ++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 8abde58cbe8..b970562e011 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -656,6 +656,35 @@ int of_property_read_u32_array(const struct device_node *np, } EXPORT_SYMBOL_GPL(of_property_read_u32_array); +/** + * of_property_read_u64 - Find and read a 64 bit integer from a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_value: pointer to return value, modified only if return value is 0. + * + * Search for a property in a device node and read a 64-bit value from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u64 value can be decoded. + */ +int of_property_read_u64(const struct device_node *np, const char *propname, + u64 *out_value) +{ + struct property *prop = of_find_property(np, propname, NULL); + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + if (sizeof(*out_value) > prop->length) + return -EOVERFLOW; + *out_value = of_read_number(prop->value, 2); + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u64); + /** * of_property_read_string - Find and read a string from a property * @np: device node from which the property value is to be read. diff --git a/include/linux/of.h b/include/linux/of.h index 53107b09cbd..1cc9930ba06 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -200,6 +200,8 @@ extern int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); +extern int of_property_read_u64(const struct device_node *np, + const char *propname, u64 *out_value); extern int of_property_read_string(struct device_node *np, const char *propname, @@ -281,6 +283,12 @@ static inline const void *of_get_property(const struct device_node *node, return NULL; } +static inline int of_property_read_u64(const struct device_node *np, + const char *propname, u64 *out_value) +{ + return -ENOSYS; +} + #define of_match_ptr(_ptr) NULL #endif /* CONFIG_OF */ -- cgit v1.2.3 From f910b831c9647d85dc6f13e3b8698d10cbfd5011 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 14 Sep 2011 07:40:10 -0500 Subject: MAINTAINERS: update devicetree maintainers As requested by Grant, adding myself as an additional devicetree maintainer. Also, add Documentation/devicetree to the file list for devicetree. Signed-off-by: Rob Herring Acked-by: Grant Likely --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ace8f9c81b9..046526a647c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4728,10 +4728,12 @@ F: drivers/i2c/busses/i2c-ocores.c OPEN FIRMWARE AND FLATTENED DEVICE TREE M: Grant Likely +M: Rob Herring L: devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers) W: http://fdt.secretlab.ca T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained +F: Documentation/devicetree F: drivers/of F: include/linux/of*.h K: of_get_property -- cgit v1.2.3 From dc9372808412edbc653a675a526c2ee6c0c14a91 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 20 Sep 2011 13:02:54 -0500 Subject: of/irq: of_irq_find_parent: check for parent equal to child An interrupt controller may often implicitly inherit itself from a parent node when in fact the controller is the interrupt root controller. Guard against the case of child == parent and return NULL in this case. This can also be fixed by adding an explicit "interrupt-parent;" to a root interrupt controller node. Based on code from Grant Likely. Signed-off-by: Rob Herring Cc: Grant Likely --- drivers/of/irq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9f689f1da0f..6a5b5e777dd 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -58,27 +58,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); */ struct device_node *of_irq_find_parent(struct device_node *child) { - struct device_node *p; + struct device_node *p, *c = child; const __be32 *parp; - if (!of_node_get(child)) + if (!of_node_get(c)) return NULL; do { - parp = of_get_property(child, "interrupt-parent", NULL); + parp = of_get_property(c, "interrupt-parent", NULL); if (parp == NULL) - p = of_get_parent(child); + p = of_get_parent(c); else { if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) p = of_node_get(of_irq_dflt_pic); else p = of_find_node_by_phandle(be32_to_cpup(parp)); } - of_node_put(child); - child = p; + of_node_put(c); + c = p; } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); - return p; + return (p == child) ? NULL : p; } /** -- cgit v1.2.3 From f614c74f94f435adcbe52bf7682f1dcc805f0ab1 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 23 Sep 2011 09:55:54 -0500 Subject: devicetree: Add ARM pl061 gpio controller binding doc Add binding documentation for ARM's Primecell PL061 GPIO controller. Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/gpio/pl061-gpio.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/pl061-gpio.txt diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt new file mode 100644 index 00000000000..a2c416bcbcc --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt @@ -0,0 +1,10 @@ +ARM PL061 GPIO controller + +Required properties: +- compatible : "arm,pl061", "arm,primecell" +- #gpio-cells : Should be two. The first cell is the pin number and the + second cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- gpio-controller : Marks the device node as a GPIO controller. +- interrupts : Interrupt mapping for GPIO IRQ. + -- cgit v1.2.3 From 6add6967a4a57e2156b96e62f28bcbe1901d16c1 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 23 Sep 2011 09:56:53 -0500 Subject: devicetree: Add ARM pl022 spi controller binding doc Add binding documentation for ARM's Primecell PL022 SPI controller. Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/spi/spi_pl022.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/spi_pl022.txt diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt new file mode 100644 index 00000000000..306ec3ff3c0 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt @@ -0,0 +1,12 @@ +ARM PL022 SPI controller + +Required properties: +- compatible : "arm,pl022", "arm,primecell" +- reg : Offset and length of the register set for the device +- interrupts : Should contain SPI controller interrupt + +Optional properties: +- cs-gpios : should specify GPIOs used for chipselects. + The gpios will be referred to as reg = in the SPI child nodes. + If unspecified, a single SPI device without a chip select can be used. + -- cgit v1.2.3 From 6b3754d6183797263bc6b28884323cf7842a8961 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 5 Oct 2011 11:18:40 -0600 Subject: devicetree: fix build error on drivers/tty/serial/altera_jtaguart.c This patch fixes the following build error caused by commit 85888069cf5d ("tty: use of_match_ptr() for of_match_table entry"). The problem was a missing #include which is where of_match_ptr() is defined. drivers/tty/serial/altera_jtaguart.c:483:3: error: implicit declaration of function 'of_match_ptr' [-Werror=implicit-function-declaration] drivers/tty/serial/altera_jtaguart.c:483:34: error: 'altera_jtaguart_match' undeclared here (not in a function) Signed-off-by: Grant Likely Cc: Ben Dooks Cc: Tobias Klauser (maintainer:ALTERA UART/JTAG...) Cc: Alan Cox (maintainer:SERIAL DRIVERS) --- drivers/tty/serial/altera_jtaguart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 20752006925..af46c56080d 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 36a0904ea0a657567122edebb95eab5f1620a5eb Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 10 Oct 2011 21:49:35 +0530 Subject: dt: add empty dt helpers for non-dt build Add empty of_device_is_compatible() and of_parse_phandle() for non-dt builds to work. Signed-off-by: Rajendra Nayak Signed-off-by: Grant Likely --- include/linux/of.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 1cc9930ba06..736b7477beb 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -255,6 +255,12 @@ static inline bool of_have_populated_dt(void) #define for_each_child_of_node(parent, child) \ while (0) +static inline int of_device_is_compatible(const struct device_node *device, + const char *name) +{ + return 0; +} + static inline struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) @@ -289,6 +295,13 @@ static inline int of_property_read_u64(const struct device_node *np, return -ENOSYS; } +static inline struct device_node *of_parse_phandle(struct device_node *np, + const char *phandle_name, + int index) +{ + return NULL; +} + #define of_match_ptr(_ptr) NULL #endif /* CONFIG_OF */ -- cgit v1.2.3 From 5762c20593b6b959f1470dc6f1ff4ca4d9570f8d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 24 Oct 2011 11:53:32 +0200 Subject: dt: Add empty of_match_node() macro Add an empty macro for of_match_node() that will save some '#ifdef CONFIG_OF' for non-dt builds. I have chosen to use a macro instead of a function to be able to avoid defining the first parameter. In fact, this "struct of_device_id *" first parameter is usualy not defined as well on non-dt builds. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely --- include/linux/of.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/of.h b/include/linux/of.h index 736b7477beb..92c40a14224 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,7 @@ static inline struct device_node *of_parse_phandle(struct device_node *np, } #define of_match_ptr(_ptr) NULL +#define of_match_node(_matches, _node) NULL #endif /* CONFIG_OF */ static inline int of_property_read_u32(const struct device_node *np, -- cgit v1.2.3 From 2b0fce8da2f5b6dc9661be540982416a9e2267f8 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 24 Oct 2011 11:09:14 +0200 Subject: Devicetree: Expand on ARM Primecell binding documentation Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/arm/primecell.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt index 1d5d7a870ec..951ca46789d 100644 --- a/Documentation/devicetree/bindings/arm/primecell.txt +++ b/Documentation/devicetree/bindings/arm/primecell.txt @@ -6,7 +6,9 @@ driver matching. Required properties: -- compatible : should be a specific value for peripheral and "arm,primecell" +- compatible : should be a specific name for the peripheral and + "arm,primecell". The specific name will match the ARM + engineering name for the logic block in the form: "arm,pl???" Optional properties: -- cgit v1.2.3 From 0b4ae4cceaf3cea9b154a6301e486fb5bc16aef2 Mon Sep 17 00:00:00 2001 From: John Bonesio Date: Mon, 24 Oct 2011 11:09:06 +0200 Subject: dt: Add id to AUXDATA structure This patch adds the ability to set the device id in the AUXDATA structure for those few device drivers that just have to have a statically defined device id. Signed-off-by: John Bonesio Signed-off-by: Grant Likely --- drivers/of/platform.c | 7 +++++++ include/linux/of_platform.h | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ed5a6d3c26a..b22f8873a41 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -345,6 +345,7 @@ static int of_platform_bus_create(struct device_node *bus, struct platform_device *dev; const char *bus_id = NULL; void *platform_data = NULL; + int id = -1; int rc = 0; /* Make sure it has a compatible property */ @@ -357,6 +358,7 @@ static int of_platform_bus_create(struct device_node *bus, auxdata = of_dev_lookup(lookup, bus); if (auxdata) { bus_id = auxdata->name; + id = auxdata->id; platform_data = auxdata->platform_data; } @@ -366,6 +368,11 @@ static int of_platform_bus_create(struct device_node *bus, } dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent); + + /* override the id if auxdata gives an id */ + if (id != -1) + dev->id = id; + if (!dev || !of_match_node(matches, bus)) return 0; diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 5a6f458a4bb..0c53ecbd937 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -45,13 +45,18 @@ struct of_dev_auxdata { char *compatible; resource_size_t phys_addr; char *name; + int id; void *platform_data; }; /* Macro to simplify populating a lookup table */ #define OF_DEV_AUXDATA(_compat,_phys,_name,_pdata) \ { .compatible = _compat, .phys_addr = _phys, .name = _name, \ - .platform_data = _pdata } + .id = -1, .platform_data = _pdata } + +#define OF_DEV_AUXDATA_ID(_compat,_phys,_name,_id,_pdata) \ + { .compatible = _compat, .phys_addr = _phys, .name = _name, \ + .id = _id, .platform_data = _pdata } /** * of_platform_driver - Legacy of-aware driver for platform devices. -- cgit v1.2.3 From 713e71903a46198c88a9f772e2db10a3a488d41e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 24 Oct 2011 11:09:07 +0200 Subject: arm/dt: add versatile dtb build rules Makes 'make dtbs' build the versatile .dtb files when versatile is enabled. Signed-off-by: Grant Likely --- arch/arm/mach-versatile/Makefile.boot | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-versatile/Makefile.boot b/arch/arm/mach-versatile/Makefile.boot index c7e75acfe6c..c08ab6da090 100644 --- a/arch/arm/mach-versatile/Makefile.boot +++ b/arch/arm/mach-versatile/Makefile.boot @@ -2,3 +2,5 @@ params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 +dtb-$(CONFIG_MACH_VERSATILE_DT) += versatile-pb.dtb +dtb-$(CONFIG_MACH_VERSATILE_DT) += versatile-ab.dtb -- cgit v1.2.3 From 2dd61d2ca0ed6f81108635bb145170bbbf611d29 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 24 Oct 2011 11:09:10 +0200 Subject: arm/dt: omap3 basic device tree board support Enable basic device tree support for the Gumstix Overo, IGEP, Panda and Beagle OMAP boards Signed-off-by: Andy Doan Signed-off-by: Jon Medhurst Signed-off-by: Grant Likely --- arch/arm/boot/dts/isee-igep-v2.dts | 7 +++++++ arch/arm/boot/dts/isee-igep-v3.dts | 7 +++++++ arch/arm/boot/dts/omap3-beagle.dts | 7 +++++++ arch/arm/boot/dts/omap3-overo.dts | 7 +++++++ arch/arm/boot/dts/omap4-panda.dts | 11 +++++++++++ arch/arm/mach-omap2/Makefile.boot | 6 ++++++ arch/arm/mach-omap2/board-igep0020.c | 12 ++++++++++++ arch/arm/mach-omap2/board-omap3beagle.c | 6 ++++++ arch/arm/mach-omap2/board-omap4panda.c | 6 ++++++ arch/arm/mach-omap2/board-overo.c | 6 ++++++ 10 files changed, 75 insertions(+) create mode 100644 arch/arm/boot/dts/isee-igep-v2.dts create mode 100644 arch/arm/boot/dts/isee-igep-v3.dts create mode 100644 arch/arm/boot/dts/omap3-beagle.dts create mode 100644 arch/arm/boot/dts/omap3-overo.dts create mode 100644 arch/arm/boot/dts/omap4-panda.dts diff --git a/arch/arm/boot/dts/isee-igep-v2.dts b/arch/arm/boot/dts/isee-igep-v2.dts new file mode 100644 index 00000000000..72caabb85b7 --- /dev/null +++ b/arch/arm/boot/dts/isee-igep-v2.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ISSE IGEPv2 Board"; + compatible = "ISEE,igep-v2"; +}; diff --git a/arch/arm/boot/dts/isee-igep-v3.dts b/arch/arm/boot/dts/isee-igep-v3.dts new file mode 100644 index 00000000000..f40886fef69 --- /dev/null +++ b/arch/arm/boot/dts/isee-igep-v3.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ISSE IGEPv3 Module"; + compatible = "ISEE,igep-v3"; +}; diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts new file mode 100644 index 00000000000..44394660006 --- /dev/null +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "TI OMAP3 BeagleBoard"; + compatible = "ti,omap3-beagle"; +}; diff --git a/arch/arm/boot/dts/omap3-overo.dts b/arch/arm/boot/dts/omap3-overo.dts new file mode 100644 index 00000000000..c61f0112bf3 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Gumstix Overo"; + compatible = "gumstix,omap3-overo"; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts new file mode 100644 index 00000000000..58909e9b664 --- /dev/null +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/memreserve/ 0x9D000000 0x03000000; /* Frame buffer */ +/memreserve/ 0xB0000000 0x10000000; /* Top 256MB is unaccessable */ + +/include/ "skeleton.dtsi" + +/ { + model = "TI OMAP4 PandaBoard"; + compatible = "ti,omap4-panda", "ti,omap4430"; +}; diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot index 565aff7f37a..422c1700ccf 100644 --- a/arch/arm/mach-omap2/Makefile.boot +++ b/arch/arm/mach-omap2/Makefile.boot @@ -1,3 +1,9 @@ zreladdr-y := 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x80800000 + +dtb-$(CONFIG_MACH_OMAP3_BEAGLE) += omap3-beagle.dtb +dtb-$(CONFIG_MACH_OMAP4_PANDA) += omap4-panda.dtb +dtb-$(CONFIG_MACH_OVERO) += omap3-overo.dtb +dtb-$(CONFIG_MACH_IGEP0020) += isee-igep-v2.dtb +dtb-$(CONFIG_MACH_IGEP0030) += isee-igep-v3.dtb diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 35be778caf1..7c3ba8b443e 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -671,6 +671,11 @@ static void __init igep_init(void) } } +static const char *igep2_dt_compat[] = { + "ISEE,igep-v2", + NULL +}; + MACHINE_START(IGEP0020, "IGEP v2 board") .boot_params = 0x80000100, .reserve = omap_reserve, @@ -679,8 +684,14 @@ MACHINE_START(IGEP0020, "IGEP v2 board") .init_irq = omap3_init_irq, .init_machine = igep_init, .timer = &omap3_timer, + .dt_compat = igep2_dt_compat, MACHINE_END +static const char *igep3_dt_compat[] = { + "ISEE,igep-v3", + NULL +}; + MACHINE_START(IGEP0030, "IGEP OMAP3 module") .boot_params = 0x80000100, .reserve = omap_reserve, @@ -689,4 +700,5 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module") .init_irq = omap3_init_irq, .init_machine = igep_init, .timer = &omap3_timer, + .dt_compat = &igep3_dt_compat, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 3ae16b4e3f5..e55a37b9e5f 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -555,6 +555,11 @@ static void __init omap3_beagle_init(void) beagle_opp_init(); } +static const char *omap3_beagle_dt_match[] = { + "ti,omap3-beagle", + NULL +}; + MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ .boot_params = 0x80000100, @@ -564,4 +569,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") .init_irq = omap3_beagle_init_irq, .init_machine = omap3_beagle_init, .timer = &omap3_secure_timer, + .dt_compat = omap3_beagle_dt_match, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 9aaa9605766..f5d18d71915 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -581,6 +581,11 @@ static void __init omap4_panda_map_io(void) omap44xx_map_common_io(); } +static const char *omap4_panda_match[] = { + "ti,omap4-panda", + NULL, +}; + MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") /* Maintainer: David Anders - Texas Instruments Inc */ .boot_params = 0x80000100, @@ -590,4 +595,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") .init_irq = gic_init_irq, .init_machine = omap4_panda_init, .timer = &omap4_timer, + .dt_compat = omap4_panda_match, MACHINE_END diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index f949a9954d7..c947db7b10f 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -560,6 +560,11 @@ static void __init overo_init(void) "OVERO_GPIO_USBH_CPEN\n"); } +static const char *omap3_overo_dt_match[] = { + "gumstix,omap3-overo", + NULL +}; + MACHINE_START(OVERO, "Gumstix Overo") .boot_params = 0x80000100, .reserve = omap_reserve, @@ -568,4 +573,5 @@ MACHINE_START(OVERO, "Gumstix Overo") .init_irq = omap3_init_irq, .init_machine = overo_init, .timer = &omap3_timer, + .dt_compat = omap3_overo_dt_match, MACHINE_END -- cgit v1.2.3 From 2f1c7786a7c5c86d79557de5204ba219b87c6688 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 24 Oct 2011 11:09:11 +0200 Subject: arm/dt: Add basic device tree support for smdkv310 board Enable basic device tree support for Exynos4 smdkv310 board. Signed-off-by: Thomas Abraham Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/arm/samsung.txt | 9 +++++++++ arch/arm/boot/dts/exynos4-smdkv310.dts | 11 +++++++++++ arch/arm/mach-exynos4/Makefile.boot | 2 ++ arch/arm/mach-exynos4/mach-smdkv310.c | 6 ++++++ 4 files changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/samsung.txt create mode 100644 arch/arm/boot/dts/exynos4-smdkv310.dts diff --git a/Documentation/devicetree/bindings/arm/samsung.txt b/Documentation/devicetree/bindings/arm/samsung.txt new file mode 100644 index 00000000000..594cb97e3d8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/samsung.txt @@ -0,0 +1,9 @@ +Samsung Exynos4 S5PV310 SoC based SMDKV310 eval board + + SMDKV310 eval board is based on S5PV310 SoC which belongs to + Samsung's Exynos4 family of application processors. + +Required root node properties: + - compatible = "samsung,smdkv310","samsung,s5pv310" + (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board. + (b) "samsung,s5pv310" - for boards based on S5PV310 SoC. diff --git a/arch/arm/boot/dts/exynos4-smdkv310.dts b/arch/arm/boot/dts/exynos4-smdkv310.dts new file mode 100644 index 00000000000..dd6c80a7ffc --- /dev/null +++ b/arch/arm/boot/dts/exynos4-smdkv310.dts @@ -0,0 +1,11 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Samsung Exynos4 SMDKV310 eval board"; + compatible = "samsung,smdkv310", "samsung,s5pv310"; + + memory { + reg = <0x40000000 0x08000000>; + }; +}; diff --git a/arch/arm/mach-exynos4/Makefile.boot b/arch/arm/mach-exynos4/Makefile.boot index d65956ffb43..fcee6b5384a 100644 --- a/arch/arm/mach-exynos4/Makefile.boot +++ b/arch/arm/mach-exynos4/Makefile.boot @@ -1,2 +1,4 @@ zreladdr-y := 0x40008000 params_phys-y := 0x40000100 + +dtb-$(CONFIG_MACH_SMDKV310) += exynos4-smdkv310.dtb diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c index ea414955686..0a54ede1bf2 100644 --- a/arch/arm/mach-exynos4/mach-smdkv310.c +++ b/arch/arm/mach-exynos4/mach-smdkv310.c @@ -252,6 +252,11 @@ static void __init smdkv310_machine_init(void) platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); } +static char const *smdkv310_dt_compat[] __initdata = { + "samsung,smdkv310", + NULL +}; + MACHINE_START(SMDKV310, "SMDKV310") /* Maintainer: Kukjin Kim */ /* Maintainer: Changhwan Youn */ @@ -260,4 +265,5 @@ MACHINE_START(SMDKV310, "SMDKV310") .map_io = smdkv310_map_io, .init_machine = smdkv310_machine_init, .timer = &exynos4_timer, + .dt_compat = smdkv310_dt_compat, MACHINE_END -- cgit v1.2.3 From 27344ef04f7b3e5e6a4f9c47625b85f8d4ca624f Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 24 Oct 2011 11:09:11 +0200 Subject: arm/dt: Add basic device tree support for mx51 and mx53 boards This patch add support for the Genesi Efika MX Smarttop and Smartbook, the Freescale mx51 babbage board, and the Freescale mx53 loco board Signed-off-by: Jason Liu Signed-off-by: Grant Likely --- .../devicetree/bindings/arm/freescale.txt | 7 +++++++ Documentation/devicetree/bindings/arm/genesi.txt | 8 ++++++++ arch/arm/boot/dts/genesi-efikamx.dts | 22 ++++++++++++++++++++++ arch/arm/boot/dts/genesi-efikasb.dts | 22 ++++++++++++++++++++++ arch/arm/boot/dts/mx51-babbage.dts | 22 ++++++++++++++++++++++ arch/arm/boot/dts/mx53-loco.dts | 22 ++++++++++++++++++++++ arch/arm/mach-mx5/Makefile.boot | 5 +++++ arch/arm/mach-mx5/board-mx51_babbage.c | 6 ++++++ arch/arm/mach-mx5/board-mx51_efikamx.c | 6 ++++++ arch/arm/mach-mx5/board-mx51_efikasb.c | 6 ++++++ arch/arm/mach-mx5/board-mx53_loco.c | 5 +++++ 11 files changed, 131 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/freescale.txt create mode 100644 Documentation/devicetree/bindings/arm/genesi.txt create mode 100644 arch/arm/boot/dts/genesi-efikamx.dts create mode 100644 arch/arm/boot/dts/genesi-efikasb.dts create mode 100644 arch/arm/boot/dts/mx51-babbage.dts create mode 100644 arch/arm/boot/dts/mx53-loco.dts diff --git a/Documentation/devicetree/bindings/arm/freescale.txt b/Documentation/devicetree/bindings/arm/freescale.txt new file mode 100644 index 00000000000..8c52102b225 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/freescale.txt @@ -0,0 +1,7 @@ +mx51 "Babbage" evalutation board +Required root node properties: + - compatible = "fsl,mx51-babbage", "fsl,mx51"; + +mx53 "Loco" evaluation board +Required root node properties: + - compatible = "fsl,mx53-loco", "fsl,mx53"; diff --git a/Documentation/devicetree/bindings/arm/genesi.txt b/Documentation/devicetree/bindings/arm/genesi.txt new file mode 100644 index 00000000000..b353489acd4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/genesi.txt @@ -0,0 +1,8 @@ +Genesi EfikaMX based on Freescale mx51 +Required root node properties: + - compatible = "genesi,efikamx", "fsl,mx51"; + +Genesi EfikaMX Smartbook based on Freescale mx51 +Required root node properties: + - compatible = "genesi,efikasb", "fsl,mx51"; + diff --git a/arch/arm/boot/dts/genesi-efikamx.dts b/arch/arm/boot/dts/genesi-efikamx.dts new file mode 100644 index 00000000000..e81ffcc8443 --- /dev/null +++ b/arch/arm/boot/dts/genesi-efikamx.dts @@ -0,0 +1,22 @@ +/* + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Genesi EfikaMX nettop"; + compatible = "genesi,efikamx", "fsl,mx51"; + + memory { + reg = <0x90000000 0x20000000>; + }; +}; diff --git a/arch/arm/boot/dts/genesi-efikasb.dts b/arch/arm/boot/dts/genesi-efikasb.dts new file mode 100644 index 00000000000..9fda6ae314e --- /dev/null +++ b/arch/arm/boot/dts/genesi-efikasb.dts @@ -0,0 +1,22 @@ +/* + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Genesi Efika Smartbook"; + compatible = "genesi,efikasb", "fsl,mx51"; + + memory { + reg = <0x90000000 0x20000000>; + }; +}; diff --git a/arch/arm/boot/dts/mx51-babbage.dts b/arch/arm/boot/dts/mx51-babbage.dts new file mode 100644 index 00000000000..e5e9c8913d0 --- /dev/null +++ b/arch/arm/boot/dts/mx51-babbage.dts @@ -0,0 +1,22 @@ +/* + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Freescale i.MX51 Babbage"; + compatible = "fsl,mx51-babbage", "fsl,mx51"; + + memory { + reg = <0x90000000 0x20000000>; + }; +}; diff --git a/arch/arm/boot/dts/mx53-loco.dts b/arch/arm/boot/dts/mx53-loco.dts new file mode 100644 index 00000000000..8426c620614 --- /dev/null +++ b/arch/arm/boot/dts/mx53-loco.dts @@ -0,0 +1,22 @@ +/* + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "Freescale i.MX53 LOCO"; + compatible = "fsl,mx53-loco", "fsl,mx53"; + + memory { + reg = <0x70000000 0x40000000>; + }; +}; diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot index e928be1b675..4111462e242 100644 --- a/arch/arm/mach-mx5/Makefile.boot +++ b/arch/arm/mach-mx5/Makefile.boot @@ -7,3 +7,8 @@ initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000 zreladdr-$(CONFIG_ARCH_MX53) := 0x70008000 params_phys-$(CONFIG_ARCH_MX53) := 0x70000100 initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000 + +dtb-$(CONFIG_MACH_MX51_BABBAGE) += mx51-babbage.dtb +dtb-$(CONFIG_MACH_MX51_EFIKAMX) += genesi-efikamx.dtb +dtb-$(CONFIG_MACH_MX51_EFIKASB) += genesi-efikasb.dtb +dtb-$(CONFIG_MACH_MX53_LOCO) += mx53-loco.dtb diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index 11b0ff67f89..49e50d194f8 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -414,6 +414,11 @@ static struct sys_timer mx51_babbage_timer = { .init = mx51_babbage_timer_init, }; +static const char *mx51_babbage_dt_match[] __initdata = { + "fsl,mx51-babbage", + NULL +}; + MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") /* Maintainer: Amit Kucheria */ .boot_params = MX51_PHYS_OFFSET + 0x100, @@ -422,4 +427,5 @@ MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") .init_irq = mx51_init_irq, .timer = &mx51_babbage_timer, .init_machine = mx51_babbage_init, + .dt_compat = mx51_babbage_dt_match, MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c index 551daf85ff8..dd5abde65f7 100644 --- a/arch/arm/mach-mx5/board-mx51_efikamx.c +++ b/arch/arm/mach-mx5/board-mx51_efikamx.c @@ -278,6 +278,11 @@ static struct sys_timer mx51_efikamx_timer = { .init = mx51_efikamx_timer_init, }; +static const char *mx51_efikamx_dt_match[] __initdata = { + "genesi,efikamx", + NULL +}; + MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop") /* Maintainer: Amit Kucheria */ .boot_params = MX51_PHYS_OFFSET + 0x100, @@ -286,4 +291,5 @@ MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop") .init_irq = mx51_init_irq, .timer = &mx51_efikamx_timer, .init_machine = mx51_efikamx_init, + .dt_compat = mx51_efikamx_dt_match, MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c index 8a9bca22beb..30b6c8f5d97 100644 --- a/arch/arm/mach-mx5/board-mx51_efikasb.c +++ b/arch/arm/mach-mx5/board-mx51_efikasb.c @@ -265,6 +265,11 @@ static struct sys_timer mx51_efikasb_timer = { .init = mx51_efikasb_timer_init, }; +static const char *mx51_efikasb_dt_match[] __initdata = { + "genesi,efikasb", + NULL +}; + MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook") .boot_params = MX51_PHYS_OFFSET + 0x100, .map_io = mx51_map_io, @@ -272,4 +277,5 @@ MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook") .init_irq = mx51_init_irq, .init_machine = efikasb_board_init, .timer = &mx51_efikasb_timer, + .dt_compat = mx51_efikasb_dt_match, MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 4e1d51d252d..13cddd703be 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -284,10 +284,15 @@ static struct sys_timer mx53_loco_timer = { .init = mx53_loco_timer_init, }; +static const char *mx53_loco_dt_match[] __initdata = { + "fsl,mx53-loco", + NULL +}; MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board") .map_io = mx53_map_io, .init_early = imx53_init_early, .init_irq = mx53_init_irq, .timer = &mx53_loco_timer, .init_machine = mx53_loco_board_init, + .dt_compat = mx53_loco_dt_match, MACHINE_END -- cgit v1.2.3 From a6babb372af746dec6bd4b00635bb400f9cd05c4 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 24 Oct 2011 11:09:12 +0200 Subject: arm/dt: vexpress: add basic DT platform matching support This patch adds a DT match table to the Versatile Express machine description in order to enable basic device tree support. Tested on a Versatile Express board where the device tree blob is passed to the kernel by u-boot. Signed-off-by: Lorenzo Pieralisi [converted .dts file to use skeleton.dtsi, and added 'dtbs' targets] Signed-off-by: Grant Likely --- arch/arm/boot/dts/vexpress.dts | 10 ++++++++++ arch/arm/mach-vexpress/Makefile.boot | 2 ++ arch/arm/mach-vexpress/v2m.c | 6 ++++++ 3 files changed, 18 insertions(+) create mode 100644 arch/arm/boot/dts/vexpress.dts diff --git a/arch/arm/boot/dts/vexpress.dts b/arch/arm/boot/dts/vexpress.dts new file mode 100644 index 00000000000..5f3bc1d1f1c --- /dev/null +++ b/arch/arm/boot/dts/vexpress.dts @@ -0,0 +1,10 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ARM Versatile Express"; + compatible = "arm,vexpress"; + memory { + reg = <0x60000000 0x40000000>; + }; +}; diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot index 07c2d9c457e..9920a1053e2 100644 --- a/arch/arm/mach-vexpress/Makefile.boot +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -1,3 +1,5 @@ zreladdr-y := 0x60008000 params_phys-y := 0x60000100 initrd_phys-y := 0x60800000 + +dtb-$(CONFIG_ARCH_VEXPRESS_CA9X4) += vexpress.dtb diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index d0d267a8d3f..1421389987a 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -442,6 +442,11 @@ static void __init v2m_init(void) ct_desc->init_tile(); } +static const char *vexpress_dt_match[] __initdata = { + "arm,vexpress", + NULL, +}; + MACHINE_START(VEXPRESS, "ARM-Versatile Express") .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = v2m_map_io, @@ -449,4 +454,5 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") .init_irq = v2m_init_irq, .timer = &v2m_timer, .init_machine = v2m_init, + .dt_compat = vexpress_dt_match, MACHINE_END -- cgit v1.2.3 From 1021eb4c454312e65365a4700a1f2b33a0654aa4 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 24 Oct 2011 11:09:15 +0200 Subject: dt: Linux dt usage model documentation v2: 2nd draft - Editorial cleanups from Randy Dunlap Signed-off-by: Grant Likely --- Documentation/devicetree/usage-model | 403 +++++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 Documentation/devicetree/usage-model diff --git a/Documentation/devicetree/usage-model b/Documentation/devicetree/usage-model new file mode 100644 index 00000000000..45e03b8dd04 --- /dev/null +++ b/Documentation/devicetree/usage-model @@ -0,0 +1,403 @@ +Linux and the Device Tree +The Linux usage model for device tree data + +Author: Grant Likely + +This article describes how Linux uses the device tree. An overview of +the device tree data format can be found at the Device Tree Usage +page on devicetree.org. + + + All the cool architectures are using device tree. I want to + use device tree too! + +The "Open Firmware Device Tree", or simply Device Tree (DT), is a data +structure and language for describing hardware. More specifically, it +is a description of hardware that is readable by an operating system +so that the operating system doesn't need to hard code details of the +machine. + +Structurally, the DT is a tree, or acyclic graph with named nodes, and +nodes may have an arbitrary number of named properties encapsulating +arbitrary data. A mechanism also exists to create arbitrary +links from one node to another outside of the natural tree structure. + +Conceptually, a common set of usage conventions, called 'bindings', +is defined for how data should appear in the tree to describe typical +hardware characteristics including data busses, interrupt lines, GPIO +connections, and peripheral devices. + +As much as possible, hardware is described using existing bindings to +maximize use of existing support code, but since property and node +names are simply text strings, it is easy to extend existing bindings +or create new ones by defining new nodes and properties. + +

History

+The DT was originally created by Open Firmware as part of the +communication method for passing data from Open Firmware to a client +program (like to an operating system). An operating system used the +Device Tree to discover the topology of the hardware at runtime, and +thereby support a majority of available hardware without hard coded +information (assuming drivers were available for all devices). + +Since Open Firmware is commonly used on PowerPC and SPARC platforms, +the Linux support for those architectures has for a long time used the +Device Tree. + +In 2005, when PowerPC Linux began a major cleanup and to merge 32-bit +and 64-bit support, the decision was made to require DT support on all +powerpc platforms, regardless of whether or not they used Open +Firmware. To do this, a DT representation called the Flattened Device +Tree (FDT) was created which could be passed to the kernel as a binary +blob without requiring a real Open Firmware implementation. U-Boot, +kexec, and other bootloaders were modified to support both passing a +Device Tree Binary (dtb) and to modify a dtb at boot time. + +Some time later, FDT infrastructure was generalized to be usable by +all architectures. At the time of this writing, 6 mainlined +architectures (arm, microblaze, mips, powerpc, sparc, and x86) and 1 +out of mainline (nios) have some level of DT support. + +

Data Model

+If you haven't already read the +href="http://devicetree.org/Device_Tree_Usage">Device Tree Usage +page, then go read it now. It's okay, I'll wait.... + +

High Level View

+The most important thing to understand is that the DT is simply a data +structure that describes the hardware. There is nothing magical about +it, and it doesn't magically make all hardware configuration problems +go away. What it does do is provide a language for decoupling the +hardware configuration from the board and device driver support in the +Linux kernel (or any other operating system for that matter). Using +it allows board and device support to become data driven; to make +setup decisions based on data passed into the kernel instead of on +per-machine hard coded selections. + +Ideally, data driven platform setup should result in less code +duplication and make it easier to support a wide range of hardware +with a single kernel image. + +Linux uses DT data for three major purposes: +1) platform identification, +2) runtime configuration, and +3) device population. + +

Platform Identification

+First and foremost, the kernel will use data in the DT to identify the +specific machine. In a perfect world, the specific platform shouldn't +matter to the kernel because all platform details would be described +perfectly by the device tree in a consistent and reliable manner. +Hardware is not perfect though, and so the kernel must identify the +machine during early boot so that it has the opportunity to run +machine-specific fixups. + +In the majority of cases, the machine identity is irrelevant, and the +kernel will instead select setup code based on the machine's core +CPU or SoC. On ARM for example, setup_arch() in +arch/arm/kernel/setup.c will call setup_machine_fdt() in +arch/arm/kernel/devicetree.c which searches through the machine_desc +table and selects the machine_desc which best matches the device tree +data. It determines the best match by looking at the 'compatible' +property in the root device tree node, and comparing it with the +dt_compat list in struct machine_desc. + +The 'compatible' property contains a sorted list of strings starting +with the exact name of the machine, followed by an optional list of +boards it is compatible with sorted from most compatible to least. For +example, the root compatible properties for the TI BeagleBoard and its +successor, the BeagleBoard xM board might look like: + + compatible = "ti,omap3-beagleboard", "ti,omap3450", "ti,omap3"; + compatible = "ti,omap3-beagleboard-xm", "ti,omap3450", "ti,omap3"; + +Where "ti,omap3-beagleboard-xm" specifies the exact model, it also +claims that it compatible with the OMAP 3450 SoC, and the omap3 family +of SoCs in general. You'll notice that the list is sorted from most +specific (exact board) to least specific (SoC family). + +Astute readers might point out that the Beagle xM could also claim +compatibility with the original Beagle board. However, one should be +cautioned about doing so at the board level since there is typically a +high level of change from one board to another, even within the same +product line, and it is hard to nail down exactly what is meant when one +board claims to be compatible with another. For the top level, it is +better to err on the side of caution and not claim one board is +compatible with another. The notable exception would be when one +board is a carrier for another, such as a CPU module attached to a +carrier board. + +One more note on compatible values. Any string used in a compatible +property must be documented as to what it indicates. Add +documentation for compatible strings in Documentation/devicetree/bindings. + +Again on ARM, for each machine_desc, the kernel looks to see if +any of the dt_compat list entries appear in the compatible property. +If one does, then that machine_desc is a candidate for driving the +machine. After searching the entire table of machine_descs, +setup_machine_fdt() returns the 'most compatible' machine_desc based +on which entry in the compatible property each machine_desc matches +against. If no matching machine_desc is found, then it returns NULL. + +The reasoning behind this scheme is the observation that in the majority +of cases, a single machine_desc can support a large number of boards +if they all use the same SoC, or same family of SoCs. However, +invariably there will be some exceptions where a specific board will +require special setup code that is not useful in the generic case. +Special cases could be handled by explicitly checking for the +troublesome board(s) in generic setup code, but doing so very quickly +becomes ugly and/or unmaintainable if it is more than just a couple of +cases. + +Instead, the compatible list allows a generic machine_desc to provide +support for a wide common set of boards by specifying "less +compatible" value in the dt_compat list. In the example above, +generic board support can claim compatibility with "ti,omap3" or +"ti,omap3450". If a bug was discovered on the original beagleboard +that required special workaround code during early boot, then a new +machine_desc could be added which implements the workarounds and only +matches on "ti,omap3-beagleboard". + +PowerPC uses a slightly different scheme where it calls the .probe() +hook from each machine_desc, and the first one returning TRUE is used. +However, this approach does not take into account the priority of the +compatible list, and probably should be avoided for new architecture +support. + +

Runtime configuration

+In most cases, a DT will be the sole method of communicating data from +firmware to the kernel, so also gets used to pass in runtime and +configuration data like the kernel parameters string and the location +of an initrd image. + +Most of this data is contained in the /chosen node, and when booting +Linux it will look something like this: + + chosen { + bootargs = "console=ttyS0,115200 loglevel=8"; + initrd-start = <0xc8000000>; + initrd-end = <0xc8200000>; + }; + +The bootargs property contains the kernel arguments, and the initrd-* +properties define the address and size of an initrd blob. The +chosen node may also optionally contain an arbitrary number of +additional properties for platform-specific configuration data. + +During early boot, the architecture setup code calls of_scan_flat_dt() +several times with different helper callbacks to parse device tree +data before paging is setup. The of_scan_flat_dt() code scans through +the device tree and uses the helpers to extract information required +during early boot. Typically the early_init_dt_scan_chosen() helper +is used to parse the chosen node including kernel parameters, +early_init_dt_scan_root() to initialize the DT address space model, +and early_init_dt_scan_memory() to determine the size and +location of usable RAM. + +On ARM, the function setup_machine_fdt() is responsible for early +scanning of the device tree after selecting the correct machine_desc +that supports the board. + +

Device population

+After the board has been identified, and after the early configuration data +has been parsed, then kernel initialization can proceed in the normal +way. At some point in this process, unflatten_device_tree() is called +to convert the data into a more efficient runtime representation. +This is also when machine-specific setup hooks will get called, like +the machine_desc .init_early(), .init_irq() and .init_machine() hooks +on ARM. The remainder of this section uses examples from the ARM +implementation, but all architectures will do pretty much the same +thing when using a DT. + +As can be guessed by the names, .init_early() is used for any machine- +specific setup that needs to be executed early in the boot process, +and .init_irq() is used to set up interrupt handling. Using a DT +doesn't materially change the behaviour of either of these functions. +If a DT is provided, then both .init_early() and .init_irq() are able +to call any of the DT query functions (of_* in include/linux/of*.h) to +get additional data about the platform. + +The most interesting hook in the DT context is .init_machine() which +is primarily responsible for populating the Linux device model with +data about the platform. Historically this has been implemented on +embedded platforms by defining a set of static clock structures, +platform_devices, and other data in the board support .c file, and +registering it en-masse in .init_machine(). When DT is used, then +instead of hard coding static devices for each platform, the list of +devices can be obtained by parsing the DT, and allocating device +structures dynamically. + +The simplest case is when .init_machine() is only responsible for +registering a block of platform_devices. A platform_device is a concept +used by Linux for memory or I/O mapped devices which cannot be detected +by hardware, and for 'composite' or 'virtual' devices (more on those +later). While there is no 'platform device' terminology for the DT, +platform devices roughly correspond to device nodes at the root of the +tree and children of simple memory mapped bus nodes. + +About now is a good time to lay out an example. Here is part of the +device tree for the NVIDIA Tegra board. + +/{ + compatible = "nvidia,harmony", "nvidia,tegra20"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + chosen { }; + aliases { }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; + }; + + soc { + compatible = "nvidia,tegra20-soc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + intc: interrupt-controller@50041000 { + compatible = "nvidia,tegra20-gic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x50041000 0x1000>, < 0x50040100 0x0100 >; + }; + + serial@70006300 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006300 0x100>; + interrupts = <122>; + }; + + i2s-1: i2s@70002800 { + compatible = "nvidia,tegra20-i2s"; + reg = <0x70002800 0x100>; + interrupts = <77>; + codec = <&wm8903>; + }; + + i2c@7000c000 { + compatible = "nvidia,tegra20-i2c"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x7000c000 0x100>; + interrupts = <70>; + + wm8903: codec@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupts = <347>; + }; + }; + }; + + sound { + compatible = "nvidia,harmony-sound"; + i2s-controller = <&i2s-1>; + i2s-codec = <&wm8903>; + }; +}; + +At .machine_init() time, Tegra board support code will need to look at +this DT and decide which nodes to create platform_devices for. +However, looking at the tree, it is not immediately obvious what kind +of device each node represents, or even if a node represents a device +at all. The /chosen, /aliases, and /memory nodes are informational +nodes that don't describe devices (although arguably memory could be +considered a device). The children of the /soc node are memory mapped +devices, but the codec@1a is an i2c device, and the sound node +represents not a device, but rather how other devices are connected +together to create the audio subsystem. I know what each device is +because I'm familiar with the board design, but how does the kernel +know what to do with each node? + +The trick is that the kernel starts at the root of the tree and looks +for nodes that have a 'compatible' property. First, it is generally +assumed that any node with a 'compatible' property represents a device +of some kind, and second, it can be assumed that any node at the root +of the tree is either directly attached to the processor bus, or is a +miscellaneous system device that cannot be described any other way. +For each of these nodes, Linux allocates and registers a +platform_device, which in turn may get bound to a platform_driver. + +Why is using a platform_device for these nodes a safe assumption? +Well, for the way that Linux models devices, just about all bus_types +assume that its devices are children of a bus controller. For +example, each i2c_client is a child of an i2c_master. Each spi_device +is a child of an SPI bus. Similarly for USB, PCI, MDIO, etc. The +same hierarchy is also found in the DT, where I2C device nodes only +ever appear as children of an I2C bus node. Ditto for SPI, MDIO, USB, +etc. The only devices which do not require a specific type of parent +device are platform_devices (and amba_devices, but more on that +later), which will happily live at the base of the Linux /sys/devices +tree. Therefore, if a DT node is at the root of the tree, then it +really probably is best registered as a platform_device. + +Linux board support code calls of_platform_populate(NULL, NULL, NULL) +to kick off discovery of devices at the root of the tree. The +parameters are all NULL because when starting from the root of the +tree, there is no need to provide a starting node (the first NULL), a +parent struct device (the last NULL), and we're not using a match +table (yet). For a board that only needs to register devices, +.init_machine() can be completely empty except for the +of_platform_populate() call. + +In the Tegra example, this accounts for the /soc and /sound nodes, but +what about the children of the SoC node? Shouldn't they be registered +as platform devices too? For Linux DT support, the generic behaviour +is for child devices to be registered by the parent's device driver at +driver .probe() time. So, an i2c bus device driver will register a +i2c_client for each child node, an SPI bus driver will register +its spi_device children, and similarly for other bus_types. +According to that model, a driver could be written that binds to the +SoC node and simply registers platform_devices for each of its +children. The board support code would allocate and register an SoC +device, an SoC device driver would bind to the SoC device, and +register platform_devices for /soc/interrupt-controller, /soc/serial, +/soc/i2s, and /soc/i2c in its .probe() hook. Easy, right? Although +it is a lot of mucking about for just registering platform devices. + +It turns out that registering children of certain platform_devices as +more platform_devices is a common pattern, and the device tree support +code reflects that. The second argument to of_platform_populate() is +an of_device_id table, and any node that matches an entry in that +table will also get its child nodes registered. In the tegra case, +the code can look something like this: + +static struct of_device_id harmony_bus_ids[] __initdata = { + { .compatible = "simple-bus", }, + {} +}; + +static void __init harmony_init_machine(void) +{ + /* ... */ + of_platform_populate(NULL, harmony_bus_ids, NULL); +} + +"simple-bus" is defined in the ePAPR 1.0 specification as a property +meaning a simple memory mapped bus, so the of_platform_populate() code +could be written to just assume simple-bus compatible nodes will +always be traversed. However, we pass it in as an argument so that +board support code can always override the default behaviour. + +

Appendix A: AMBA devices

+ +ARM Primecells are a certain kind of device attached to the ARM AMBA +bus which include some support for hardware detection and power +management. In Linux, struct amba_device and the amba_bus_type is +used to represent Primecell devices. However, the fiddly bit is that +not all devices on an AMBA bus are Primecells, and for Linux it is +typical for both amba_device and platform_device instances to be +siblings of the same bus segment. + +When using the DT, this creates problems for of_platform_populate() +because it must decide whether to register each node as either a +platform_device or an amba_device. This unfortunately complicates the +device creation model a little bit, but the solution turns out not to +be too invasive. If a node is compatible with "arm,amba-primecell", then +of_platform_populate() will register it as an amba_device instead of a +platform_device. -- cgit v1.2.3