Skip to content

Commit

Permalink
Merge tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux
Browse files Browse the repository at this point in the history
Pull devicetree updates from Rob Herring:
 - Import of latest upstream device tree compiler (dtc)
 - New function of_get_child_by_name
 - Support for #size-cells of 0 and #addr-cells of >2
 - Couple of DT binding documentation updates

Fix up trivial conflicts due to of_get_child_by_name() having been added
next to the new of_get_next_available_child().

* tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux:
  MAINTAINERS: add scripts/dtc under Devicetree maintainers
  dtc: import latest upstream dtc
  dt: Document general interrupt controller bindings
  dt/s3c64xx/spi: Use of_get_child_by_name to get a named child
  dt: introduce of_get_child_by_name to get child node by name
  of: i2c: add support for wakeup-source property
  of/address: Handle #address-cells > 2 specially
  DT: export of_irq_to_resource_table()
  devicetree: serial: Add documentation for imx serial
  devicetree: pwm: mxs-pwm.txt: Fix reg field annotation
  of: Allow busses with #size-cells=0
  • Loading branch information
torvalds committed Oct 3, 2012
2 parents eb0ad9c + 36165f5 commit a54dfb1
Show file tree
Hide file tree
Showing 42 changed files with 4,057 additions and 712 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
Specifying interrupt information for devices
============================================

1) Interrupt client nodes
-------------------------

Nodes that describe devices which generate interrupts must contain an
"interrupts" property. This property must contain a list of interrupt
specifiers, one per output interrupt. The format of the interrupt specifier is
determined by the interrupt controller to which the interrupts are routed; see
section 2 below for details.

The "interrupt-parent" property is used to specify the controller to which
interrupts are routed and contains a single phandle referring to the interrupt
controller node. This property is inherited, so it may be specified in an
interrupt client node or in any of its parent nodes.

2) Interrupt controller nodes
-----------------------------

A device is marked as an interrupt controller with the "interrupt-controller"
property. This is a empty, boolean property. An additional "#interrupt-cells"
property defines the number of cells needed to specify a single interrupt.

It is the responsibility of the interrupt controller's binding to define the
length and format of the interrupt specifier. The following two variants are
commonly used:

a) one cell
-----------
The #interrupt-cells property is set to 1 and the single cell defines the
index of the interrupt within the controller.

Example:

vic: intc@10140000 {
compatible = "arm,versatile-vic";
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x10140000 0x1000>;
};

sic: intc@10003000 {
compatible = "arm,versatile-sic";
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x10003000 0x1000>;
interrupt-parent = <&vic>;
interrupts = <31>; /* Cascaded to vic */
};

b) two cells
------------
The #interrupt-cells property is set to 2 and the first cell defines the
index of the interrupt within the controller, while the second cell is used
to specify any of the following flags:
- bits[3:0] trigger type and level flags
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive

Example:

i2c@7000c000 {
gpioext: gpio-adnp@41 {
compatible = "ad,gpio-adnp";
reg = <0x41>;

interrupt-parent = <&gpio>;
interrupts = <160 1>;

gpio-controller;
#gpio-cells = <1>;

interrupt-controller;
#interrupt-cells = <2>;

nr-gpios = <64>;
};

sx8634@2b {
compatible = "smtc,sx8634";
reg = <0x2b>;

interrupt-parent = <&gpioext>;
interrupts = <3 0x8>;

#address-cells = <1>;
#size-cells = <0>;

threshold = <0x40>;
sensitivity = <7>;
};
};
2 changes: 1 addition & 1 deletion Documentation/devicetree/bindings/pwm/mxs-pwm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Example:

pwm: pwm@80064000 {
compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
reg = <0x80064000 2000>;
reg = <0x80064000 0x2000>;
#pwm-cells = <2>;
fsl,pwm-number = <8>;
};
35 changes: 35 additions & 0 deletions Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
* Freescale i.MX UART controller

Required properties:
- compatible : should be "fsl,imx21-uart"
- reg : Address and length of the register set for the device
- interrupts : Should contain UART interrupt number

Optional properties:
- fsl,uart-has-rtscts: indicate that RTS/CTS signals are used

Note: Each uart controller should have an alias correctly numbered
in "aliases" node.

Example:

- From imx51.dtsi:
aliases {
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
};

uart1: serial@73fbc000 {
compatible = "fsl,imx51-uart", "fsl,imx21-uart";
reg = <0x73fbc000 0x4000>;
interrupts = <31>;
status = "disabled";
}

- From imx51-babbage.dts:
uart1: serial@73fbc000 {
fsl,uart-has-rtscts;
status = "okay";
};

1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5067,6 +5067,7 @@ S: Maintained
F: Documentation/devicetree
F: drivers/of
F: include/linux/of*.h
F: scripts/dtc
K: of_get_property
K: of_match_table

Expand Down
35 changes: 31 additions & 4 deletions drivers/of/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

/* Max address size we deal with */
#define OF_MAX_ADDR_CELLS 4
#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
(ns) > 0)
#define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
#define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0)

static struct of_bus *of_match_bus(struct device_node *np);
static int __of_address_to_resource(struct device_node *dev,
Expand Down Expand Up @@ -69,6 +69,14 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range,
(unsigned long long)cp, (unsigned long long)s,
(unsigned long long)da);

/*
* If the number of address cells is larger than 2 we assume the
* mapping doesn't specify a physical address. Rather, the address
* specifies an identifier that must match exactly.
*/
if (na > 2 && memcmp(range, addr, na * 4) != 0)
return OF_BAD_ADDR;

if (da < cp || da >= (cp + s))
return OF_BAD_ADDR;
return da - cp;
Expand Down Expand Up @@ -182,7 +190,7 @@ const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
}
bus->count_cells(dev, &na, &ns);
of_node_put(parent);
if (!OF_CHECK_COUNTS(na, ns))
if (!OF_CHECK_ADDR_COUNT(na))
return NULL;

/* Get "reg" or "assigned-addresses" property */
Expand Down Expand Up @@ -490,6 +498,25 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
}
EXPORT_SYMBOL(of_translate_dma_address);

bool of_can_translate_address(struct device_node *dev)
{
struct device_node *parent;
struct of_bus *bus;
int na, ns;

parent = of_get_parent(dev);
if (parent == NULL)
return false;

bus = of_match_bus(parent);
bus->count_cells(dev, &na, &ns);

of_node_put(parent);

return OF_CHECK_COUNTS(na, ns);
}
EXPORT_SYMBOL(of_can_translate_address);

const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
unsigned int *flags)
{
Expand All @@ -506,7 +533,7 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
bus = of_match_bus(parent);
bus->count_cells(dev, &na, &ns);
of_node_put(parent);
if (!OF_CHECK_COUNTS(na, ns))
if (!OF_CHECK_ADDR_COUNT(na))
return NULL;

/* Get "reg" or "assigned-addresses" property */
Expand Down
23 changes: 23 additions & 0 deletions drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,29 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_available_child);

/**
* of_get_child_by_name - Find the child node by name for a given parent
* @node: parent node
* @name: child name to look for.
*
* This function looks for child node for given matching name
*
* Returns a node pointer if found, with refcount incremented, use
* of_node_put() on it when done.
* Returns NULL if node is not found.
*/
struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name)
{
struct device_node *child;

for_each_child_of_node(node, child)
if (child->name && (of_node_cmp(child->name, name) == 0))
break;
return child;
}
EXPORT_SYMBOL(of_get_child_by_name);

/**
* of_find_node_by_path - Find a node matching a full OF path
* @path: The full path to match
Expand Down
1 change: 1 addition & 0 deletions drivers/of/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res,

return i;
}
EXPORT_SYMBOL_GPL(of_irq_to_resource_table);

struct intc_desc {
struct list_head list;
Expand Down
3 changes: 3 additions & 0 deletions drivers/of/of_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
info.of_node = of_node_get(node);
info.archdata = &dev_ad;

if (of_get_property(node, "wakeup-source", NULL))
info.flags |= I2C_CLIENT_WAKE;

request_module("%s%s", I2C_MODULE_PREFIX, info.type);

result = i2c_new_device(adap, &info);
Expand Down
16 changes: 13 additions & 3 deletions drivers/of/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void of_device_make_bus_id(struct device *dev)
struct device_node *node = dev->of_node;
const u32 *reg;
u64 addr;
const __be32 *addrp;
int magic;

#ifdef CONFIG_PPC_DCR
Expand Down Expand Up @@ -105,7 +106,15 @@ void of_device_make_bus_id(struct device *dev)
*/
reg = of_get_property(node, "reg", NULL);
if (reg) {
addr = of_translate_address(node, reg);
if (of_can_translate_address(node)) {
addr = of_translate_address(node, reg);
} else {
addrp = of_get_address(node, 0, NULL, NULL);
if (addrp)
addr = of_read_number(addrp, 1);
else
addr = OF_BAD_ADDR;
}
if (addr != OF_BAD_ADDR) {
dev_set_name(dev, "%llx.%s",
(unsigned long long)addr, node->name);
Expand Down Expand Up @@ -140,8 +149,9 @@ struct platform_device *of_device_alloc(struct device_node *np,
return NULL;

/* count the io and irq resources */
while (of_address_to_resource(np, num_reg, &temp_res) == 0)
num_reg++;
if (of_can_translate_address(np))
while (of_address_to_resource(np, num_reg, &temp_res) == 0)
num_reg++;
num_irq = of_irq_count(np);

/* Populate the resource table */
Expand Down
7 changes: 4 additions & 3 deletions drivers/spi/spi-s3c64xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,9 +835,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
return ERR_PTR(-EINVAL);
}

for_each_child_of_node(slave_np, data_np)
if (!strcmp(data_np->name, "controller-data"))
break;
data_np = of_get_child_by_name(slave_np, "controller-data");
if (!data_np) {
dev_err(&spi->dev, "child node 'controller-data' not found\n");
return ERR_PTR(-EINVAL);
Expand All @@ -847,6 +845,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
if (!cs) {
dev_err(&spi->dev, "could not allocate memory for controller"
" data\n");
of_node_put(data_np);
return ERR_PTR(-ENOMEM);
}

Expand All @@ -855,11 +854,13 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
dev_err(&spi->dev, "chip select gpio is not specified or "
"invalid\n");
kfree(cs);
of_node_put(data_np);
return ERR_PTR(-EINVAL);
}

of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
cs->fb_delay = fb_delay;
of_node_put(data_np);
return cs;
}

Expand Down
2 changes: 2 additions & 0 deletions include/linux/of.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
extern struct device_node *of_get_next_available_child(
const struct device_node *node, struct device_node *prev);

extern struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name);
#define for_each_child_of_node(parent, child) \
for (child = of_get_next_child(parent, NULL); child != NULL; \
child = of_get_next_child(parent, child))
Expand Down
1 change: 1 addition & 0 deletions include/linux/of_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#ifdef CONFIG_OF_ADDRESS
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern bool of_can_translate_address(struct device_node *dev);
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
extern struct device_node *of_find_matching_node_by_address(
Expand Down
13 changes: 11 additions & 2 deletions scripts/dtc/Makefile.dtc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
checks.c
DTC_SRCS = \
checks.c \
data.c \
dtc.c \
flattree.c \
fstree.c \
livetree.c \
srcpos.c \
treesource.c \
util.c

DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
Loading

0 comments on commit a54dfb1

Please sign in to comment.