Commit 8181780c authored by Linus Torvalds's avatar Linus Torvalds

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
parents 7235dd74 99ce39e3
* ARM Primecell Peripherals
ARM, Ltd. Primecell peripherals have a standard id register that can be used to
identify the peripheral type, vendor, and revision. This value can be used for
driver matching.
Required properties:
- compatible : should be a specific value for peripheral and "arm,primecell"
Optional properties:
- arm,primecell-periphid : Value to override the h/w value with
Example:
serial@fff36000 {
compatible = "arm,pl011", "arm,primecell";
arm,primecell-periphid = <0x00341011>;
};
Freescale SoC SEC Security Engines Freescale SoC SEC Security Engines versions 2.x-3.x
Required properties: Required properties:
......
* UART (Universal Asynchronous Receiver/Transmitter)
Required properties:
- compatible : one of:
- "ns8250"
- "ns16450"
- "ns16550a"
- "ns16550"
- "ns16750"
- "ns16850"
- "nvidia,tegra20-uart"
- "ibm,qpace-nwp-serial"
- "serial" if the port type is unknown.
- reg : offset and length of the register set for the device.
- interrupts : should contain uart interrupt.
- clock-frequency : the input clock frequency for the UART.
Optional properties:
- current-speed : the current active speed of the UART.
- reg-offset : offset to apply to the mapbase from the start of the registers.
- reg-shift : quantity to shift the register offsets by.
- reg-io-width : the size (in bytes) of the IO accesses that should be
performed on the device. There are some systems that require 32-bit
accesses to the UART (e.g. TI davinci).
- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
RTAS and should not be registered.
Example:
uart@80230000 {
compatible = "ns8250";
reg = <0x80230000 0x100>;
clock-frequency = <3686400>;
interrupts = <10>;
reg-shift = <2>;
};
...@@ -1155,12 +1155,19 @@ static int __devinit ace_probe(struct platform_device *dev) ...@@ -1155,12 +1155,19 @@ static int __devinit ace_probe(struct platform_device *dev)
{ {
resource_size_t physaddr = 0; resource_size_t physaddr = 0;
int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
int id = dev->id; u32 id = dev->id;
int irq = NO_IRQ; int irq = NO_IRQ;
int i; int i;
dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
/* device id and bus width */
of_property_read_u32(dev->dev.of_node, "port-number", &id);
if (id < 0)
id = 0;
if (of_find_property(dev->dev.of_node, "8-bit", NULL))
bus_width = ACE_BUS_WIDTH_8;
for (i = 0; i < dev->num_resources; i++) { for (i = 0; i < dev->num_resources; i++) {
if (dev->resource[i].flags & IORESOURCE_MEM) if (dev->resource[i].flags & IORESOURCE_MEM)
physaddr = dev->resource[i].start; physaddr = dev->resource[i].start;
...@@ -1181,57 +1188,7 @@ static int __devexit ace_remove(struct platform_device *dev) ...@@ -1181,57 +1188,7 @@ static int __devexit ace_remove(struct platform_device *dev)
return 0; return 0;
} }
static struct platform_driver ace_platform_driver = {
.probe = ace_probe,
.remove = __devexit_p(ace_remove),
.driver = {
.owner = THIS_MODULE,
.name = "xsysace",
},
};
/* ---------------------------------------------------------------------
* OF_Platform Bus Support
*/
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
static int __devinit ace_of_probe(struct platform_device *op)
{
struct resource res;
resource_size_t physaddr;
const u32 *id;
int irq, bus_width, rc;
/* device id */
id = of_get_property(op->dev.of_node, "port-number", NULL);
/* physaddr */
rc = of_address_to_resource(op->dev.of_node, 0, &res);
if (rc) {
dev_err(&op->dev, "invalid address\n");
return rc;
}
physaddr = res.start;
/* irq */
irq = irq_of_parse_and_map(op->dev.of_node, 0);
/* bus width */
bus_width = ACE_BUS_WIDTH_16;
if (of_find_property(op->dev.of_node, "8-bit", NULL))
bus_width = ACE_BUS_WIDTH_8;
/* Call the bus-independent setup code */
return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
physaddr, irq, bus_width);
}
static int __devexit ace_of_remove(struct platform_device *op)
{
ace_free(&op->dev);
return 0;
}
/* Match table for of_platform binding */ /* Match table for of_platform binding */
static const struct of_device_id ace_of_match[] __devinitconst = { static const struct of_device_id ace_of_match[] __devinitconst = {
{ .compatible = "xlnx,opb-sysace-1.00.b", }, { .compatible = "xlnx,opb-sysace-1.00.b", },
...@@ -1241,34 +1198,20 @@ static const struct of_device_id ace_of_match[] __devinitconst = { ...@@ -1241,34 +1198,20 @@ static const struct of_device_id ace_of_match[] __devinitconst = {
{}, {},
}; };
MODULE_DEVICE_TABLE(of, ace_of_match); MODULE_DEVICE_TABLE(of, ace_of_match);
#else /* CONFIG_OF */
#define ace_of_match NULL
#endif /* CONFIG_OF */
static struct platform_driver ace_of_driver = { static struct platform_driver ace_platform_driver = {
.probe = ace_of_probe, .probe = ace_probe,
.remove = __devexit_p(ace_of_remove), .remove = __devexit_p(ace_remove),
.driver = { .driver = {
.name = "xsysace",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "xsysace",
.of_match_table = ace_of_match, .of_match_table = ace_of_match,
}, },
}; };
/* Registration helpers to keep the number of #ifdefs to a minimum */
static inline int __init ace_of_register(void)
{
pr_debug("xsysace: registering OF binding\n");
return platform_driver_register(&ace_of_driver);
}
static inline void __exit ace_of_unregister(void)
{
platform_driver_unregister(&ace_of_driver);
}
#else /* CONFIG_OF */
/* CONFIG_OF not enabled; do nothing helpers */
static inline int __init ace_of_register(void) { return 0; }
static inline void __exit ace_of_unregister(void) { }
#endif /* CONFIG_OF */
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Module init/exit routines * Module init/exit routines
*/ */
...@@ -1282,11 +1225,6 @@ static int __init ace_init(void) ...@@ -1282,11 +1225,6 @@ static int __init ace_init(void)
goto err_blk; goto err_blk;
} }
rc = ace_of_register();
if (rc)
goto err_of;
pr_debug("xsysace: registering platform binding\n");
rc = platform_driver_register(&ace_platform_driver); rc = platform_driver_register(&ace_platform_driver);
if (rc) if (rc)
goto err_plat; goto err_plat;
...@@ -1295,21 +1233,17 @@ static int __init ace_init(void) ...@@ -1295,21 +1233,17 @@ static int __init ace_init(void)
return 0; return 0;
err_plat: err_plat:
ace_of_unregister();
err_of:
unregister_blkdev(ace_major, "xsysace"); unregister_blkdev(ace_major, "xsysace");
err_blk: err_blk:
printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc);
return rc; return rc;
} }
module_init(ace_init);
static void __exit ace_exit(void) static void __exit ace_exit(void)
{ {
pr_debug("Unregistering Xilinx SystemACE driver\n"); pr_debug("Unregistering Xilinx SystemACE driver\n");
platform_driver_unregister(&ace_platform_driver); platform_driver_unregister(&ace_platform_driver);
ace_of_unregister();
unregister_blkdev(ace_major, "xsysace"); unregister_blkdev(ace_major, "xsysace");
} }
module_init(ace_init);
module_exit(ace_exit); module_exit(ace_exit);
...@@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index, ...@@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index,
} }
EXPORT_SYMBOL_GPL(of_address_to_resource); 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 * 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) ...@@ -595,6 +595,71 @@ struct device_node *of_find_node_by_phandle(phandle handle)
} }
EXPORT_SYMBOL(of_find_node_by_phandle); 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 * of_parse_phandle - Resolve a phandle property to a device_node pointer
* @np: Pointer to device node holding phandle property * @np: Pointer to device node holding phandle property
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/amba/bus.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -22,6 +23,14 @@ ...@@ -22,6 +23,14 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.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) static int of_dev_node_match(struct device *dev, void *data)
{ {
return dev->of_node == data; return dev->of_node == data;
...@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np, ...@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
EXPORT_SYMBOL(of_device_alloc); 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 * @np: pointer to node to create device for
* @bus_id: name to assign device * @bus_id: name to assign device
* @platform_data: pointer to populate platform_data pointer with
* @parent: Linux device model parent device. * @parent: Linux device model parent device.
* *
* Returns pointer to created platform device, or NULL if a device was not * Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered. * registered. Unavailable devices will not get registered.
*/ */
struct platform_device *of_platform_device_create(struct device_node *np, struct platform_device *of_platform_device_create_pdata(
const char *bus_id, struct device_node *np,
struct device *parent) const char *bus_id,
void *platform_data,
struct device *parent)
{ {
struct platform_device *dev; struct platform_device *dev;
...@@ -194,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np, ...@@ -194,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np,
#endif #endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.bus = &platform_bus_type; dev->dev.bus = &platform_bus_type;
dev->dev.platform_data = platform_data;
/* We do not fill the DMA ops for platform devices by default. /* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code * This is currently the responsibility of the platform code
...@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np, ...@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np,
return dev; 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); 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. * of_platform_bus_create() - Create a device for a node and its children.
* @bus: device node of the bus to instantiate * @bus: device node of the bus to instantiate
...@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create); ...@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create);
*/ */
static int of_platform_bus_create(struct device_node *bus, static int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches, 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 device_node *child;
struct platform_device *dev; struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
int rc = 0; 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)) if (!dev || !of_match_node(matches, bus))
return 0; return 0;
for_each_child_of_node(bus, child) { for_each_child_of_node(bus, child) {
pr_debug(" create child: %s\n", child->full_name); 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) { if (rc) {
of_node_put(child); of_node_put(child);
break; break;
...@@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root, ...@@ -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 */ /* Do a self check of bus type, if there's a match, create children */
if (of_match_node(matches, root)) { 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) { } else for_each_child_of_node(root, child) {
if (!of_match_node(matches, child)) if (!of_match_node(matches, child))
continue; continue;
rc = of_platform_bus_create(child, matches, parent); rc = of_platform_bus_create(child, matches, NULL, parent, false);
if (rc) if (rc)
break; break;
} }
...@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root, ...@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root,
return rc; return rc;
} }
EXPORT_SYMBOL(of_platform_bus_probe); 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 */ #endif /* !CONFIG_SPARC */
...@@ -32,17 +32,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, ...@@ -32,17 +32,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
{ {
struct resource resource; struct resource resource;
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
const __be32 *clk, *spd; u32 clk, spd, prop;
const __be32 *prop; int ret;
int ret, prop_size;
memset(port, 0, sizeof *port); memset(port, 0, sizeof *port);
spd = of_get_property(np, "current-speed", NULL); if (of_property_read_u32(np, "clock-frequency", &clk)) {
clk = of_get_property(np, "clock-frequency", NULL);
if (!clk) {
dev_warn(&ofdev->dev, "no clock-frequency property set\n"); dev_warn(&ofdev->dev, "no clock-frequency property set\n");
return -ENODEV; return -ENODEV;
} }
/* If current-speed was set, then try not to change it. */
if (of_property_read_u32(np, "current-speed", &spd) == 0)
port->custom_divisor = clk / (16 * spd);
ret = of_address_to_resource(np, 0, &resource); ret = of_address_to_resource(np, 0, &resource);
if (ret) { if (ret) {
...@@ -54,25 +54,35 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, ...@@ -54,25 +54,35 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
port->mapbase = resource.start; port->mapbase = resource.start;
/* Check for shifted address mapping */ /* Check for shifted address mapping */
prop = of_get_property(np, "reg-offset", &prop_size); if (of_property_read_u32(np, "reg-offset", &prop) == 0)
if (prop && (prop_size == sizeof(u32))) port->mapbase += prop;
port->mapbase += be32_to_cpup(prop);
/* Check for registers offset within the devices address range */ /* Check for registers offset within the devices address range */
prop = of_get_property(np, "reg-shift", &prop_size); if (of_property_read_u32(np, "reg-shift", &prop) == 0)
if (prop && (prop_size == sizeof(u32))) port->regshift = prop;
port->regshift = be32_to_cpup(prop);
port->irq = irq_of_parse_and_map(np, 0); port->irq = irq_of_parse_and_map(np, 0);
port->iotype = UPIO_MEM; port->iotype = UPIO_MEM;
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
switch (prop) {
case 1:
port->iotype = UPIO_MEM;
break;
case 4:
port->iotype = UPIO_MEM32;
break;
default:
dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
prop);
return -EINVAL;
}
}
port->type = type; port->type = type;
port->uartclk = be32_to_cpup(clk); port->uartclk = clk;
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
| UPF_FIXED_PORT | UPF_FIXED_TYPE; | UPF_FIXED_PORT | UPF_FIXED_TYPE;
port->dev = &ofdev->dev; port->dev = &ofdev->dev;
/* If current-speed was set, then try not to change it. */
if (spd)
port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd)));
return 0; return 0;
} }
...@@ -171,6 +181,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { ...@@ -171,6 +181,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
{ .compatible = "ns16550", .data = (void *)PORT_16550, }, { .compatible = "ns16550", .data = (void *)PORT_16550, },
{ .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16750", .data = (void *)PORT_16750, },
{ .compatible = "ns16850", .data = (void *)PORT_16850, }, { .compatible = "ns16850", .data = (void *)PORT_16850, },
{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
{ .compatible = "ibm,qpace-nwp-serial", { .compatible = "ibm,qpace-nwp-serial",
.data = (void *)PORT_NWPSERIAL, }, .data = (void *)PORT_NWPSERIAL, },
......
...@@ -195,6 +195,13 @@ extern struct device_node *of_find_node_with_property( ...@@ -195,6 +195,13 @@ extern struct device_node *of_find_node_with_property(
extern struct property *of_find_property(const struct device_node *np, extern struct property *of_find_property(const struct device_node *np,
const char *name, const char *name,
int *lenp); int *lenp);
extern int of_property_read_u32_array(const struct device_node *np,
char *propname,
u32 *out_values,
size_t sz);
extern int of_property_read_string(struct device_node *np, char *propname,
const char **out_string);
extern int of_device_is_compatible(const struct device_node *device, extern int of_device_is_compatible(const struct device_node *device,
const char *); const char *);
extern int of_device_is_available(const struct device_node *device); extern int of_device_is_available(const struct device_node *device);
...@@ -227,12 +234,32 @@ extern void of_attach_node(struct device_node *); ...@@ -227,12 +234,32 @@ extern void of_attach_node(struct device_node *);
extern void of_detach_node(struct device_node *); extern void of_detach_node(struct device_node *);
#endif #endif
#else #else /* CONFIG_OF */
static inline bool of_have_populated_dt(void) static inline bool of_have_populated_dt(void)
{ {
return false; return false;
} }
static inline int of_property_read_u32_array(const struct device_node *np,
char *propname, u32 *out_values, size_t sz)
{
return -ENOSYS;
}
static inline int of_property_read_string(struct device_node *np,
char *propname, const char **out_string)
{
return -ENOSYS;
}
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static inline int of_property_read_u32(const struct device_node *np,
char *propname,
u32 *out_value)
{
return of_property_read_u32_array(np, propname, out_value, 1);
}
#endif /* _LINUX_OF_H */ #endif /* _LINUX_OF_H */
#ifndef __OF_ADDRESS_H #ifndef __OF_ADDRESS_H
#define __OF_ADDRESS_H #define __OF_ADDRESS_H
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/of.h> #include <linux/of.h>
extern u64 of_translate_address(struct device_node *np, const __be32 *addr); extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern int of_address_to_resource(struct device_node *dev, int index, extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r); struct resource *r);
extern struct device_node *of_find_matching_node_by_address(
struct device_node *from,
const struct of_device_id *matches,
u64 base_address);
extern void __iomem *of_iomap(struct device_node *device, int index); extern void __iomem *of_iomap(struct device_node *device, int index);
/* Extract an address from a device, returns the region size and /* Extract an address from a device, returns the region size and
......
...@@ -19,6 +19,40 @@ ...@@ -19,6 +19,40 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
/**
* struct of_dev_auxdata - lookup table entry for device names & platform_data
* @compatible: compatible value of node to match against node
* @phys_addr: Start address of registers to match against node
* @name: Name to assign for matching nodes
* @platform_data: platform_data to assign for matching nodes
*
* This lookup table allows the caller of of_platform_populate() to override
* the names of devices when creating devices from the device tree. The table
* should be terminated with an empty entry. It also allows the platform_data
* pointer to be set.
*
* The reason for this functionality is that some Linux infrastructure uses
* the device name to look up a specific device, but the Linux-specific names
* are not encoded into the device tree, so the kernel needs to provide specific
* values.
*
* Note: Using an auxdata lookup table should be considered a last resort when
* converting a platform to use the DT. Normally the automatically generated
* device name will not matter, and drivers should obtain data from the device
* node instead of from an anonymouns platform_data pointer.
*/
struct of_dev_auxdata {
char *compatible;
resource_size_t phys_addr;
char *name;
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 }
/** /**
* of_platform_driver - Legacy of-aware driver for platform devices. * of_platform_driver - Legacy of-aware driver for platform devices.
* *
...@@ -40,6 +74,8 @@ struct of_platform_driver ...@@ -40,6 +74,8 @@ struct of_platform_driver
#define to_of_platform_driver(drv) \ #define to_of_platform_driver(drv) \
container_of(drv,struct of_platform_driver, driver) container_of(drv,struct of_platform_driver, driver)
extern const struct of_device_id of_default_bus_match_table[];
/* Platform drivers register/unregister */ /* Platform drivers register/unregister */
extern struct platform_device *of_device_alloc(struct device_node *np, extern struct platform_device *of_device_alloc(struct device_node *np,
const char *bus_id, const char *bus_id,
...@@ -55,6 +91,10 @@ extern struct platform_device *of_platform_device_create(struct device_node *np, ...@@ -55,6 +91,10 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
extern int of_platform_bus_probe(struct device_node *root, extern int of_platform_bus_probe(struct device_node *root,
const struct of_device_id *matches, const struct of_device_id *matches,
struct device *parent); struct device *parent);
extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent);
#endif /* !CONFIG_SPARC */ #endif /* !CONFIG_SPARC */
#endif /* CONFIG_OF_DEVICE */ #endif /* CONFIG_OF_DEVICE */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment