mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge branch 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6
* 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6: dt: include linux/errno.h in linux/of_address.h of/address: Add of_find_matching_node_by_address helper dt: remove extra xsysace platform_driver registration tty/serial: Add devicetree support for nVidia Tegra serial ports dt: add empty of_property_read_u32[_array] for non-dt dt: bindings: move SEC node under new crypto/ dt: add helper function to read u32 arrays tty/serial: change of_serial to use new of_property_read_u32() api dt: add 'const' for of_property_read_string parameter **out_string dt: add helper functions to read u32 and string property values tty: of_serial: support for 32 bit accesses dt: document the of_serial bindings dt/platform: allow device name to be overridden drivers/amba: create devices from device tree dt: add of_platform_populate() for creating device from the device tree dt: Add default match table for bus ids
This commit is contained in:
commit
8181780c16
11 changed files with 444 additions and 109 deletions
|
|
@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_address_to_resource);
|
||||
|
||||
struct device_node *of_find_matching_node_by_address(struct device_node *from,
|
||||
const struct of_device_id *matches,
|
||||
u64 base_address)
|
||||
{
|
||||
struct device_node *dn = of_find_matching_node(from, matches);
|
||||
struct resource res;
|
||||
|
||||
while (dn) {
|
||||
if (of_address_to_resource(dn, 0, &res))
|
||||
continue;
|
||||
if (res.start == base_address)
|
||||
return dn;
|
||||
dn = of_find_matching_node(dn, matches);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* of_iomap - Maps the memory mapped IO for a given device_node
|
||||
|
|
|
|||
|
|
@ -595,6 +595,71 @@ struct device_node *of_find_node_by_phandle(phandle handle)
|
|||
}
|
||||
EXPORT_SYMBOL(of_find_node_by_phandle);
|
||||
|
||||
/**
|
||||
* of_property_read_u32_array - Find and read an array of 32 bit integers
|
||||
* 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 32-bit value(s) 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 u32 value can be decoded.
|
||||
*/
|
||||
int of_property_read_u32_array(const struct device_node *np, char *propname,
|
||||
u32 *out_values, size_t sz)
|
||||
{
|
||||
struct property *prop = of_find_property(np, propname, NULL);
|
||||
const __be32 *val;
|
||||
|
||||
if (!prop)
|
||||
return -EINVAL;
|
||||
if (!prop->value)
|
||||
return -ENODATA;
|
||||
if ((sz * sizeof(*out_values)) > prop->length)
|
||||
return -EOVERFLOW;
|
||||
|
||||
val = prop->value;
|
||||
while (sz--)
|
||||
*out_values++ = be32_to_cpup(val++);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_property_read_u32_array);
|
||||
|
||||
/**
|
||||
* of_property_read_string - Find and read a string from a property
|
||||
* @np: device node from which the property value is to be read.
|
||||
* @propname: name of the property to be searched.
|
||||
* @out_string: pointer to null terminated return string, modified only if
|
||||
* return value is 0.
|
||||
*
|
||||
* Search for a property in a device tree node and retrieve a null
|
||||
* terminated string value (pointer to data, not a copy). Returns 0 on
|
||||
* success, -EINVAL if the property does not exist, -ENODATA if property
|
||||
* does not have a value, and -EILSEQ if the string is not null-terminated
|
||||
* within the length of the property data.
|
||||
*
|
||||
* The out_string pointer is modified only if a valid string can be decoded.
|
||||
*/
|
||||
int of_property_read_string(struct device_node *np, char *propname,
|
||||
const char **out_string)
|
||||
{
|
||||
struct property *prop = of_find_property(np, propname, NULL);
|
||||
if (!prop)
|
||||
return -EINVAL;
|
||||
if (!prop->value)
|
||||
return -ENODATA;
|
||||
if (strnlen(prop->value, prop->length) >= prop->length)
|
||||
return -EILSEQ;
|
||||
*out_string = prop->value;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_property_read_string);
|
||||
|
||||
/**
|
||||
* of_parse_phandle - Resolve a phandle property to a device_node pointer
|
||||
* @np: Pointer to device node holding phandle property
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -22,6 +23,14 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
const struct of_device_id of_default_bus_match_table[] = {
|
||||
{ .compatible = "simple-bus", },
|
||||
#ifdef CONFIG_ARM_AMBA
|
||||
{ .compatible = "arm,amba-bus", },
|
||||
#endif /* CONFIG_ARM_AMBA */
|
||||
{} /* Empty terminated list */
|
||||
};
|
||||
|
||||
static int of_dev_node_match(struct device *dev, void *data)
|
||||
{
|
||||
return dev->of_node == data;
|
||||
|
|
@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
|
|||
EXPORT_SYMBOL(of_device_alloc);
|
||||
|
||||
/**
|
||||
* of_platform_device_create - Alloc, initialize and register an of_device
|
||||
* of_platform_device_create_pdata - Alloc, initialize and register an of_device
|
||||
* @np: pointer to node to create device for
|
||||
* @bus_id: name to assign device
|
||||
* @platform_data: pointer to populate platform_data pointer with
|
||||
* @parent: Linux device model parent device.
|
||||
*
|
||||
* Returns pointer to created platform device, or NULL if a device was not
|
||||
* registered. Unavailable devices will not get registered.
|
||||
*/
|
||||
struct platform_device *of_platform_device_create(struct device_node *np,
|
||||
const char *bus_id,
|
||||
struct device *parent)
|
||||
struct platform_device *of_platform_device_create_pdata(
|
||||
struct device_node *np,
|
||||
const char *bus_id,
|
||||
void *platform_data,
|
||||
struct device *parent)
|
||||
{
|
||||
struct platform_device *dev;
|
||||
|
||||
|
|
@ -194,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np,
|
|||
#endif
|
||||
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
dev->dev.bus = &platform_bus_type;
|
||||
dev->dev.platform_data = platform_data;
|
||||
|
||||
/* We do not fill the DMA ops for platform devices by default.
|
||||
* This is currently the responsibility of the platform code
|
||||
|
|
@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np,
|
|||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_platform_device_create - Alloc, initialize and register an of_device
|
||||
* @np: pointer to node to create device for
|
||||
* @bus_id: name to assign device
|
||||
* @parent: Linux device model parent device.
|
||||
*
|
||||
* Returns pointer to created platform device, or NULL if a device was not
|
||||
* registered. Unavailable devices will not get registered.
|
||||
*/
|
||||
struct platform_device *of_platform_device_create(struct device_node *np,
|
||||
const char *bus_id,
|
||||
struct device *parent)
|
||||
{
|
||||
return of_platform_device_create_pdata(np, bus_id, NULL, parent);
|
||||
}
|
||||
EXPORT_SYMBOL(of_platform_device_create);
|
||||
|
||||
#ifdef CONFIG_ARM_AMBA
|
||||
static struct amba_device *of_amba_device_create(struct device_node *node,
|
||||
const char *bus_id,
|
||||
void *platform_data,
|
||||
struct device *parent)
|
||||
{
|
||||
struct amba_device *dev;
|
||||
const void *prop;
|
||||
int i, ret;
|
||||
|
||||
pr_debug("Creating amba device %s\n", node->full_name);
|
||||
|
||||
if (!of_device_is_available(node))
|
||||
return NULL;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
/* setup generic device info */
|
||||
dev->dev.coherent_dma_mask = ~0;
|
||||
dev->dev.of_node = of_node_get(node);
|
||||
dev->dev.parent = parent;
|
||||
dev->dev.platform_data = platform_data;
|
||||
if (bus_id)
|
||||
dev_set_name(&dev->dev, "%s", bus_id);
|
||||
else
|
||||
of_device_make_bus_id(&dev->dev);
|
||||
|
||||
/* setup amba-specific device info */
|
||||
dev->dma_mask = ~0;
|
||||
|
||||
/* Allow the HW Peripheral ID to be overridden */
|
||||
prop = of_get_property(node, "arm,primecell-periphid", NULL);
|
||||
if (prop)
|
||||
dev->periphid = of_read_ulong(prop, 1);
|
||||
|
||||
/* Decode the IRQs and address ranges */
|
||||
for (i = 0; i < AMBA_NR_IRQS; i++)
|
||||
dev->irq[i] = irq_of_parse_and_map(node, i);
|
||||
|
||||
ret = of_address_to_resource(node, 0, &dev->res);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
ret = amba_device_register(dev, &iomem_resource);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
return dev;
|
||||
|
||||
err_free:
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
#else /* CONFIG_ARM_AMBA */
|
||||
static struct amba_device *of_amba_device_create(struct device_node *node,
|
||||
const char *bus_id,
|
||||
void *platform_data,
|
||||
struct device *parent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_ARM_AMBA */
|
||||
|
||||
/**
|
||||
* of_devname_lookup() - Given a device node, lookup the preferred Linux name
|
||||
*/
|
||||
static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct resource res;
|
||||
if (lookup) {
|
||||
for(; lookup->name != NULL; lookup++) {
|
||||
if (!of_device_is_compatible(np, lookup->compatible))
|
||||
continue;
|
||||
if (of_address_to_resource(np, 0, &res))
|
||||
continue;
|
||||
if (res.start != lookup->phys_addr)
|
||||
continue;
|
||||
pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_platform_bus_create() - Create a device for a node and its children.
|
||||
* @bus: device node of the bus to instantiate
|
||||
|
|
@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create);
|
|||
*/
|
||||
static int of_platform_bus_create(struct device_node *bus,
|
||||
const struct of_device_id *matches,
|
||||
struct device *parent)
|
||||
const struct of_dev_auxdata *lookup,
|
||||
struct device *parent, bool strict)
|
||||
{
|
||||
const struct of_dev_auxdata *auxdata;
|
||||
struct device_node *child;
|
||||
struct platform_device *dev;
|
||||
const char *bus_id = NULL;
|
||||
void *platform_data = NULL;
|
||||
int rc = 0;
|
||||
|
||||
dev = of_platform_device_create(bus, NULL, parent);
|
||||
/* Make sure it has a compatible property */
|
||||
if (strict && (!of_get_property(bus, "compatible", NULL))) {
|
||||
pr_debug("%s() - skipping %s, no compatible prop\n",
|
||||
__func__, bus->full_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auxdata = of_dev_lookup(lookup, bus);
|
||||
if (auxdata) {
|
||||
bus_id = auxdata->name;
|
||||
platform_data = auxdata->platform_data;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(bus, "arm,primecell")) {
|
||||
of_amba_device_create(bus, bus_id, platform_data, parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
|
||||
if (!dev || !of_match_node(matches, bus))
|
||||
return 0;
|
||||
|
||||
for_each_child_of_node(bus, child) {
|
||||
pr_debug(" create child: %s\n", child->full_name);
|
||||
rc = of_platform_bus_create(child, matches, &dev->dev);
|
||||
rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
|
||||
if (rc) {
|
||||
of_node_put(child);
|
||||
break;
|
||||
|
|
@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root,
|
|||
|
||||
/* Do a self check of bus type, if there's a match, create children */
|
||||
if (of_match_node(matches, root)) {
|
||||
rc = of_platform_bus_create(root, matches, parent);
|
||||
rc = of_platform_bus_create(root, matches, NULL, parent, false);
|
||||
} else for_each_child_of_node(root, child) {
|
||||
if (!of_match_node(matches, child))
|
||||
continue;
|
||||
rc = of_platform_bus_create(child, matches, parent);
|
||||
rc = of_platform_bus_create(child, matches, NULL, parent, false);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
|
@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root,
|
|||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(of_platform_bus_probe);
|
||||
|
||||
/**
|
||||
* of_platform_populate() - Populate platform_devices from device tree data
|
||||
* @root: parent of the first level to probe or NULL for the root of the tree
|
||||
* @matches: match table, NULL to use the default
|
||||
* @parent: parent to hook devices from, NULL for toplevel
|
||||
*
|
||||
* Similar to of_platform_bus_probe(), this function walks the device tree
|
||||
* and creates devices from nodes. It differs in that it follows the modern
|
||||
* convention of requiring all device nodes to have a 'compatible' property,
|
||||
* and it is suitable for creating devices which are children of the root
|
||||
* node (of_platform_bus_probe will only create children of the root which
|
||||
* are selected by the @matches argument).
|
||||
*
|
||||
* New board support should be using this function instead of
|
||||
* of_platform_bus_probe().
|
||||
*
|
||||
* Returns 0 on success, < 0 on failure.
|
||||
*/
|
||||
int of_platform_populate(struct device_node *root,
|
||||
const struct of_device_id *matches,
|
||||
const struct of_dev_auxdata *lookup,
|
||||
struct device *parent)
|
||||
{
|
||||
struct device_node *child;
|
||||
int rc = 0;
|
||||
|
||||
root = root ? of_node_get(root) : of_find_node_by_path("/");
|
||||
if (!root)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_child_of_node(root, child) {
|
||||
rc = of_platform_bus_create(child, matches, lookup, parent, true);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(root);
|
||||
return rc;
|
||||
}
|
||||
#endif /* !CONFIG_SPARC */
|
||||
|
|
|
|||
Loading…
Reference in a new issue