提交 87c7662b 编写于 作者: L Linus Torvalds

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
...@@ -23,5 +23,5 @@ gmac0: ethernet@ff700000 { ...@@ -23,5 +23,5 @@ gmac0: ethernet@ff700000 {
interrupt-names = "macirq"; interrupt-names = "macirq";
mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */ mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
clocks = <&emac_0_clk>; clocks = <&emac_0_clk>;
clocks-names = "stmmaceth"; clock-names = "stmmaceth";
}; };
...@@ -33,7 +33,7 @@ Optional properties: ...@@ -33,7 +33,7 @@ Optional properties:
- max-frame-size: See ethernet.txt file in the same directory - max-frame-size: See ethernet.txt file in the same directory
- clocks: If present, the first clock should be the GMAC main clock, - clocks: If present, the first clock should be the GMAC main clock,
further clocks may be specified in derived bindings. 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". first one should be "stmmaceth".
Examples: Examples:
......
...@@ -83,7 +83,7 @@ Example: ...@@ -83,7 +83,7 @@ Example:
reg = <0xfe61f080 0x4>; reg = <0xfe61f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x5000>; ranges = <0 0xfe610000 0x5000>;
PIO0: gpio@fe610000 { PIO0: gpio@fe610000 {
...@@ -165,7 +165,7 @@ sdhci0:sdhci@fe810000{ ...@@ -165,7 +165,7 @@ sdhci0:sdhci@fe810000{
interrupt-parent = <&PIO3>; interrupt-parent = <&PIO3>;
#interrupt-cells = <2>; #interrupt-cells = <2>;
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; /* Interrupt line via PIO3-3 */ interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; /* Interrupt line via PIO3-3 */
interrupts-names = "card-detect"; interrupt-names = "card-detect";
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc>; pinctrl-0 = <&pinctrl_mmc>;
}; };
...@@ -47,7 +47,7 @@ mcasp0: mcasp0@1d00000 { ...@@ -47,7 +47,7 @@ mcasp0: mcasp0@1d00000 {
reg = <0x100000 0x3000>; reg = <0x100000 0x3000>;
reg-names "mpu"; reg-names "mpu";
interrupts = <82>, <83>; interrupts = <82>, <83>;
interrupts-names = "tx", "rx"; interrupt-names = "tx", "rx";
op-mode = <0>; /* MCASP_IIS_MODE */ op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>; tdm-slots = <2>;
serial-dir = < serial-dir = <
......
...@@ -802,7 +802,7 @@ ...@@ -802,7 +802,7 @@
<0x46000000 0x400000>; <0x46000000 0x400000>;
reg-names = "mpu", "dat"; reg-names = "mpu", "dat";
interrupts = <80>, <81>; interrupts = <80>, <81>;
interrupts-names = "tx", "rx"; interrupt-names = "tx", "rx";
status = "disabled"; status = "disabled";
dmas = <&edma 8>, dmas = <&edma 8>,
<&edma 9>; <&edma 9>;
...@@ -816,7 +816,7 @@ ...@@ -816,7 +816,7 @@
<0x46400000 0x400000>; <0x46400000 0x400000>;
reg-names = "mpu", "dat"; reg-names = "mpu", "dat";
interrupts = <82>, <83>; interrupts = <82>, <83>;
interrupts-names = "tx", "rx"; interrupt-names = "tx", "rx";
status = "disabled"; status = "disabled";
dmas = <&edma 10>, dmas = <&edma 10>,
<&edma 11>; <&edma 11>;
......
...@@ -691,7 +691,7 @@ ...@@ -691,7 +691,7 @@
<0x46000000 0x400000>; <0x46000000 0x400000>;
reg-names = "mpu", "dat"; reg-names = "mpu", "dat";
interrupts = <80>, <81>; interrupts = <80>, <81>;
interrupts-names = "tx", "rx"; interrupt-names = "tx", "rx";
status = "disabled"; status = "disabled";
dmas = <&edma 8>, dmas = <&edma 8>,
<&edma 9>; <&edma 9>;
...@@ -705,7 +705,7 @@ ...@@ -705,7 +705,7 @@
<0x46400000 0x400000>; <0x46400000 0x400000>;
reg-names = "mpu", "dat"; reg-names = "mpu", "dat";
interrupts = <82>, <83>; interrupts = <82>, <83>;
interrupts-names = "tx", "rx"; interrupt-names = "tx", "rx";
status = "disabled"; status = "disabled";
dmas = <&edma 10>, dmas = <&edma 10>,
<&edma 11>; <&edma 11>;
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
reg = <0xfe61f080 0x4>; reg = <0xfe61f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x5000>; ranges = <0 0xfe610000 0x5000>;
PIO0: gpio@fe610000 { PIO0: gpio@fe610000 {
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
reg = <0xfee0f080 0x4>; reg = <0xfee0f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfee00000 0x8000>; ranges = <0 0xfee00000 0x8000>;
PIO5: gpio@fee00000 { PIO5: gpio@fee00000 {
...@@ -282,7 +282,7 @@ ...@@ -282,7 +282,7 @@
reg = <0xfe82f080 0x4>; reg = <0xfe82f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfe820000 0x8000>; ranges = <0 0xfe820000 0x8000>;
PIO13: gpio@fe820000 { PIO13: gpio@fe820000 {
...@@ -423,7 +423,7 @@ ...@@ -423,7 +423,7 @@
reg = <0xfd6bf080 0x4>; reg = <0xfd6bf080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfd6b0000 0x3000>; ranges = <0 0xfd6b0000 0x3000>;
PIO100: gpio@fd6b0000 { PIO100: gpio@fd6b0000 {
...@@ -460,7 +460,7 @@ ...@@ -460,7 +460,7 @@
reg = <0xfd33f080 0x4>; reg = <0xfd33f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfd330000 0x5000>; ranges = <0 0xfd330000 0x5000>;
PIO103: gpio@fd330000 { PIO103: gpio@fd330000 {
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
reg = <0xfe61f080 0x4>; reg = <0xfe61f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfe610000 0x6000>; ranges = <0 0xfe610000 0x6000>;
PIO0: gpio@fe610000 { PIO0: gpio@fe610000 {
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
reg = <0xfee0f080 0x4>; reg = <0xfee0f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfee00000 0x10000>; ranges = <0 0xfee00000 0x10000>;
PIO5: gpio@fee00000 { PIO5: gpio@fee00000 {
...@@ -333,7 +333,7 @@ ...@@ -333,7 +333,7 @@
reg = <0xfe82f080 0x4>; reg = <0xfe82f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfe820000 0x6000>; ranges = <0 0xfe820000 0x6000>;
PIO13: gpio@fe820000 { PIO13: gpio@fe820000 {
...@@ -461,7 +461,7 @@ ...@@ -461,7 +461,7 @@
reg = <0xfd6bf080 0x4>; reg = <0xfd6bf080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfd6b0000 0x3000>; ranges = <0 0xfd6b0000 0x3000>;
PIO100: gpio@fd6b0000 { PIO100: gpio@fd6b0000 {
...@@ -498,7 +498,7 @@ ...@@ -498,7 +498,7 @@
reg = <0xfd33f080 0x4>; reg = <0xfd33f080 0x4>;
reg-names = "irqmux"; reg-names = "irqmux";
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
interrupts-names = "irqmux"; interrupt-names = "irqmux";
ranges = <0 0xfd330000 0x5000>; ranges = <0 0xfd330000 0x5000>;
PIO103: gpio@fd330000 { PIO103: gpio@fd330000 {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) ...@@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
return -ENXIO; return -ENXIO;
return dev->archdata.irqs[num]; return dev->archdata.irqs[num];
#else #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; return r ? r->start : -ENXIO;
#endif #endif
......
...@@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) ...@@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
memset(r, 0, sizeof(*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. * to the resource.
*/ */
of_property_read_string_index(dev, "interrupt-names", index, 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) ...@@ -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); 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 * of_irq_count - Count the number of IRQs a node uses
* @dev: pointer to device tree node * @dev: pointer to device tree node
......
...@@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np, ...@@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np,
rc = of_address_to_resource(np, i, res); rc = of_address_to_resource(np, i, res);
WARN_ON(rc); 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); dev->dev.of_node = of_node_get(np);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -427,6 +428,36 @@ static void __init of_selftest_match_node(void) ...@@ -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) static int __init of_selftest(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -445,6 +476,7 @@ static int __init of_selftest(void) ...@@ -445,6 +476,7 @@ static int __init of_selftest(void)
of_selftest_parse_interrupts(); of_selftest_parse_interrupts();
of_selftest_parse_interrupts_extended(); of_selftest_parse_interrupts_extended();
of_selftest_match_node(); of_selftest_match_node();
of_selftest_platform_populate();
pr_info("end of selftest - %i passed, %i failed\n", pr_info("end of selftest - %i passed, %i failed\n",
selftest_results.passed, selftest_results.failed); selftest_results.passed, selftest_results.failed);
return 0; return 0;
......
...@@ -54,5 +54,18 @@ ...@@ -54,5 +54,18 @@
<&test_intmap1 1 2>; <&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 */
};
}; };
}; };
...@@ -44,11 +44,16 @@ extern void of_irq_init(const struct of_device_id *matches); ...@@ -44,11 +44,16 @@ extern void of_irq_init(const struct of_device_id *matches);
#ifdef CONFIG_OF_IRQ #ifdef CONFIG_OF_IRQ
extern int of_irq_count(struct device_node *dev); extern int of_irq_count(struct device_node *dev);
extern int of_irq_get(struct device_node *dev, int index);
#else #else
static inline int of_irq_count(struct device_node *dev) static inline int of_irq_count(struct device_node *dev)
{ {
return 0; return 0;
} }
static inline int of_irq_get(struct device_node *dev, int index)
{
return 0;
}
#endif #endif
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册