Merge branch 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6

* 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6:
  of_mdio: Don't phy_scan_fixups() twice
  Devicetree: Expand on ARM Primecell binding documentation
  dt: Add empty of_match_node() macro
  dt: add empty dt helpers for non-dt build
  devicetree: fix build error on drivers/tty/serial/altera_jtaguart.c
  devicetree: Add ARM pl022 spi controller binding doc
  devicetree: Add ARM pl061 gpio controller binding doc
  of/irq: of_irq_find_parent: check for parent equal to child
  MAINTAINERS: update devicetree maintainers
  dt: add helper to read 64-bit integers
  tty: use of_match_ptr() for of_match_table entry
  OF: Add of_match_ptr() macro
  dt: add empty for_each_child_of_node, of_find_property
  devicetree: Document Qualcomm and Atmel prefixes
  serial/imx: add of_alias_get_id() reference back
  dt: add of_alias_scan and of_alias_get_id
  devicetree: Add a registry of vendor prefixes
This commit is contained in:
Linus Torvalds 2011-10-27 08:35:41 +02:00
commit 5fffb9513c
15 changed files with 286 additions and 26 deletions

View File

@ -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:

View File

@ -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.

View File

@ -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 = <index> in the SPI child nodes.
If unspecified, a single SPI device without a chip select can be used.

View File

@ -0,0 +1,40 @@
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.
atmel Atmel Corporation
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
qcom Qualcomm, Inc.
ramtron Ramtron International
samsung Samsung Semiconductor
schindler Schindler
simtek
sirf SiRF Technology, Inc.
stericsson ST-Ericsson
ti Texas Instruments
xlnx Xilinx

View File

@ -4760,10 +4760,12 @@ F: drivers/i2c/busses/i2c-ocores.c
OPEN FIRMWARE AND FLATTENED DEVICE TREE
M: Grant Likely <grant.likely@secretlab.ca>
M: Rob Herring <rob.herring@calxeda.com>
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

View File

@ -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 <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
/**
* 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.
@ -631,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.
@ -988,3 +1042,99 @@ void of_detach_node(struct device_node *np)
}
#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);

View File

@ -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 */

View File

@ -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;
}
/**

View File

@ -83,7 +83,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
addr);
continue;
}
phy_scan_fixups(phy);
/* Associate the OF node with the device structure so it
* can be looked up later */

View File

@ -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);
}

View File

@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/of.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
@ -472,8 +473,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 +481,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),
},
};

View File

@ -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),
},
};

View File

@ -1290,17 +1290,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;

View File

@ -569,8 +569,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)
@ -610,7 +608,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),
},
};

View File

@ -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)
@ -199,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,
@ -209,6 +212,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 +227,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);
@ -235,6 +244,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)
@ -242,6 +252,22 @@ static inline bool of_have_populated_dt(void)
return false;
}
#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)
{
return NULL;
}
static inline int of_property_read_u32_array(const struct device_node *np,
const char *propname,
u32 *out_values, size_t sz)
@ -263,6 +289,21 @@ 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;
}
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
#define of_match_node(_matches, _node) NULL
#endif /* CONFIG_OF */
static inline int of_property_read_u32(const struct device_node *np,