Devicetree bug fixes for v3.15

This branch contains a pair of important bug fixes for the DT code:
 - Fix some incorrect binding property names before they enter common usage
 - Fix bug where some platform devices will be unable to get their
   interrupt number when they depend on an interrupt controller that is
   not available at device creation time. This is a problem causing
   mainline to fail on a number of ARM platforms.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJTXr8WAAoJEMWQL496c2LNhzgP/RhhIS9ySzJkdPEMksnBaQbN
 JKG+wBwlzvtJSPw2xX5EpWweOd1PDqHxLjjWu7q5WIrQQyOGRAELkYg1H+5ksFo1
 obCAFOjTC7VXPGc+BX0dLN6Eq4UHP8k3Ui8zlMSZQNt+gBvYo1gX2ulR8sQgS8rF
 xw+8iNDA2GIFusQbci35yOAhp6yo/ble3KIeR5dFKeMpiVSh9rqdLS+H9HgnG5Sw
 G2LUrAeRY2yQbow3c1001HiKrJieZZSTCq8oiZDgJZY5+Qk8zamyj2xxgMoJUA8Q
 2Kcb3379vNvDgjYX61NiwyrhIbJEiao8IXq6WMDNbmH3+FUwogrnh/A/g5POtX0N
 JV5tGkc/2lfm5oBCFSzcw661XjLysPsm3nPLhnxRL/dlBVkl0IZzTVYPTqUtoKlK
 NfwKFUDgg+QVmhFQT0BDCyOGAcRsz4rNEPPB6M12OmEKgxGpetfUaFdBcJqSNaxf
 Ac6AAZCXrkLlRNOVhK333ILPxv1JRC++JAeRKNwHr9e6j2aJjUgilSuzpHJ5Lkyo
 sj6kp+n1n+giYlgc9GjM7b33tm8XEd4rbcgwCWwaypEsl4FIwPs9xMys7md8SOCE
 AAnVPVUvLGC9O2GhldeQlOgtGWzILW3zJXb2mrMIIGyLBGBx1qr3VJIZpxoddTc0
 UtIJn0X37mKY/R4/hWs4
 =B2JT
 -----END PGP SIGNATURE-----

Merge tag 'dt-for-linus' of git://git.secretlab.ca/git/linux

Pull devicetree bug fixes from Grant Likely:
 "These are some important bug fixes that need to get into v3.15.

  This branch contains a pair of important bug fixes for the DT code:

   - Fix some incorrect binding property names before they enter common
     usage

   - Fix bug where some platform devices will be unable to get their
     interrupt number when they depend on an interrupt controller that
     is not available at device creation time.  This is a problem
     causing mainline to fail on a number of ARM platforms"

* tag 'dt-for-linus' of git://git.secretlab.ca/git/linux:
  of/irq: do irq resolution in platform_get_irq
  of: selftest: add deferred probe interrupt test
  dt: Fix binding typos in clock-names and interrupt-names
This commit is contained in:
Linus Torvalds 2014-04-28 15:19:06 -07:00
commit 87c7662bea
14 changed files with 105 additions and 22 deletions

View file

@ -23,5 +23,5 @@ gmac0: ethernet@ff700000 {
interrupt-names = "macirq";
mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
clocks = <&emac_0_clk>;
clocks-names = "stmmaceth";
clock-names = "stmmaceth";
};

View file

@ -33,7 +33,7 @@ Optional properties:
- max-frame-size: See ethernet.txt file in the same directory
- clocks: If present, the first clock should be the GMAC main clock,
further clocks may be specified in derived bindings.
- clocks-names: One name for each entry in the clocks property, the
- clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth".
Examples:

View file

@ -83,7 +83,7 @@ Example:
reg = <0xfe61f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x5000>;
PIO0: gpio@fe610000 {
@ -165,7 +165,7 @@ sdhci0:sdhci@fe810000{
interrupt-parent = <&PIO3>;
#interrupt-cells = <2>;
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; /* Interrupt line via PIO3-3 */
interrupts-names = "card-detect";
interrupt-names = "card-detect";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc>;
};

View file

@ -47,7 +47,7 @@ mcasp0: mcasp0@1d00000 {
reg = <0x100000 0x3000>;
reg-names "mpu";
interrupts = <82>, <83>;
interrupts-names = "tx", "rx";
interrupt-names = "tx", "rx";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
serial-dir = <

View file

@ -802,7 +802,7 @@
<0x46000000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <80>, <81>;
interrupts-names = "tx", "rx";
interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 8>,
<&edma 9>;
@ -816,7 +816,7 @@
<0x46400000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <82>, <83>;
interrupts-names = "tx", "rx";
interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 10>,
<&edma 11>;

View file

@ -691,7 +691,7 @@
<0x46000000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <80>, <81>;
interrupts-names = "tx", "rx";
interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 8>,
<&edma 9>;
@ -705,7 +705,7 @@
<0x46400000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <82>, <83>;
interrupts-names = "tx", "rx";
interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 10>,
<&edma 11>;

View file

@ -49,7 +49,7 @@
reg = <0xfe61f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x5000>;
PIO0: gpio@fe610000 {
@ -187,7 +187,7 @@
reg = <0xfee0f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfee00000 0x8000>;
PIO5: gpio@fee00000 {
@ -282,7 +282,7 @@
reg = <0xfe82f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfe820000 0x8000>;
PIO13: gpio@fe820000 {
@ -423,7 +423,7 @@
reg = <0xfd6bf080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfd6b0000 0x3000>;
PIO100: gpio@fd6b0000 {
@ -460,7 +460,7 @@
reg = <0xfd33f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfd330000 0x5000>;
PIO103: gpio@fd330000 {

View file

@ -53,7 +53,7 @@
reg = <0xfe61f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x6000>;
PIO0: gpio@fe610000 {
@ -201,7 +201,7 @@
reg = <0xfee0f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfee00000 0x10000>;
PIO5: gpio@fee00000 {
@ -333,7 +333,7 @@
reg = <0xfe82f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfe820000 0x6000>;
PIO13: gpio@fe820000 {
@ -461,7 +461,7 @@
reg = <0xfd6bf080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfd6b0000 0x3000>;
PIO100: gpio@fd6b0000 {
@ -498,7 +498,7 @@
reg = <0xfd33f080 0x4>;
reg-names = "irqmux";
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux";
interrupt-names = "irqmux";
ranges = <0 0xfd330000 0x5000>;
PIO103: gpio@fd330000 {

View file

@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
return -ENXIO;
return dev->archdata.irqs[num];
#else
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
struct resource *r;
if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node)
return of_irq_get(dev->dev.of_node, num);
r = platform_get_resource(dev, IORESOURCE_IRQ, num);
return r ? r->start : -ENXIO;
#endif

View file

@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
memset(r, 0, sizeof(*r));
/*
* Get optional "interrupts-names" property to add a name
* Get optional "interrupt-names" property to add a name
* to the resource.
*/
of_property_read_string_index(dev, "interrupt-names", index,
@ -379,6 +379,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
}
EXPORT_SYMBOL_GPL(of_irq_to_resource);
/**
* of_irq_get - Decode a node's IRQ and return it as a Linux irq number
* @dev: pointer to device tree node
* @index: zero-based index of the irq
*
* Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
* is not yet created.
*
*/
int of_irq_get(struct device_node *dev, int index)
{
int rc;
struct of_phandle_args oirq;
struct irq_domain *domain;
rc = of_irq_parse_one(dev, index, &oirq);
if (rc)
return rc;
domain = irq_find_host(oirq.np);
if (!domain)
return -EPROBE_DEFER;
return irq_create_of_mapping(&oirq);
}
/**
* of_irq_count - Count the number of IRQs a node uses
* @dev: pointer to device tree node

View file

@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np,
rc = of_address_to_resource(np, i, res);
WARN_ON(rc);
}
WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
pr_debug("not all legacy IRQ resources mapped for %s\n",
np->name);
}
dev->dev.of_node = of_node_get(np);

View file

@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@ -427,6 +428,36 @@ static void __init of_selftest_match_node(void)
}
}
static void __init of_selftest_platform_populate(void)
{
int irq;
struct device_node *np;
struct platform_device *pdev;
np = of_find_node_by_path("/testcase-data");
of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
/* Test that a missing irq domain returns -EPROBE_DEFER */
np = of_find_node_by_path("/testcase-data/testcase-device1");
pdev = of_find_device_by_node(np);
if (!pdev)
selftest(0, "device 1 creation failed\n");
irq = platform_get_irq(pdev, 0);
if (irq != -EPROBE_DEFER)
selftest(0, "device deferred probe failed - %d\n", irq);
/* Test that a parsing failure does not return -EPROBE_DEFER */
np = of_find_node_by_path("/testcase-data/testcase-device2");
pdev = of_find_device_by_node(np);
if (!pdev)
selftest(0, "device 2 creation failed\n");
irq = platform_get_irq(pdev, 0);
if (irq >= 0 || irq == -EPROBE_DEFER)
selftest(0, "device parsing error failed - %d\n", irq);
selftest(1, "passed");
}
static int __init of_selftest(void)
{
struct device_node *np;
@ -445,6 +476,7 @@ static int __init of_selftest(void)
of_selftest_parse_interrupts();
of_selftest_parse_interrupts_extended();
of_selftest_match_node();
of_selftest_platform_populate();
pr_info("end of selftest - %i passed, %i failed\n",
selftest_results.passed, selftest_results.failed);
return 0;

View file

@ -54,5 +54,18 @@
<&test_intmap1 1 2>;
};
};
testcase-device1 {
compatible = "testcase-device";
interrupt-parent = <&test_intc0>;
interrupts = <1>;
};
testcase-device2 {
compatible = "testcase-device";
interrupt-parent = <&test_intc2>;
interrupts = <1>; /* invalid specifier - too short */
};
};
};

View file

@ -44,11 +44,16 @@ extern void of_irq_init(const struct of_device_id *matches);
#ifdef CONFIG_OF_IRQ
extern int of_irq_count(struct device_node *dev);
extern int of_irq_get(struct device_node *dev, int index);
#else
static inline int of_irq_count(struct device_node *dev)
{
return 0;
}
static inline int of_irq_get(struct device_node *dev, int index)
{
return 0;
}
#endif
#if defined(CONFIG_OF)