diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 18:54:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 18:54:50 -0400 |
commit | 8954672d86d036643e3ce7ce3b2422c336db66d0 (patch) | |
tree | f68f4f97fe7a9e43d4ada455bbaf3a5af5725b34 | |
parent | 3be1b98e073bdd4c1bb3144201a927c4a21330ba (diff) | |
parent | b7dccbea6b079be01e07921264709f249009b8e8 (diff) |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq core updates from Thomas Gleixner:
"Managerial summary:
Core code:
- final removal of IRQF_DISABLED
- new state save/restore functions for virtualization support
- wakeup support for stacked irqdomains
- new function to solve the netpoll synchronization problem
irqchips:
- new driver for STi based devices
- new driver for Vybrid MSCM
- massive cleanup of the GIC driver by moving the GIC-addons to
stacked irqdomains
- the usual pile of fixes and updates to the various chip drivers"
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
irqchip: GICv3: Add support for irq_[get, set]_irqchip_state()
irqchip: GIC: Add support for irq_[get, set]_irqchip_state()
genirq: Allow the irqchip state of an IRQ to be save/restored
genirq: MSI: Fix freeing of unallocated MSI
irqchip: renesas-irqc: Add wake-up support
irqchip: armada-370-xp: Allow using wakeup source
irqchip: mips-gic: Add new functions to start/stop the GIC counter
irqchip: tegra: Add Tegra210 support
irqchip: digicolor: Move digicolor_set_gc to init section
irqchip: renesas-irqc: Add functional clock to bindings
irqchip: renesas-irqc: Add minimal runtime PM support
irqchip: renesas-irqc: Add more register documentation
DT: exynos: update PMU binding
ARM: exynos4/5: convert pmu wakeup to stacked domains
irqchip: gic: Don't complain in gic_get_cpumask() if UP system
ARM: zynq: switch from gic_arch_extn to gic_set_irqchip_flags
ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags
ARM: shmobile: remove use of gic_arch_extn.irq_set_wake
irqchip: gic: Add an entry point to set up irqchip flags
ARM: omap: convert wakeupgen to stacked domains
...
79 files changed, 2032 insertions, 669 deletions
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt new file mode 100644 index 000000000000..44aa3c451ccf --- /dev/null +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt | |||
@@ -0,0 +1,14 @@ | |||
1 | Freescale Vybrid Miscellaneous System Control - CPU Configuration | ||
2 | |||
3 | The MSCM IP contains multiple sub modules, this binding describes the first | ||
4 | block of registers which contains CPU configuration information. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: "fsl,vf610-mscm-cpucfg", "syscon" | ||
8 | - reg: the register range of the MSCM CPU configuration registers | ||
9 | |||
10 | Example: | ||
11 | mscm_cpucfg: cpucfg@40001000 { | ||
12 | compatible = "fsl,vf610-mscm-cpucfg", "syscon"; | ||
13 | reg = <0x40001000 0x800>; | ||
14 | } | ||
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt new file mode 100644 index 000000000000..669808b2af49 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt | |||
@@ -0,0 +1,33 @@ | |||
1 | Freescale Vybrid Miscellaneous System Control - Interrupt Router | ||
2 | |||
3 | The MSCM IP contains multiple sub modules, this binding describes the second | ||
4 | block of registers which control the interrupt router. The interrupt router | ||
5 | allows to configure the recipient of each peripheral interrupt. Furthermore | ||
6 | it controls the directed processor interrupts. The module is available in all | ||
7 | Vybrid SoC's but is only really useful in dual core configurations (VF6xx | ||
8 | which comes with a Cortex-A5/Cortex-M4 combination). | ||
9 | |||
10 | Required properties: | ||
11 | - compatible: "fsl,vf610-mscm-ir" | ||
12 | - reg: the register range of the MSCM Interrupt Router | ||
13 | - fsl,cpucfg: The handle to the MSCM CPU configuration node, required | ||
14 | to get the current CPU ID | ||
15 | - interrupt-controller: Identifies the node as an interrupt controller | ||
16 | - #interrupt-cells: Two cells, interrupt number and cells. | ||
17 | The hardware interrupt number according to interrupt | ||
18 | assignment of the interrupt router is required. | ||
19 | Flags get passed only when using GIC as parent. Flags | ||
20 | encoding as documented by the GIC bindings. | ||
21 | - interrupt-parent: Should be the phandle for the interrupt controller of | ||
22 | the CPU the device tree is intended to be used on. This | ||
23 | is either the node of the GIC or NVIC controller. | ||
24 | |||
25 | Example: | ||
26 | mscm_ir: interrupt-controller@40001800 { | ||
27 | compatible = "fsl,vf610-mscm-ir"; | ||
28 | reg = <0x40001800 0x400>; | ||
29 | fsl,cpucfg = <&mscm_cpucfg>; | ||
30 | interrupt-controller; | ||
31 | #interrupt-cells = <2>; | ||
32 | interrupt-parent = <&intc>; | ||
33 | } | ||
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index c97484b73e72..1e0d21201d3a 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt | |||
@@ -56,11 +56,6 @@ Optional | |||
56 | regions, used when the GIC doesn't have banked registers. The offset is | 56 | regions, used when the GIC doesn't have banked registers. The offset is |
57 | cpu-offset * cpu-nr. | 57 | cpu-offset * cpu-nr. |
58 | 58 | ||
59 | - arm,routable-irqs : Total number of gic irq inputs which are not directly | ||
60 | connected from the peripherals, but are routed dynamically | ||
61 | by a crossbar/multiplexer preceding the GIC. The GIC irq | ||
62 | input line is assigned dynamically when the corresponding | ||
63 | peripheral's crossbar line is mapped. | ||
64 | Example: | 59 | Example: |
65 | 60 | ||
66 | intc: interrupt-controller@fff11000 { | 61 | intc: interrupt-controller@fff11000 { |
@@ -68,7 +63,6 @@ Example: | |||
68 | #interrupt-cells = <3>; | 63 | #interrupt-cells = <3>; |
69 | #address-cells = <1>; | 64 | #address-cells = <1>; |
70 | interrupt-controller; | 65 | interrupt-controller; |
71 | arm,routable-irqs = <160>; | ||
72 | reg = <0xfff11000 0x1000>, | 66 | reg = <0xfff11000 0x1000>, |
73 | <0xfff10100 0x100>; | 67 | <0xfff10100 0x100>; |
74 | }; | 68 | }; |
diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt index 4139db353d0a..a9b28d74d902 100644 --- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt | |||
@@ -9,7 +9,9 @@ inputs. | |||
9 | Required properties: | 9 | Required properties: |
10 | - compatible : Should be "ti,irq-crossbar" | 10 | - compatible : Should be "ti,irq-crossbar" |
11 | - reg: Base address and the size of the crossbar registers. | 11 | - reg: Base address and the size of the crossbar registers. |
12 | - ti,max-irqs: Total number of irqs available at the interrupt controller. | 12 | - interrupt-controller: indicates that this block is an interrupt controller. |
13 | - interrupt-parent: the interrupt controller this block is connected to. | ||
14 | - ti,max-irqs: Total number of irqs available at the parent interrupt controller. | ||
13 | - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed. | 15 | - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed. |
14 | - ti,reg-size: Size of a individual register in bytes. Every individual | 16 | - ti,reg-size: Size of a individual register in bytes. Every individual |
15 | register is assumed to be of same size. Valid sizes are 1, 2, 4. | 17 | register is assumed to be of same size. Valid sizes are 1, 2, 4. |
@@ -27,13 +29,13 @@ Optional properties: | |||
27 | when the interrupt controller irq is unused (when not provided, default is 0) | 29 | when the interrupt controller irq is unused (when not provided, default is 0) |
28 | 30 | ||
29 | Examples: | 31 | Examples: |
30 | crossbar_mpu: @4a020000 { | 32 | crossbar_mpu: crossbar@4a002a48 { |
31 | compatible = "ti,irq-crossbar"; | 33 | compatible = "ti,irq-crossbar"; |
32 | reg = <0x4a002a48 0x130>; | 34 | reg = <0x4a002a48 0x130>; |
33 | ti,max-irqs = <160>; | 35 | ti,max-irqs = <160>; |
34 | ti,max-crossbar-sources = <400>; | 36 | ti,max-crossbar-sources = <400>; |
35 | ti,reg-size = <2>; | 37 | ti,reg-size = <2>; |
36 | ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>; | 38 | ti,irqs-reserved = <0 1 2 3 5 6 131 132>; |
37 | ti,irqs-skip = <10 133 139 140>; | 39 | ti,irqs-skip = <10 133 139 140>; |
38 | }; | 40 | }; |
39 | 41 | ||
@@ -44,10 +46,6 @@ Documentation/devicetree/bindings/arm/gic.txt for further details. | |||
44 | 46 | ||
45 | An interrupt consumer on an SoC using crossbar will use: | 47 | An interrupt consumer on an SoC using crossbar will use: |
46 | interrupts = <GIC_SPI request_number interrupt_level> | 48 | interrupts = <GIC_SPI request_number interrupt_level> |
47 | When the request number is between 0 to that described by | ||
48 | "ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the | ||
49 | request_number is greater than "ti,max-crossbar-sources", then it is mapped as a | ||
50 | quirky hardware mapping direct to GIC. | ||
51 | 49 | ||
52 | Example: | 50 | Example: |
53 | device_x@0x4a023000 { | 51 | device_x@0x4a023000 { |
@@ -55,9 +53,3 @@ Example: | |||
55 | interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; | 53 | interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; |
56 | ... | 54 | ... |
57 | }; | 55 | }; |
58 | |||
59 | device_y@0x4a033000 { | ||
60 | /* Direct mapped GIC SPI 1 used */ | ||
61 | interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>; | ||
62 | ... | ||
63 | }; | ||
diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt index 67b211381f2b..2d6356d8daf4 100644 --- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt +++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt | |||
@@ -29,10 +29,27 @@ Properties: | |||
29 | - clocks : list of phandles and specifiers to all input clocks listed in | 29 | - clocks : list of phandles and specifiers to all input clocks listed in |
30 | clock-names property. | 30 | clock-names property. |
31 | 31 | ||
32 | Optional properties: | ||
33 | |||
34 | Some PMUs are capable of behaving as an interrupt controller (mostly | ||
35 | to wake up a suspended PMU). In which case, they can have the | ||
36 | following properties: | ||
37 | |||
38 | - interrupt-controller: indicate that said PMU is an interrupt controller | ||
39 | |||
40 | - #interrupt-cells: must be identical to the that of the parent interrupt | ||
41 | controller. | ||
42 | |||
43 | - interrupt-parent: a phandle indicating which interrupt controller | ||
44 | this PMU signals interrupts to. | ||
45 | |||
32 | Example : | 46 | Example : |
33 | pmu_system_controller: system-controller@10040000 { | 47 | pmu_system_controller: system-controller@10040000 { |
34 | compatible = "samsung,exynos5250-pmu", "syscon"; | 48 | compatible = "samsung,exynos5250-pmu", "syscon"; |
35 | reg = <0x10040000 0x5000>; | 49 | reg = <0x10040000 0x5000>; |
50 | interrupt-controller; | ||
51 | #interrupt-cells = <3>; | ||
52 | interrupt-parent = <&gic>; | ||
36 | #clock-cells = <1>; | 53 | #clock-cells = <1>; |
37 | clock-names = "clkout0", "clkout1", "clkout2", "clkout3", | 54 | clock-names = "clkout0", "clkout1", "clkout2", "clkout3", |
38 | "clkout4", "clkout8", "clkout9"; | 55 | "clkout4", "clkout8", "clkout9"; |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt new file mode 100644 index 000000000000..1099fe0788fa --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt | |||
@@ -0,0 +1,43 @@ | |||
1 | NVIDIA Legacy Interrupt Controller | ||
2 | |||
3 | All Tegra SoCs contain a legacy interrupt controller that routes | ||
4 | interrupts to the GIC, and also serves as a wakeup source. It is also | ||
5 | referred to as "ictlr", hence the name of the binding. | ||
6 | |||
7 | The HW block exposes a number of interrupt controllers, each | ||
8 | implementing a set of 32 interrupts. | ||
9 | |||
10 | Required properties: | ||
11 | |||
12 | - compatible : should be: "nvidia,tegra<chip>-ictlr". The LIC on | ||
13 | subsequent SoCs remained backwards-compatible with Tegra30, so on | ||
14 | Tegra generations later than Tegra30 the compatible value should | ||
15 | include "nvidia,tegra30-ictlr". | ||
16 | - reg : Specifies base physical address and size of the registers. | ||
17 | Each controller must be described separately (Tegra20 has 4 of them, | ||
18 | whereas Tegra30 and later have 5" | ||
19 | - interrupt-controller : Identifies the node as an interrupt controller. | ||
20 | - #interrupt-cells : Specifies the number of cells needed to encode an | ||
21 | interrupt source. The value must be 3. | ||
22 | - interrupt-parent : a phandle to the GIC these interrupts are routed | ||
23 | to. | ||
24 | |||
25 | Notes: | ||
26 | |||
27 | - Because this HW ultimately routes interrupts to the GIC, the | ||
28 | interrupt specifier must be that of the GIC. | ||
29 | - Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs | ||
30 | are explicitly forbidden. | ||
31 | |||
32 | Example: | ||
33 | |||
34 | ictlr: interrupt-controller@60004000 { | ||
35 | compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr"; | ||
36 | reg = <0x60004000 64>, | ||
37 | <0x60004100 64>, | ||
38 | <0x60004200 64>, | ||
39 | <0x60004300 64>; | ||
40 | interrupt-controller; | ||
41 | #interrupt-cells = <3>; | ||
42 | interrupt-parent = <&intc>; | ||
43 | }; | ||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt index 1a88e62228e5..63633bdea7e4 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt | |||
@@ -4,7 +4,7 @@ Required properties: | |||
4 | 4 | ||
5 | - compatible: has to be "renesas,irqc-<soctype>", "renesas,irqc" as fallback. | 5 | - compatible: has to be "renesas,irqc-<soctype>", "renesas,irqc" as fallback. |
6 | Examples with soctypes are: | 6 | Examples with soctypes are: |
7 | - "renesas,irqc-r8a73a4" (R-Mobile AP6) | 7 | - "renesas,irqc-r8a73a4" (R-Mobile APE6) |
8 | - "renesas,irqc-r8a7790" (R-Car H2) | 8 | - "renesas,irqc-r8a7790" (R-Car H2) |
9 | - "renesas,irqc-r8a7791" (R-Car M2-W) | 9 | - "renesas,irqc-r8a7791" (R-Car M2-W) |
10 | - "renesas,irqc-r8a7792" (R-Car V2H) | 10 | - "renesas,irqc-r8a7792" (R-Car V2H) |
@@ -12,6 +12,7 @@ Required properties: | |||
12 | - "renesas,irqc-r8a7794" (R-Car E2) | 12 | - "renesas,irqc-r8a7794" (R-Car E2) |
13 | - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in | 13 | - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in |
14 | interrupts.txt in this directory | 14 | interrupts.txt in this directory |
15 | - clocks: Must contain a reference to the functional clock. | ||
15 | 16 | ||
16 | Optional properties: | 17 | Optional properties: |
17 | 18 | ||
@@ -29,4 +30,5 @@ Example: | |||
29 | <0 1 IRQ_TYPE_LEVEL_HIGH>, | 30 | <0 1 IRQ_TYPE_LEVEL_HIGH>, |
30 | <0 2 IRQ_TYPE_LEVEL_HIGH>, | 31 | <0 2 IRQ_TYPE_LEVEL_HIGH>, |
31 | <0 3 IRQ_TYPE_LEVEL_HIGH>; | 32 | <0 3 IRQ_TYPE_LEVEL_HIGH>; |
33 | clocks = <&mstp4_clks R8A7790_CLK_IRQC>; | ||
32 | }; | 34 | }; |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt b/Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt new file mode 100644 index 000000000000..ced6014061a3 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt | |||
@@ -0,0 +1,35 @@ | |||
1 | STMicroelectronics STi System Configuration Controlled IRQs | ||
2 | ----------------------------------------------------------- | ||
3 | |||
4 | On STi based systems; External, CTI (Core Sight), PMU (Performance Management), | ||
5 | and PL310 L2 Cache IRQs are controlled using System Configuration registers. | ||
6 | This driver is used to unmask them prior to use. | ||
7 | |||
8 | Required properties: | ||
9 | - compatible : Should be set to one of: | ||
10 | "st,stih415-irq-syscfg" | ||
11 | "st,stih416-irq-syscfg" | ||
12 | "st,stih407-irq-syscfg" | ||
13 | "st,stid127-irq-syscfg" | ||
14 | - st,syscfg : Phandle to Cortex-A9 IRQ system config registers | ||
15 | - st,irq-device : Array of IRQs to enable - should be 2 in length | ||
16 | - st,fiq-device : Array of FIQs to enable - should be 2 in length | ||
17 | |||
18 | Optional properties: | ||
19 | - st,invert-ext : External IRQs can be inverted at will. This property inverts | ||
20 | these IRQs using bitwise logic. A number of defines have been | ||
21 | provided for convenience: | ||
22 | ST_IRQ_SYSCFG_EXT_1_INV | ||
23 | ST_IRQ_SYSCFG_EXT_2_INV | ||
24 | ST_IRQ_SYSCFG_EXT_3_INV | ||
25 | Example: | ||
26 | |||
27 | irq-syscfg { | ||
28 | compatible = "st,stih416-irq-syscfg"; | ||
29 | st,syscfg = <&syscfg_cpu>; | ||
30 | st,irq-device = <ST_IRQ_SYSCFG_PMU_0>, | ||
31 | <ST_IRQ_SYSCFG_PMU_1>; | ||
32 | st,fiq-device = <ST_IRQ_SYSCFG_DISABLED>, | ||
33 | <ST_IRQ_SYSCFG_DISABLED>; | ||
34 | st,invert-ext = <(ST_IRQ_SYSCFG_EXT_1_INV | ST_IRQ_SYSCFG_EXT_3_INV)>; | ||
35 | }; | ||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu new file mode 100644 index 000000000000..43effa0a4fe7 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu | |||
@@ -0,0 +1,33 @@ | |||
1 | TI OMAP4 Wake-up Generator | ||
2 | |||
3 | All TI OMAP4/5 (and their derivatives) an interrupt controller that | ||
4 | routes interrupts to the GIC, and also serves as a wakeup source. It | ||
5 | is also referred to as "WUGEN-MPU", hence the name of the binding. | ||
6 | |||
7 | Reguired properties: | ||
8 | |||
9 | - compatible : should contain at least "ti,omap4-wugen-mpu" or | ||
10 | "ti,omap5-wugen-mpu" | ||
11 | - reg : Specifies base physical address and size of the registers. | ||
12 | - interrupt-controller : Identifies the node as an interrupt controller. | ||
13 | - #interrupt-cells : Specifies the number of cells needed to encode an | ||
14 | interrupt source. The value must be 3. | ||
15 | - interrupt-parent : a phandle to the GIC these interrupts are routed | ||
16 | to. | ||
17 | |||
18 | Notes: | ||
19 | |||
20 | - Because this HW ultimately routes interrupts to the GIC, the | ||
21 | interrupt specifier must be that of the GIC. | ||
22 | - Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs | ||
23 | are explicitly forbiden. | ||
24 | |||
25 | Example: | ||
26 | |||
27 | wakeupgen: interrupt-controller@48281000 { | ||
28 | compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu"; | ||
29 | interrupt-controller; | ||
30 | #interrupt-cells = <3>; | ||
31 | reg = <0x48281000 0x1000>; | ||
32 | interrupt-parent = <&gic>; | ||
33 | }; | ||
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt index 1d508dcbf859..8586efff1e99 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.txt | |||
@@ -786,7 +786,6 @@ port address 0x1400. | |||
786 | irqm:1 same as initial settings (assumed BIOS settings) | 786 | irqm:1 same as initial settings (assumed BIOS settings) |
787 | irqm:2 always totem pole | 787 | irqm:2 always totem pole |
788 | irqm:0x10 driver will not use IRQF_SHARED flag when requesting irq | 788 | irqm:0x10 driver will not use IRQF_SHARED flag when requesting irq |
789 | irqm:0x20 driver will not use IRQF_DISABLED flag when requesting irq | ||
790 | 789 | ||
791 | (Bits 0x10 and 0x20 can be combined with hardware irq mode option) | 790 | (Bits 0x10 and 0x20 can be combined with hardware irq mode option) |
792 | 791 | ||
@@ -1231,30 +1230,6 @@ they only refer to system buffers that are well aligned. So, a work around | |||
1231 | may only be needed under Linux when a scatter/gather list is not used and | 1230 | may only be needed under Linux when a scatter/gather list is not used and |
1232 | when the SCSI DATA IN phase is reentered after a phase mismatch. | 1231 | when the SCSI DATA IN phase is reentered after a phase mismatch. |
1233 | 1232 | ||
1234 | 14.5 IRQ sharing problems | ||
1235 | |||
1236 | When an IRQ is shared by devices that are handled by different drivers, it | ||
1237 | may happen that one driver complains about the request of the IRQ having | ||
1238 | failed. Inder Linux-2.0, this may be due to one driver having requested the | ||
1239 | IRQ using the IRQF_DISABLED flag but some other having requested the same IRQ | ||
1240 | without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by | ||
1241 | one driver not having requested the IRQ with the IRQF_SHARED flag. | ||
1242 | |||
1243 | By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the | ||
1244 | IRQF_DISABLED and the IRQF_SHARED flag under Linux-2.0 and with only the IRQF_SHARED | ||
1245 | flag under Linux-2.2. | ||
1246 | |||
1247 | Under Linux-2.0, you can disable use of IRQF_DISABLED flag from the boot | ||
1248 | command line by using the following option: | ||
1249 | |||
1250 | ncr53c8xx=irqm:0x20 (for the generic ncr53c8xx driver) | ||
1251 | sym53c8xx=irqm:0x20 (for the sym53c8xx driver) | ||
1252 | |||
1253 | If this does not fix the problem, then you may want to check how all other | ||
1254 | drivers are requesting the IRQ and report the problem. Note that if at least | ||
1255 | a single driver does not request the IRQ with the IRQF_SHARED flag (share IRQ), | ||
1256 | then the request of the IRQ obviously will not succeed for all the drivers. | ||
1257 | |||
1258 | 15. SCSI problem troubleshooting | 1233 | 15. SCSI problem troubleshooting |
1259 | 1234 | ||
1260 | 15.1 Problem tracking | 1235 | 15.1 Problem tracking |
diff --git a/Documentation/scsi/tmscsim.txt b/Documentation/scsi/tmscsim.txt index 0810132772a8..0e0322bf0020 100644 --- a/Documentation/scsi/tmscsim.txt +++ b/Documentation/scsi/tmscsim.txt | |||
@@ -107,10 +107,6 @@ produced errors and started to corrupt my disks. So don't do that! A 37.50 | |||
107 | MHz PCI bus works for me, though, but I don't recommend using higher clocks | 107 | MHz PCI bus works for me, though, but I don't recommend using higher clocks |
108 | than the 33.33 MHz being in the PCI spec. | 108 | than the 33.33 MHz being in the PCI spec. |
109 | 109 | ||
110 | If you want to share the IRQ with another device and the driver refuses to | ||
111 | do so, you might succeed with changing the DC390_IRQ type in tmscsim.c to | ||
112 | IRQF_SHARED | IRQF_DISABLED. | ||
113 | |||
114 | 110 | ||
115 | 3.Features | 111 | 3.Features |
116 | ---------- | 112 | ---------- |
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 1943fc333e7c..8a099bc10c1e 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | / { | 16 | / { |
17 | compatible = "ti,am4372", "ti,am43"; | 17 | compatible = "ti,am4372", "ti,am43"; |
18 | interrupt-parent = <&gic>; | 18 | interrupt-parent = <&wakeupgen>; |
19 | 19 | ||
20 | 20 | ||
21 | aliases { | 21 | aliases { |
@@ -48,6 +48,15 @@ | |||
48 | #interrupt-cells = <3>; | 48 | #interrupt-cells = <3>; |
49 | reg = <0x48241000 0x1000>, | 49 | reg = <0x48241000 0x1000>, |
50 | <0x48240100 0x0100>; | 50 | <0x48240100 0x0100>; |
51 | interrupt-parent = <&gic>; | ||
52 | }; | ||
53 | |||
54 | wakeupgen: interrupt-controller@48281000 { | ||
55 | compatible = "ti,omap4-wugen-mpu"; | ||
56 | interrupt-controller; | ||
57 | #interrupt-cells = <3>; | ||
58 | reg = <0x48281000 0x1000>; | ||
59 | interrupt-parent = <&gic>; | ||
51 | }; | 60 | }; |
52 | 61 | ||
53 | l2-cache-controller@48242000 { | 62 | l2-cache-controller@48242000 { |
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index f84d9715a4a9..26956cb50835 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts | |||
@@ -352,7 +352,6 @@ | |||
352 | reg = <0x24>; | 352 | reg = <0x24>; |
353 | compatible = "ti,tps65218"; | 353 | compatible = "ti,tps65218"; |
354 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ | 354 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ |
355 | interrupt-parent = <&gic>; | ||
356 | interrupt-controller; | 355 | interrupt-controller; |
357 | #interrupt-cells = <2>; | 356 | #interrupt-cells = <2>; |
358 | 357 | ||
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 832d24318f62..8ae29c955c11 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts | |||
@@ -392,7 +392,6 @@ | |||
392 | tps@24 { | 392 | tps@24 { |
393 | compatible = "ti,tps65218"; | 393 | compatible = "ti,tps65218"; |
394 | reg = <0x24>; | 394 | reg = <0x24>; |
395 | interrupt-parent = <&gic>; | ||
396 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; | 395 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; |
397 | interrupt-controller; | 396 | interrupt-controller; |
398 | #interrupt-cells = <2>; | 397 | #interrupt-cells = <2>; |
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 257c099c347e..1d7109196872 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts | |||
@@ -369,7 +369,6 @@ | |||
369 | reg = <0x24>; | 369 | reg = <0x24>; |
370 | compatible = "ti,tps65218"; | 370 | compatible = "ti,tps65218"; |
371 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ | 371 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ |
372 | interrupt-parent = <&gic>; | ||
373 | interrupt-controller; | 372 | interrupt-controller; |
374 | #interrupt-cells = <2>; | 373 | #interrupt-cells = <2>; |
375 | 374 | ||
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 6463f9ef2b54..bd48dba16748 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts | |||
@@ -454,7 +454,6 @@ | |||
454 | mcp_rtc: rtc@6f { | 454 | mcp_rtc: rtc@6f { |
455 | compatible = "microchip,mcp7941x"; | 455 | compatible = "microchip,mcp7941x"; |
456 | reg = <0x6f>; | 456 | reg = <0x6f>; |
457 | interrupt-parent = <&gic>; | ||
458 | interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>; /* IRQ_SYS_1N */ | 457 | interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>; /* IRQ_SYS_1N */ |
459 | 458 | ||
460 | pinctrl-names = "default"; | 459 | pinctrl-names = "default"; |
@@ -477,7 +476,7 @@ | |||
477 | 476 | ||
478 | &uart3 { | 477 | &uart3 { |
479 | status = "okay"; | 478 | status = "okay"; |
480 | interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, | 479 | interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, |
481 | <&dra7_pmx_core 0x248>; | 480 | <&dra7_pmx_core 0x248>; |
482 | 481 | ||
483 | pinctrl-names = "default"; | 482 | pinctrl-names = "default"; |
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 7563d7ce01bb..b1bd06c6c2a8 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts | |||
@@ -444,7 +444,7 @@ | |||
444 | status = "okay"; | 444 | status = "okay"; |
445 | pinctrl-names = "default"; | 445 | pinctrl-names = "default"; |
446 | pinctrl-0 = <&uart1_pins>; | 446 | pinctrl-0 = <&uart1_pins>; |
447 | interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, | 447 | interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, |
448 | <&dra7_pmx_core 0x3e0>; | 448 | <&dra7_pmx_core 0x3e0>; |
449 | }; | 449 | }; |
450 | 450 | ||
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index c4659a979c41..a0afce7ad482 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi | |||
@@ -13,14 +13,13 @@ | |||
13 | #include "skeleton.dtsi" | 13 | #include "skeleton.dtsi" |
14 | 14 | ||
15 | #define MAX_SOURCES 400 | 15 | #define MAX_SOURCES 400 |
16 | #define DIRECT_IRQ(irq) (MAX_SOURCES + irq) | ||
17 | 16 | ||
18 | / { | 17 | / { |
19 | #address-cells = <1>; | 18 | #address-cells = <1>; |
20 | #size-cells = <1>; | 19 | #size-cells = <1>; |
21 | 20 | ||
22 | compatible = "ti,dra7xx"; | 21 | compatible = "ti,dra7xx"; |
23 | interrupt-parent = <&gic>; | 22 | interrupt-parent = <&crossbar_mpu>; |
24 | 23 | ||
25 | aliases { | 24 | aliases { |
26 | i2c0 = &i2c1; | 25 | i2c0 = &i2c1; |
@@ -50,18 +49,27 @@ | |||
50 | <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, | 49 | <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, |
51 | <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, | 50 | <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, |
52 | <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; | 51 | <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; |
52 | interrupt-parent = <&gic>; | ||
53 | }; | 53 | }; |
54 | 54 | ||
55 | gic: interrupt-controller@48211000 { | 55 | gic: interrupt-controller@48211000 { |
56 | compatible = "arm,cortex-a15-gic"; | 56 | compatible = "arm,cortex-a15-gic"; |
57 | interrupt-controller; | 57 | interrupt-controller; |
58 | #interrupt-cells = <3>; | 58 | #interrupt-cells = <3>; |
59 | arm,routable-irqs = <192>; | ||
60 | reg = <0x48211000 0x1000>, | 59 | reg = <0x48211000 0x1000>, |
61 | <0x48212000 0x1000>, | 60 | <0x48212000 0x1000>, |
62 | <0x48214000 0x2000>, | 61 | <0x48214000 0x2000>, |
63 | <0x48216000 0x2000>; | 62 | <0x48216000 0x2000>; |
64 | interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; | 63 | interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; |
64 | interrupt-parent = <&gic>; | ||
65 | }; | ||
66 | |||
67 | wakeupgen: interrupt-controller@48281000 { | ||
68 | compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu"; | ||
69 | interrupt-controller; | ||
70 | #interrupt-cells = <3>; | ||
71 | reg = <0x48281000 0x1000>; | ||
72 | interrupt-parent = <&gic>; | ||
65 | }; | 73 | }; |
66 | 74 | ||
67 | /* | 75 | /* |
@@ -91,8 +99,8 @@ | |||
91 | ti,hwmods = "l3_main_1", "l3_main_2"; | 99 | ti,hwmods = "l3_main_1", "l3_main_2"; |
92 | reg = <0x44000000 0x1000000>, | 100 | reg = <0x44000000 0x1000000>, |
93 | <0x45000000 0x1000>; | 101 | <0x45000000 0x1000>; |
94 | interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, | 102 | interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, |
95 | <GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH>; | 103 | <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; |
96 | 104 | ||
97 | prm: prm@4ae06000 { | 105 | prm: prm@4ae06000 { |
98 | compatible = "ti,dra7-prm"; | 106 | compatible = "ti,dra7-prm"; |
@@ -344,7 +352,7 @@ | |||
344 | uart1: serial@4806a000 { | 352 | uart1: serial@4806a000 { |
345 | compatible = "ti,omap4-uart"; | 353 | compatible = "ti,omap4-uart"; |
346 | reg = <0x4806a000 0x100>; | 354 | reg = <0x4806a000 0x100>; |
347 | interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; | 355 | interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; |
348 | ti,hwmods = "uart1"; | 356 | ti,hwmods = "uart1"; |
349 | clock-frequency = <48000000>; | 357 | clock-frequency = <48000000>; |
350 | status = "disabled"; | 358 | status = "disabled"; |
@@ -355,7 +363,7 @@ | |||
355 | uart2: serial@4806c000 { | 363 | uart2: serial@4806c000 { |
356 | compatible = "ti,omap4-uart"; | 364 | compatible = "ti,omap4-uart"; |
357 | reg = <0x4806c000 0x100>; | 365 | reg = <0x4806c000 0x100>; |
358 | interrupts-extended = <&gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; | 366 | interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; |
359 | ti,hwmods = "uart2"; | 367 | ti,hwmods = "uart2"; |
360 | clock-frequency = <48000000>; | 368 | clock-frequency = <48000000>; |
361 | status = "disabled"; | 369 | status = "disabled"; |
@@ -366,7 +374,7 @@ | |||
366 | uart3: serial@48020000 { | 374 | uart3: serial@48020000 { |
367 | compatible = "ti,omap4-uart"; | 375 | compatible = "ti,omap4-uart"; |
368 | reg = <0x48020000 0x100>; | 376 | reg = <0x48020000 0x100>; |
369 | interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; | 377 | interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; |
370 | ti,hwmods = "uart3"; | 378 | ti,hwmods = "uart3"; |
371 | clock-frequency = <48000000>; | 379 | clock-frequency = <48000000>; |
372 | status = "disabled"; | 380 | status = "disabled"; |
@@ -377,7 +385,7 @@ | |||
377 | uart4: serial@4806e000 { | 385 | uart4: serial@4806e000 { |
378 | compatible = "ti,omap4-uart"; | 386 | compatible = "ti,omap4-uart"; |
379 | reg = <0x4806e000 0x100>; | 387 | reg = <0x4806e000 0x100>; |
380 | interrupts-extended = <&gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; | 388 | interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; |
381 | ti,hwmods = "uart4"; | 389 | ti,hwmods = "uart4"; |
382 | clock-frequency = <48000000>; | 390 | clock-frequency = <48000000>; |
383 | status = "disabled"; | 391 | status = "disabled"; |
@@ -388,7 +396,7 @@ | |||
388 | uart5: serial@48066000 { | 396 | uart5: serial@48066000 { |
389 | compatible = "ti,omap4-uart"; | 397 | compatible = "ti,omap4-uart"; |
390 | reg = <0x48066000 0x100>; | 398 | reg = <0x48066000 0x100>; |
391 | interrupts-extended = <&gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; | 399 | interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; |
392 | ti,hwmods = "uart5"; | 400 | ti,hwmods = "uart5"; |
393 | clock-frequency = <48000000>; | 401 | clock-frequency = <48000000>; |
394 | status = "disabled"; | 402 | status = "disabled"; |
@@ -399,7 +407,7 @@ | |||
399 | uart6: serial@48068000 { | 407 | uart6: serial@48068000 { |
400 | compatible = "ti,omap4-uart"; | 408 | compatible = "ti,omap4-uart"; |
401 | reg = <0x48068000 0x100>; | 409 | reg = <0x48068000 0x100>; |
402 | interrupts-extended = <&gic GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; | 410 | interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; |
403 | ti,hwmods = "uart6"; | 411 | ti,hwmods = "uart6"; |
404 | clock-frequency = <48000000>; | 412 | clock-frequency = <48000000>; |
405 | status = "disabled"; | 413 | status = "disabled"; |
@@ -410,7 +418,7 @@ | |||
410 | uart7: serial@48420000 { | 418 | uart7: serial@48420000 { |
411 | compatible = "ti,omap4-uart"; | 419 | compatible = "ti,omap4-uart"; |
412 | reg = <0x48420000 0x100>; | 420 | reg = <0x48420000 0x100>; |
413 | interrupts-extended = <&gic GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>; | 421 | interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>; |
414 | ti,hwmods = "uart7"; | 422 | ti,hwmods = "uart7"; |
415 | clock-frequency = <48000000>; | 423 | clock-frequency = <48000000>; |
416 | status = "disabled"; | 424 | status = "disabled"; |
@@ -419,7 +427,7 @@ | |||
419 | uart8: serial@48422000 { | 427 | uart8: serial@48422000 { |
420 | compatible = "ti,omap4-uart"; | 428 | compatible = "ti,omap4-uart"; |
421 | reg = <0x48422000 0x100>; | 429 | reg = <0x48422000 0x100>; |
422 | interrupts-extended = <&gic GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>; | 430 | interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>; |
423 | ti,hwmods = "uart8"; | 431 | ti,hwmods = "uart8"; |
424 | clock-frequency = <48000000>; | 432 | clock-frequency = <48000000>; |
425 | status = "disabled"; | 433 | status = "disabled"; |
@@ -428,7 +436,7 @@ | |||
428 | uart9: serial@48424000 { | 436 | uart9: serial@48424000 { |
429 | compatible = "ti,omap4-uart"; | 437 | compatible = "ti,omap4-uart"; |
430 | reg = <0x48424000 0x100>; | 438 | reg = <0x48424000 0x100>; |
431 | interrupts-extended = <&gic GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; | 439 | interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; |
432 | ti,hwmods = "uart9"; | 440 | ti,hwmods = "uart9"; |
433 | clock-frequency = <48000000>; | 441 | clock-frequency = <48000000>; |
434 | status = "disabled"; | 442 | status = "disabled"; |
@@ -437,7 +445,7 @@ | |||
437 | uart10: serial@4ae2b000 { | 445 | uart10: serial@4ae2b000 { |
438 | compatible = "ti,omap4-uart"; | 446 | compatible = "ti,omap4-uart"; |
439 | reg = <0x4ae2b000 0x100>; | 447 | reg = <0x4ae2b000 0x100>; |
440 | interrupts-extended = <&gic GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; | 448 | interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; |
441 | ti,hwmods = "uart10"; | 449 | ti,hwmods = "uart10"; |
442 | clock-frequency = <48000000>; | 450 | clock-frequency = <48000000>; |
443 | status = "disabled"; | 451 | status = "disabled"; |
@@ -1335,9 +1343,12 @@ | |||
1335 | status = "disabled"; | 1343 | status = "disabled"; |
1336 | }; | 1344 | }; |
1337 | 1345 | ||
1338 | crossbar_mpu: crossbar@4a020000 { | 1346 | crossbar_mpu: crossbar@4a002a48 { |
1339 | compatible = "ti,irq-crossbar"; | 1347 | compatible = "ti,irq-crossbar"; |
1340 | reg = <0x4a002a48 0x130>; | 1348 | reg = <0x4a002a48 0x130>; |
1349 | interrupt-controller; | ||
1350 | interrupt-parent = <&wakeupgen>; | ||
1351 | #interrupt-cells = <3>; | ||
1341 | ti,max-irqs = <160>; | 1352 | ti,max-irqs = <160>; |
1342 | ti,max-crossbar-sources = <MAX_SOURCES>; | 1353 | ti,max-crossbar-sources = <MAX_SOURCES>; |
1343 | ti,reg-size = <2>; | 1354 | ti,reg-size = <2>; |
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 40ed539ce474..daf28110d487 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts | |||
@@ -158,7 +158,6 @@ | |||
158 | pinctrl-0 = <&tps65917_pins_default>; | 158 | pinctrl-0 = <&tps65917_pins_default>; |
159 | 159 | ||
160 | interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ | 160 | interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ |
161 | interrupt-parent = <&gic>; | ||
162 | interrupt-controller; | 161 | interrupt-controller; |
163 | #interrupt-cells = <2>; | 162 | #interrupt-cells = <2>; |
164 | 163 | ||
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi index e5a3d23a3df1..f7fb0d0ef25a 100644 --- a/arch/arm/boot/dts/dra72x.dtsi +++ b/arch/arm/boot/dts/dra72x.dtsi | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | pmu { | 26 | pmu { |
27 | compatible = "arm,cortex-a15-pmu"; | 27 | compatible = "arm,cortex-a15-pmu"; |
28 | interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>; | 28 | interrupt-parent = <&wakeupgen>; |
29 | interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; | ||
29 | }; | 30 | }; |
30 | }; | 31 | }; |
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi index 10173fab1a15..00eeed789b4b 100644 --- a/arch/arm/boot/dts/dra74x.dtsi +++ b/arch/arm/boot/dts/dra74x.dtsi | |||
@@ -41,8 +41,9 @@ | |||
41 | 41 | ||
42 | pmu { | 42 | pmu { |
43 | compatible = "arm,cortex-a15-pmu"; | 43 | compatible = "arm,cortex-a15-pmu"; |
44 | interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>, | 44 | interrupt-parent = <&wakeupgen>; |
45 | <GIC_SPI DIRECT_IRQ(132) IRQ_TYPE_LEVEL_HIGH>; | 45 | interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, |
46 | <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | ocp { | 49 | ocp { |
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index ac6b0ae42caf..14ab515aa83c 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi | |||
@@ -131,6 +131,9 @@ | |||
131 | pmu_system_controller: system-controller@10020000 { | 131 | pmu_system_controller: system-controller@10020000 { |
132 | compatible = "samsung,exynos3250-pmu", "syscon"; | 132 | compatible = "samsung,exynos3250-pmu", "syscon"; |
133 | reg = <0x10020000 0x4000>; | 133 | reg = <0x10020000 0x4000>; |
134 | interrupt-controller; | ||
135 | #interrupt-cells = <3>; | ||
136 | interrupt-parent = <&gic>; | ||
134 | }; | 137 | }; |
135 | 138 | ||
136 | mipi_phy: video-phy@10020710 { | 139 | mipi_phy: video-phy@10020710 { |
@@ -185,6 +188,7 @@ | |||
185 | compatible = "samsung,exynos3250-rtc"; | 188 | compatible = "samsung,exynos3250-rtc"; |
186 | reg = <0x10070000 0x100>; | 189 | reg = <0x10070000 0x100>; |
187 | interrupts = <0 73 0>, <0 74 0>; | 190 | interrupts = <0 73 0>, <0 74 0>; |
191 | interrupt-parent = <&pmu_system_controller>; | ||
188 | status = "disabled"; | 192 | status = "disabled"; |
189 | }; | 193 | }; |
190 | 194 | ||
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 77ea547768f4..e20cdc24c3bb 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi | |||
@@ -154,6 +154,9 @@ | |||
154 | pmu_system_controller: system-controller@10020000 { | 154 | pmu_system_controller: system-controller@10020000 { |
155 | compatible = "samsung,exynos4210-pmu", "syscon"; | 155 | compatible = "samsung,exynos4210-pmu", "syscon"; |
156 | reg = <0x10020000 0x4000>; | 156 | reg = <0x10020000 0x4000>; |
157 | interrupt-controller; | ||
158 | #interrupt-cells = <3>; | ||
159 | interrupt-parent = <&gic>; | ||
157 | }; | 160 | }; |
158 | 161 | ||
159 | dsi_0: dsi@11C80000 { | 162 | dsi_0: dsi@11C80000 { |
@@ -266,6 +269,7 @@ | |||
266 | rtc@10070000 { | 269 | rtc@10070000 { |
267 | compatible = "samsung,s3c6410-rtc"; | 270 | compatible = "samsung,s3c6410-rtc"; |
268 | reg = <0x10070000 0x100>; | 271 | reg = <0x10070000 0x100>; |
272 | interrupt-parent = <&pmu_system_controller>; | ||
269 | interrupts = <0 44 0>, <0 45 0>; | 273 | interrupts = <0 44 0>, <0 45 0>; |
270 | clocks = <&clock CLK_RTC>; | 274 | clocks = <&clock CLK_RTC>; |
271 | clock-names = "rtc"; | 275 | clock-names = "rtc"; |
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index adbde1adad95..77f656eb8e6b 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi | |||
@@ -205,6 +205,9 @@ | |||
205 | clock-names = "clkout16"; | 205 | clock-names = "clkout16"; |
206 | clocks = <&clock CLK_FIN_PLL>; | 206 | clocks = <&clock CLK_FIN_PLL>; |
207 | #clock-cells = <1>; | 207 | #clock-cells = <1>; |
208 | interrupt-controller; | ||
209 | #interrupt-cells = <3>; | ||
210 | interrupt-parent = <&gic>; | ||
208 | }; | 211 | }; |
209 | 212 | ||
210 | sysreg_system_controller: syscon@10050000 { | 213 | sysreg_system_controller: syscon@10050000 { |
@@ -241,6 +244,7 @@ | |||
241 | rtc: rtc@101E0000 { | 244 | rtc: rtc@101E0000 { |
242 | clocks = <&clock CLK_RTC>; | 245 | clocks = <&clock CLK_RTC>; |
243 | clock-names = "rtc"; | 246 | clock-names = "rtc"; |
247 | interrupt-parent = <&pmu_system_controller>; | ||
244 | status = "disabled"; | 248 | status = "disabled"; |
245 | }; | 249 | }; |
246 | 250 | ||
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c0e98cf3514f..b3d2d53820e3 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi | |||
@@ -327,6 +327,7 @@ | |||
327 | rtc: rtc@101E0000 { | 327 | rtc: rtc@101E0000 { |
328 | clocks = <&clock CLK_RTC>; | 328 | clocks = <&clock CLK_RTC>; |
329 | clock-names = "rtc"; | 329 | clock-names = "rtc"; |
330 | interrupt-parent = <&pmu_system_controller>; | ||
330 | status = "disabled"; | 331 | status = "disabled"; |
331 | }; | 332 | }; |
332 | 333 | ||
@@ -770,6 +771,9 @@ | |||
770 | clock-names = "clkout16"; | 771 | clock-names = "clkout16"; |
771 | clocks = <&clock CLK_FIN_PLL>; | 772 | clocks = <&clock CLK_FIN_PLL>; |
772 | #clock-cells = <1>; | 773 | #clock-cells = <1>; |
774 | interrupt-controller; | ||
775 | #interrupt-cells = <3>; | ||
776 | interrupt-parent = <&gic>; | ||
773 | }; | 777 | }; |
774 | 778 | ||
775 | sysreg_system_controller: syscon@10050000 { | 779 | sysreg_system_controller: syscon@10050000 { |
diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/omap4-duovero.dtsi index e860ccd9d09c..f2a94fa62552 100644 --- a/arch/arm/boot/dts/omap4-duovero.dtsi +++ b/arch/arm/boot/dts/omap4-duovero.dtsi | |||
@@ -173,14 +173,12 @@ | |||
173 | twl: twl@48 { | 173 | twl: twl@48 { |
174 | reg = <0x48>; | 174 | reg = <0x48>; |
175 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ | 175 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ |
176 | interrupt-parent = <&gic>; | ||
177 | }; | 176 | }; |
178 | 177 | ||
179 | twl6040: twl@4b { | 178 | twl6040: twl@4b { |
180 | compatible = "ti,twl6040"; | 179 | compatible = "ti,twl6040"; |
181 | reg = <0x4b>; | 180 | reg = <0x4b>; |
182 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ | 181 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ |
183 | interrupt-parent = <&gic>; | ||
184 | ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* gpio_160 */ | 182 | ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* gpio_160 */ |
185 | 183 | ||
186 | vio-supply = <&v1v8>; | 184 | vio-supply = <&v1v8>; |
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi index 150513506c19..7c15fb2e2fe4 100644 --- a/arch/arm/boot/dts/omap4-panda-common.dtsi +++ b/arch/arm/boot/dts/omap4-panda-common.dtsi | |||
@@ -372,7 +372,6 @@ | |||
372 | reg = <0x48>; | 372 | reg = <0x48>; |
373 | /* IRQ# = 7 */ | 373 | /* IRQ# = 7 */ |
374 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ | 374 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ |
375 | interrupt-parent = <&gic>; | ||
376 | }; | 375 | }; |
377 | 376 | ||
378 | twl6040: twl@4b { | 377 | twl6040: twl@4b { |
@@ -384,7 +383,6 @@ | |||
384 | 383 | ||
385 | /* IRQ# = 119 */ | 384 | /* IRQ# = 119 */ |
386 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ | 385 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ |
387 | interrupt-parent = <&gic>; | ||
388 | ti,audpwron-gpio = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio line 127 */ | 386 | ti,audpwron-gpio = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio line 127 */ |
389 | 387 | ||
390 | vio-supply = <&v1v8>; | 388 | vio-supply = <&v1v8>; |
@@ -479,17 +477,17 @@ | |||
479 | }; | 477 | }; |
480 | 478 | ||
481 | &uart2 { | 479 | &uart2 { |
482 | interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH | 480 | interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH |
483 | &omap4_pmx_core OMAP4_UART2_RX>; | 481 | &omap4_pmx_core OMAP4_UART2_RX>; |
484 | }; | 482 | }; |
485 | 483 | ||
486 | &uart3 { | 484 | &uart3 { |
487 | interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH | 485 | interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH |
488 | &omap4_pmx_core OMAP4_UART3_RX>; | 486 | &omap4_pmx_core OMAP4_UART3_RX>; |
489 | }; | 487 | }; |
490 | 488 | ||
491 | &uart4 { | 489 | &uart4 { |
492 | interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH | 490 | interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH |
493 | &omap4_pmx_core OMAP4_UART4_RX>; | 491 | &omap4_pmx_core OMAP4_UART4_RX>; |
494 | }; | 492 | }; |
495 | 493 | ||
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 3e1da43068f6..8aca8dae968a 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts | |||
@@ -363,7 +363,6 @@ | |||
363 | reg = <0x48>; | 363 | reg = <0x48>; |
364 | /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ | 364 | /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ |
365 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ | 365 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ |
366 | interrupt-parent = <&gic>; | ||
367 | }; | 366 | }; |
368 | 367 | ||
369 | twl6040: twl@4b { | 368 | twl6040: twl@4b { |
@@ -375,7 +374,6 @@ | |||
375 | 374 | ||
376 | /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ | 375 | /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ |
377 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ | 376 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ |
378 | interrupt-parent = <&gic>; | ||
379 | ti,audpwron-gpio = <&gpio4 31 0>; /* gpio line 127 */ | 377 | ti,audpwron-gpio = <&gpio4 31 0>; /* gpio line 127 */ |
380 | 378 | ||
381 | vio-supply = <&v1v8>; | 379 | vio-supply = <&v1v8>; |
@@ -570,21 +568,21 @@ | |||
570 | }; | 568 | }; |
571 | 569 | ||
572 | &uart2 { | 570 | &uart2 { |
573 | interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH | 571 | interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH |
574 | &omap4_pmx_core OMAP4_UART2_RX>; | 572 | &omap4_pmx_core OMAP4_UART2_RX>; |
575 | pinctrl-names = "default"; | 573 | pinctrl-names = "default"; |
576 | pinctrl-0 = <&uart2_pins>; | 574 | pinctrl-0 = <&uart2_pins>; |
577 | }; | 575 | }; |
578 | 576 | ||
579 | &uart3 { | 577 | &uart3 { |
580 | interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH | 578 | interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH |
581 | &omap4_pmx_core OMAP4_UART3_RX>; | 579 | &omap4_pmx_core OMAP4_UART3_RX>; |
582 | pinctrl-names = "default"; | 580 | pinctrl-names = "default"; |
583 | pinctrl-0 = <&uart3_pins>; | 581 | pinctrl-0 = <&uart3_pins>; |
584 | }; | 582 | }; |
585 | 583 | ||
586 | &uart4 { | 584 | &uart4 { |
587 | interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH | 585 | interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH |
588 | &omap4_pmx_core OMAP4_UART4_RX>; | 586 | &omap4_pmx_core OMAP4_UART4_RX>; |
589 | pinctrl-names = "default"; | 587 | pinctrl-names = "default"; |
590 | pinctrl-0 = <&uart4_pins>; | 588 | pinctrl-0 = <&uart4_pins>; |
diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi index 062701e1a898..a4f1ba2e1903 100644 --- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi +++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi | |||
@@ -185,7 +185,6 @@ | |||
185 | reg = <0x48>; | 185 | reg = <0x48>; |
186 | /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ | 186 | /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ |
187 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ | 187 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */ |
188 | interrupt-parent = <&gic>; | ||
189 | }; | 188 | }; |
190 | 189 | ||
191 | twl6040: twl@4b { | 190 | twl6040: twl@4b { |
@@ -197,7 +196,6 @@ | |||
197 | 196 | ||
198 | /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ | 197 | /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ |
199 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ | 198 | interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */ |
200 | interrupt-parent = <&gic>; | ||
201 | ti,audpwron-gpio = <&gpio6 22 0>; /* gpio 182 */ | 199 | ti,audpwron-gpio = <&gpio6 22 0>; /* gpio 182 */ |
202 | 200 | ||
203 | vio-supply = <&v1v8>; | 201 | vio-supply = <&v1v8>; |
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 87401d9f4d8b..f2091d1c9c36 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | / { | 15 | / { |
16 | compatible = "ti,omap4430", "ti,omap4"; | 16 | compatible = "ti,omap4430", "ti,omap4"; |
17 | interrupt-parent = <&gic>; | 17 | interrupt-parent = <&wakeupgen>; |
18 | 18 | ||
19 | aliases { | 19 | aliases { |
20 | i2c0 = &i2c1; | 20 | i2c0 = &i2c1; |
@@ -56,6 +56,7 @@ | |||
56 | #interrupt-cells = <3>; | 56 | #interrupt-cells = <3>; |
57 | reg = <0x48241000 0x1000>, | 57 | reg = <0x48241000 0x1000>, |
58 | <0x48240100 0x0100>; | 58 | <0x48240100 0x0100>; |
59 | interrupt-parent = <&gic>; | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | L2: l2-cache-controller@48242000 { | 62 | L2: l2-cache-controller@48242000 { |
@@ -70,6 +71,15 @@ | |||
70 | clocks = <&mpu_periphclk>; | 71 | clocks = <&mpu_periphclk>; |
71 | reg = <0x48240600 0x20>; | 72 | reg = <0x48240600 0x20>; |
72 | interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>; | 73 | interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>; |
74 | interrupt-parent = <&gic>; | ||
75 | }; | ||
76 | |||
77 | wakeupgen: interrupt-controller@48281000 { | ||
78 | compatible = "ti,omap4-wugen-mpu"; | ||
79 | interrupt-controller; | ||
80 | #interrupt-cells = <3>; | ||
81 | reg = <0x48281000 0x1000>; | ||
82 | interrupt-parent = <&gic>; | ||
73 | }; | 83 | }; |
74 | 84 | ||
75 | /* | 85 | /* |
@@ -319,7 +329,7 @@ | |||
319 | uart2: serial@4806c000 { | 329 | uart2: serial@4806c000 { |
320 | compatible = "ti,omap4-uart"; | 330 | compatible = "ti,omap4-uart"; |
321 | reg = <0x4806c000 0x100>; | 331 | reg = <0x4806c000 0x100>; |
322 | interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; | 332 | interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; |
323 | ti,hwmods = "uart2"; | 333 | ti,hwmods = "uart2"; |
324 | clock-frequency = <48000000>; | 334 | clock-frequency = <48000000>; |
325 | }; | 335 | }; |
@@ -327,7 +337,7 @@ | |||
327 | uart3: serial@48020000 { | 337 | uart3: serial@48020000 { |
328 | compatible = "ti,omap4-uart"; | 338 | compatible = "ti,omap4-uart"; |
329 | reg = <0x48020000 0x100>; | 339 | reg = <0x48020000 0x100>; |
330 | interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; | 340 | interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; |
331 | ti,hwmods = "uart3"; | 341 | ti,hwmods = "uart3"; |
332 | clock-frequency = <48000000>; | 342 | clock-frequency = <48000000>; |
333 | }; | 343 | }; |
@@ -335,7 +345,7 @@ | |||
335 | uart4: serial@4806e000 { | 345 | uart4: serial@4806e000 { |
336 | compatible = "ti,omap4-uart"; | 346 | compatible = "ti,omap4-uart"; |
337 | reg = <0x4806e000 0x100>; | 347 | reg = <0x4806e000 0x100>; |
338 | interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; | 348 | interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; |
339 | ti,hwmods = "uart4"; | 349 | ti,hwmods = "uart4"; |
340 | clock-frequency = <48000000>; | 350 | clock-frequency = <48000000>; |
341 | }; | 351 | }; |
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts index b54b271e153b..61ad2ea34720 100644 --- a/arch/arm/boot/dts/omap5-cm-t54.dts +++ b/arch/arm/boot/dts/omap5-cm-t54.dts | |||
@@ -412,7 +412,6 @@ | |||
412 | palmas: palmas@48 { | 412 | palmas: palmas@48 { |
413 | compatible = "ti,palmas"; | 413 | compatible = "ti,palmas"; |
414 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ | 414 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ |
415 | interrupt-parent = <&gic>; | ||
416 | reg = <0x48>; | 415 | reg = <0x48>; |
417 | interrupt-controller; | 416 | interrupt-controller; |
418 | #interrupt-cells = <2>; | 417 | #interrupt-cells = <2>; |
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts index 159720d6c956..74777a6e200a 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/omap5-uevm.dts | |||
@@ -311,7 +311,6 @@ | |||
311 | palmas: palmas@48 { | 311 | palmas: palmas@48 { |
312 | compatible = "ti,palmas"; | 312 | compatible = "ti,palmas"; |
313 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ | 313 | interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */ |
314 | interrupt-parent = <&gic>; | ||
315 | reg = <0x48>; | 314 | reg = <0x48>; |
316 | interrupt-controller; | 315 | interrupt-controller; |
317 | #interrupt-cells = <2>; | 316 | #interrupt-cells = <2>; |
@@ -521,7 +520,6 @@ | |||
521 | pinctrl-0 = <&twl6040_pins>; | 520 | pinctrl-0 = <&twl6040_pins>; |
522 | 521 | ||
523 | interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */ | 522 | interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */ |
524 | interrupt-parent = <&gic>; | ||
525 | ti,audpwron-gpio = <&gpio5 13 0>; /* gpio line 141 */ | 523 | ti,audpwron-gpio = <&gpio5 13 0>; /* gpio line 141 */ |
526 | 524 | ||
527 | vio-supply = <&smps7_reg>; | 525 | vio-supply = <&smps7_reg>; |
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 4a485b63a141..77b5f70d0ebc 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi | |||
@@ -18,7 +18,7 @@ | |||
18 | #size-cells = <1>; | 18 | #size-cells = <1>; |
19 | 19 | ||
20 | compatible = "ti,omap5"; | 20 | compatible = "ti,omap5"; |
21 | interrupt-parent = <&gic>; | 21 | interrupt-parent = <&wakeupgen>; |
22 | 22 | ||
23 | aliases { | 23 | aliases { |
24 | i2c0 = &i2c1; | 24 | i2c0 = &i2c1; |
@@ -79,6 +79,7 @@ | |||
79 | <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, | 79 | <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, |
80 | <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, | 80 | <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, |
81 | <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>; | 81 | <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>; |
82 | interrupt-parent = <&gic>; | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | pmu { | 85 | pmu { |
@@ -95,6 +96,15 @@ | |||
95 | <0x48212000 0x1000>, | 96 | <0x48212000 0x1000>, |
96 | <0x48214000 0x2000>, | 97 | <0x48214000 0x2000>, |
97 | <0x48216000 0x2000>; | 98 | <0x48216000 0x2000>; |
99 | interrupt-parent = <&gic>; | ||
100 | }; | ||
101 | |||
102 | wakeupgen: interrupt-controller@48281000 { | ||
103 | compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu"; | ||
104 | interrupt-controller; | ||
105 | #interrupt-cells = <3>; | ||
106 | reg = <0x48281000 0x1000>; | ||
107 | interrupt-parent = <&gic>; | ||
98 | }; | 108 | }; |
99 | 109 | ||
100 | /* | 110 | /* |
@@ -458,7 +468,7 @@ | |||
458 | uart1: serial@4806a000 { | 468 | uart1: serial@4806a000 { |
459 | compatible = "ti,omap4-uart"; | 469 | compatible = "ti,omap4-uart"; |
460 | reg = <0x4806a000 0x100>; | 470 | reg = <0x4806a000 0x100>; |
461 | interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; | 471 | interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; |
462 | ti,hwmods = "uart1"; | 472 | ti,hwmods = "uart1"; |
463 | clock-frequency = <48000000>; | 473 | clock-frequency = <48000000>; |
464 | }; | 474 | }; |
@@ -466,7 +476,7 @@ | |||
466 | uart2: serial@4806c000 { | 476 | uart2: serial@4806c000 { |
467 | compatible = "ti,omap4-uart"; | 477 | compatible = "ti,omap4-uart"; |
468 | reg = <0x4806c000 0x100>; | 478 | reg = <0x4806c000 0x100>; |
469 | interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; | 479 | interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; |
470 | ti,hwmods = "uart2"; | 480 | ti,hwmods = "uart2"; |
471 | clock-frequency = <48000000>; | 481 | clock-frequency = <48000000>; |
472 | }; | 482 | }; |
@@ -474,7 +484,7 @@ | |||
474 | uart3: serial@48020000 { | 484 | uart3: serial@48020000 { |
475 | compatible = "ti,omap4-uart"; | 485 | compatible = "ti,omap4-uart"; |
476 | reg = <0x48020000 0x100>; | 486 | reg = <0x48020000 0x100>; |
477 | interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; | 487 | interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; |
478 | ti,hwmods = "uart3"; | 488 | ti,hwmods = "uart3"; |
479 | clock-frequency = <48000000>; | 489 | clock-frequency = <48000000>; |
480 | }; | 490 | }; |
@@ -482,7 +492,7 @@ | |||
482 | uart4: serial@4806e000 { | 492 | uart4: serial@4806e000 { |
483 | compatible = "ti,omap4-uart"; | 493 | compatible = "ti,omap4-uart"; |
484 | reg = <0x4806e000 0x100>; | 494 | reg = <0x4806e000 0x100>; |
485 | interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; | 495 | interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; |
486 | ti,hwmods = "uart4"; | 496 | ti,hwmods = "uart4"; |
487 | clock-frequency = <48000000>; | 497 | clock-frequency = <48000000>; |
488 | }; | 498 | }; |
@@ -490,7 +500,7 @@ | |||
490 | uart5: serial@48066000 { | 500 | uart5: serial@48066000 { |
491 | compatible = "ti,omap4-uart"; | 501 | compatible = "ti,omap4-uart"; |
492 | reg = <0x48066000 0x100>; | 502 | reg = <0x48066000 0x100>; |
493 | interrupts-extended = <&gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; | 503 | interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; |
494 | ti,hwmods = "uart5"; | 504 | ti,hwmods = "uart5"; |
495 | clock-frequency = <48000000>; | 505 | clock-frequency = <48000000>; |
496 | }; | 506 | }; |
@@ -498,7 +508,7 @@ | |||
498 | uart6: serial@48068000 { | 508 | uart6: serial@48068000 { |
499 | compatible = "ti,omap4-uart"; | 509 | compatible = "ti,omap4-uart"; |
500 | reg = <0x48068000 0x100>; | 510 | reg = <0x48068000 0x100>; |
501 | interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; | 511 | interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; |
502 | ti,hwmods = "uart6"; | 512 | ti,hwmods = "uart6"; |
503 | clock-frequency = <48000000>; | 513 | clock-frequency = <48000000>; |
504 | }; | 514 | }; |
@@ -883,14 +893,12 @@ | |||
883 | usbhsohci: ohci@4a064800 { | 893 | usbhsohci: ohci@4a064800 { |
884 | compatible = "ti,ohci-omap3"; | 894 | compatible = "ti,ohci-omap3"; |
885 | reg = <0x4a064800 0x400>; | 895 | reg = <0x4a064800 0x400>; |
886 | interrupt-parent = <&gic>; | ||
887 | interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; | 896 | interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; |
888 | }; | 897 | }; |
889 | 898 | ||
890 | usbhsehci: ehci@4a064c00 { | 899 | usbhsehci: ehci@4a064c00 { |
891 | compatible = "ti,ehci-omap"; | 900 | compatible = "ti,ehci-omap"; |
892 | reg = <0x4a064c00 0x400>; | 901 | reg = <0x4a064c00 0x400>; |
893 | interrupt-parent = <&gic>; | ||
894 | interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; | 902 | interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; |
895 | }; | 903 | }; |
896 | }; | 904 | }; |
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 4296b5398bf5..f58a3d9d5f13 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | / { | 9 | / { |
10 | compatible = "nvidia,tegra114"; | 10 | compatible = "nvidia,tegra114"; |
11 | interrupt-parent = <&gic>; | 11 | interrupt-parent = <&lic>; |
12 | 12 | ||
13 | host1x@50000000 { | 13 | host1x@50000000 { |
14 | compatible = "nvidia,tegra114-host1x", "simple-bus"; | 14 | compatible = "nvidia,tegra114-host1x", "simple-bus"; |
@@ -134,6 +134,19 @@ | |||
134 | <0x50046000 0x2000>; | 134 | <0x50046000 0x2000>; |
135 | interrupts = <GIC_PPI 9 | 135 | interrupts = <GIC_PPI 9 |
136 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; | 136 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; |
137 | interrupt-parent = <&gic>; | ||
138 | }; | ||
139 | |||
140 | lic: interrupt-controller@60004000 { | ||
141 | compatible = "nvidia,tegra114-ictlr", "nvidia,tegra30-ictlr"; | ||
142 | reg = <0x60004000 0x100>, | ||
143 | <0x60004100 0x50>, | ||
144 | <0x60004200 0x50>, | ||
145 | <0x60004300 0x50>, | ||
146 | <0x60004400 0x50>; | ||
147 | interrupt-controller; | ||
148 | #interrupt-cells = <3>; | ||
149 | interrupt-parent = <&gic>; | ||
137 | }; | 150 | }; |
138 | 151 | ||
139 | timer@60005000 { | 152 | timer@60005000 { |
@@ -766,5 +779,6 @@ | |||
766 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, | 779 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, |
767 | <GIC_PPI 10 | 780 | <GIC_PPI 10 |
768 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; | 781 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; |
782 | interrupt-parent = <&gic>; | ||
769 | }; | 783 | }; |
770 | }; | 784 | }; |
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index 4be06c6ea0c8..db85695aa7aa 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | / { | 11 | / { |
12 | compatible = "nvidia,tegra124"; | 12 | compatible = "nvidia,tegra124"; |
13 | interrupt-parent = <&gic>; | 13 | interrupt-parent = <&lic>; |
14 | #address-cells = <2>; | 14 | #address-cells = <2>; |
15 | #size-cells = <2>; | 15 | #size-cells = <2>; |
16 | 16 | ||
@@ -173,6 +173,7 @@ | |||
173 | <0x0 0x50046000 0x0 0x2000>; | 173 | <0x0 0x50046000 0x0 0x2000>; |
174 | interrupts = <GIC_PPI 9 | 174 | interrupts = <GIC_PPI 9 |
175 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; | 175 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; |
176 | interrupt-parent = <&gic>; | ||
176 | }; | 177 | }; |
177 | 178 | ||
178 | gpu@0,57000000 { | 179 | gpu@0,57000000 { |
@@ -190,6 +191,18 @@ | |||
190 | status = "disabled"; | 191 | status = "disabled"; |
191 | }; | 192 | }; |
192 | 193 | ||
194 | lic: interrupt-controller@60004000 { | ||
195 | compatible = "nvidia,tegra124-ictlr", "nvidia,tegra30-ictlr"; | ||
196 | reg = <0x0 0x60004000 0x0 0x100>, | ||
197 | <0x0 0x60004100 0x0 0x100>, | ||
198 | <0x0 0x60004200 0x0 0x100>, | ||
199 | <0x0 0x60004300 0x0 0x100>, | ||
200 | <0x0 0x60004400 0x0 0x100>; | ||
201 | interrupt-controller; | ||
202 | #interrupt-cells = <3>; | ||
203 | interrupt-parent = <&gic>; | ||
204 | }; | ||
205 | |||
193 | timer@0,60005000 { | 206 | timer@0,60005000 { |
194 | compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer"; | 207 | compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer"; |
195 | reg = <0x0 0x60005000 0x0 0x400>; | 208 | reg = <0x0 0x60005000 0x0 0x400>; |
@@ -955,5 +968,6 @@ | |||
955 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, | 968 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, |
956 | <GIC_PPI 10 | 969 | <GIC_PPI 10 |
957 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; | 970 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; |
971 | interrupt-parent = <&gic>; | ||
958 | }; | 972 | }; |
959 | }; | 973 | }; |
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index e5527f742696..adf6b048d0bb 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | / { | 8 | / { |
9 | compatible = "nvidia,tegra20"; | 9 | compatible = "nvidia,tegra20"; |
10 | interrupt-parent = <&intc>; | 10 | interrupt-parent = <&lic>; |
11 | 11 | ||
12 | host1x@50000000 { | 12 | host1x@50000000 { |
13 | compatible = "nvidia,tegra20-host1x", "simple-bus"; | 13 | compatible = "nvidia,tegra20-host1x", "simple-bus"; |
@@ -142,6 +142,7 @@ | |||
142 | 142 | ||
143 | timer@50040600 { | 143 | timer@50040600 { |
144 | compatible = "arm,cortex-a9-twd-timer"; | 144 | compatible = "arm,cortex-a9-twd-timer"; |
145 | interrupt-parent = <&intc>; | ||
145 | reg = <0x50040600 0x20>; | 146 | reg = <0x50040600 0x20>; |
146 | interrupts = <GIC_PPI 13 | 147 | interrupts = <GIC_PPI 13 |
147 | (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; | 148 | (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; |
@@ -154,6 +155,7 @@ | |||
154 | 0x50040100 0x0100>; | 155 | 0x50040100 0x0100>; |
155 | interrupt-controller; | 156 | interrupt-controller; |
156 | #interrupt-cells = <3>; | 157 | #interrupt-cells = <3>; |
158 | interrupt-parent = <&intc>; | ||
157 | }; | 159 | }; |
158 | 160 | ||
159 | cache-controller@50043000 { | 161 | cache-controller@50043000 { |
@@ -165,6 +167,17 @@ | |||
165 | cache-level = <2>; | 167 | cache-level = <2>; |
166 | }; | 168 | }; |
167 | 169 | ||
170 | lic: interrupt-controller@60004000 { | ||
171 | compatible = "nvidia,tegra20-ictlr"; | ||
172 | reg = <0x60004000 0x100>, | ||
173 | <0x60004100 0x50>, | ||
174 | <0x60004200 0x50>, | ||
175 | <0x60004300 0x50>; | ||
176 | interrupt-controller; | ||
177 | #interrupt-cells = <3>; | ||
178 | interrupt-parent = <&intc>; | ||
179 | }; | ||
180 | |||
168 | timer@60005000 { | 181 | timer@60005000 { |
169 | compatible = "nvidia,tegra20-timer"; | 182 | compatible = "nvidia,tegra20-timer"; |
170 | reg = <0x60005000 0x60>; | 183 | reg = <0x60005000 0x60>; |
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index db4810df142c..60e205a0f63d 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | / { | 9 | / { |
10 | compatible = "nvidia,tegra30"; | 10 | compatible = "nvidia,tegra30"; |
11 | interrupt-parent = <&intc>; | 11 | interrupt-parent = <&lic>; |
12 | 12 | ||
13 | pcie-controller@00003000 { | 13 | pcie-controller@00003000 { |
14 | compatible = "nvidia,tegra30-pcie"; | 14 | compatible = "nvidia,tegra30-pcie"; |
@@ -228,6 +228,7 @@ | |||
228 | timer@50040600 { | 228 | timer@50040600 { |
229 | compatible = "arm,cortex-a9-twd-timer"; | 229 | compatible = "arm,cortex-a9-twd-timer"; |
230 | reg = <0x50040600 0x20>; | 230 | reg = <0x50040600 0x20>; |
231 | interrupt-parent = <&intc>; | ||
231 | interrupts = <GIC_PPI 13 | 232 | interrupts = <GIC_PPI 13 |
232 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; | 233 | (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; |
233 | clocks = <&tegra_car TEGRA30_CLK_TWD>; | 234 | clocks = <&tegra_car TEGRA30_CLK_TWD>; |
@@ -239,6 +240,7 @@ | |||
239 | 0x50040100 0x0100>; | 240 | 0x50040100 0x0100>; |
240 | interrupt-controller; | 241 | interrupt-controller; |
241 | #interrupt-cells = <3>; | 242 | #interrupt-cells = <3>; |
243 | interrupt-parent = <&intc>; | ||
242 | }; | 244 | }; |
243 | 245 | ||
244 | cache-controller@50043000 { | 246 | cache-controller@50043000 { |
@@ -250,6 +252,18 @@ | |||
250 | cache-level = <2>; | 252 | cache-level = <2>; |
251 | }; | 253 | }; |
252 | 254 | ||
255 | lic: interrupt-controller@60004000 { | ||
256 | compatible = "nvidia,tegra30-ictlr"; | ||
257 | reg = <0x60004000 0x100>, | ||
258 | <0x60004100 0x50>, | ||
259 | <0x60004200 0x50>, | ||
260 | <0x60004300 0x50>, | ||
261 | <0x60004400 0x50>; | ||
262 | interrupt-controller; | ||
263 | #interrupt-cells = <3>; | ||
264 | interrupt-parent = <&intc>; | ||
265 | }; | ||
266 | |||
253 | timer@60005000 { | 267 | timer@60005000 { |
254 | compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer"; | 268 | compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer"; |
255 | reg = <0x60005000 0x400>; | 269 | reg = <0x60005000 0x400>; |
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 9e9dfdfad9d7..f44c2e05c82e 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
@@ -166,16 +166,14 @@ static void __init exynos_init_io(void) | |||
166 | exynos_map_io(); | 166 | exynos_map_io(); |
167 | } | 167 | } |
168 | 168 | ||
169 | /* | ||
170 | * Apparently, these SoCs are not able to wake-up from suspend using | ||
171 | * the PMU. Too bad. Should they suddenly become capable of such a | ||
172 | * feat, the matches below should be moved to suspend.c. | ||
173 | */ | ||
169 | static const struct of_device_id exynos_dt_pmu_match[] = { | 174 | static const struct of_device_id exynos_dt_pmu_match[] = { |
170 | { .compatible = "samsung,exynos3250-pmu" }, | ||
171 | { .compatible = "samsung,exynos4210-pmu" }, | ||
172 | { .compatible = "samsung,exynos4212-pmu" }, | ||
173 | { .compatible = "samsung,exynos4412-pmu" }, | ||
174 | { .compatible = "samsung,exynos4415-pmu" }, | ||
175 | { .compatible = "samsung,exynos5250-pmu" }, | ||
176 | { .compatible = "samsung,exynos5260-pmu" }, | 175 | { .compatible = "samsung,exynos5260-pmu" }, |
177 | { .compatible = "samsung,exynos5410-pmu" }, | 176 | { .compatible = "samsung,exynos5410-pmu" }, |
178 | { .compatible = "samsung,exynos5420-pmu" }, | ||
179 | { /*sentinel*/ }, | 177 | { /*sentinel*/ }, |
180 | }; | 178 | }; |
181 | 179 | ||
@@ -186,9 +184,6 @@ static void exynos_map_pmu(void) | |||
186 | np = of_find_matching_node(NULL, exynos_dt_pmu_match); | 184 | np = of_find_matching_node(NULL, exynos_dt_pmu_match); |
187 | if (np) | 185 | if (np) |
188 | pmu_base_addr = of_iomap(np, 0); | 186 | pmu_base_addr = of_iomap(np, 0); |
189 | |||
190 | if (!pmu_base_addr) | ||
191 | panic("failed to find exynos pmu register\n"); | ||
192 | } | 187 | } |
193 | 188 | ||
194 | static void __init exynos_init_irq(void) | 189 | static void __init exynos_init_irq(void) |
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 318d127df147..2146d918aedd 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c | |||
@@ -18,7 +18,9 @@ | |||
18 | #include <linux/syscore_ops.h> | 18 | #include <linux/syscore_ops.h> |
19 | #include <linux/cpu_pm.h> | 19 | #include <linux/cpu_pm.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/irqchip/arm-gic.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/irqdomain.h> | ||
23 | #include <linux/of_address.h> | ||
22 | #include <linux/err.h> | 24 | #include <linux/err.h> |
23 | #include <linux/regulator/machine.h> | 25 | #include <linux/regulator/machine.h> |
24 | 26 | ||
@@ -43,8 +45,8 @@ | |||
43 | #define EXYNOS5420_CPU_STATE 0x28 | 45 | #define EXYNOS5420_CPU_STATE 0x28 |
44 | 46 | ||
45 | /** | 47 | /** |
46 | * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping | 48 | * struct exynos_wkup_irq - PMU IRQ to mask mapping |
47 | * @hwirq: Hardware IRQ signal of the GIC | 49 | * @hwirq: Hardware IRQ signal of the PMU |
48 | * @mask: Mask in PMU wake-up mask register | 50 | * @mask: Mask in PMU wake-up mask register |
49 | */ | 51 | */ |
50 | struct exynos_wkup_irq { | 52 | struct exynos_wkup_irq { |
@@ -93,14 +95,14 @@ static const struct exynos_wkup_irq exynos3250_wkup_irq[] = { | |||
93 | }; | 95 | }; |
94 | 96 | ||
95 | static const struct exynos_wkup_irq exynos4_wkup_irq[] = { | 97 | static const struct exynos_wkup_irq exynos4_wkup_irq[] = { |
96 | { 76, BIT(1) }, /* RTC alarm */ | 98 | { 44, BIT(1) }, /* RTC alarm */ |
97 | { 77, BIT(2) }, /* RTC tick */ | 99 | { 45, BIT(2) }, /* RTC tick */ |
98 | { /* sentinel */ }, | 100 | { /* sentinel */ }, |
99 | }; | 101 | }; |
100 | 102 | ||
101 | static const struct exynos_wkup_irq exynos5250_wkup_irq[] = { | 103 | static const struct exynos_wkup_irq exynos5250_wkup_irq[] = { |
102 | { 75, BIT(1) }, /* RTC alarm */ | 104 | { 43, BIT(1) }, /* RTC alarm */ |
103 | { 76, BIT(2) }, /* RTC tick */ | 105 | { 44, BIT(2) }, /* RTC tick */ |
104 | { /* sentinel */ }, | 106 | { /* sentinel */ }, |
105 | }; | 107 | }; |
106 | 108 | ||
@@ -167,6 +169,113 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) | |||
167 | return -ENOENT; | 169 | return -ENOENT; |
168 | } | 170 | } |
169 | 171 | ||
172 | static struct irq_chip exynos_pmu_chip = { | ||
173 | .name = "PMU", | ||
174 | .irq_eoi = irq_chip_eoi_parent, | ||
175 | .irq_mask = irq_chip_mask_parent, | ||
176 | .irq_unmask = irq_chip_unmask_parent, | ||
177 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
178 | .irq_set_wake = exynos_irq_set_wake, | ||
179 | #ifdef CONFIG_SMP | ||
180 | .irq_set_affinity = irq_chip_set_affinity_parent, | ||
181 | #endif | ||
182 | }; | ||
183 | |||
184 | static int exynos_pmu_domain_xlate(struct irq_domain *domain, | ||
185 | struct device_node *controller, | ||
186 | const u32 *intspec, | ||
187 | unsigned int intsize, | ||
188 | unsigned long *out_hwirq, | ||
189 | unsigned int *out_type) | ||
190 | { | ||
191 | if (domain->of_node != controller) | ||
192 | return -EINVAL; /* Shouldn't happen, really... */ | ||
193 | if (intsize != 3) | ||
194 | return -EINVAL; /* Not GIC compliant */ | ||
195 | if (intspec[0] != 0) | ||
196 | return -EINVAL; /* No PPI should point to this domain */ | ||
197 | |||
198 | *out_hwirq = intspec[1]; | ||
199 | *out_type = intspec[2]; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int exynos_pmu_domain_alloc(struct irq_domain *domain, | ||
204 | unsigned int virq, | ||
205 | unsigned int nr_irqs, void *data) | ||
206 | { | ||
207 | struct of_phandle_args *args = data; | ||
208 | struct of_phandle_args parent_args; | ||
209 | irq_hw_number_t hwirq; | ||
210 | int i; | ||
211 | |||
212 | if (args->args_count != 3) | ||
213 | return -EINVAL; /* Not GIC compliant */ | ||
214 | if (args->args[0] != 0) | ||
215 | return -EINVAL; /* No PPI should point to this domain */ | ||
216 | |||
217 | hwirq = args->args[1]; | ||
218 | |||
219 | for (i = 0; i < nr_irqs; i++) | ||
220 | irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, | ||
221 | &exynos_pmu_chip, NULL); | ||
222 | |||
223 | parent_args = *args; | ||
224 | parent_args.np = domain->parent->of_node; | ||
225 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args); | ||
226 | } | ||
227 | |||
228 | static struct irq_domain_ops exynos_pmu_domain_ops = { | ||
229 | .xlate = exynos_pmu_domain_xlate, | ||
230 | .alloc = exynos_pmu_domain_alloc, | ||
231 | .free = irq_domain_free_irqs_common, | ||
232 | }; | ||
233 | |||
234 | static int __init exynos_pmu_irq_init(struct device_node *node, | ||
235 | struct device_node *parent) | ||
236 | { | ||
237 | struct irq_domain *parent_domain, *domain; | ||
238 | |||
239 | if (!parent) { | ||
240 | pr_err("%s: no parent, giving up\n", node->full_name); | ||
241 | return -ENODEV; | ||
242 | } | ||
243 | |||
244 | parent_domain = irq_find_host(parent); | ||
245 | if (!parent_domain) { | ||
246 | pr_err("%s: unable to obtain parent domain\n", node->full_name); | ||
247 | return -ENXIO; | ||
248 | } | ||
249 | |||
250 | pmu_base_addr = of_iomap(node, 0); | ||
251 | |||
252 | if (!pmu_base_addr) { | ||
253 | pr_err("%s: failed to find exynos pmu register\n", | ||
254 | node->full_name); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | domain = irq_domain_add_hierarchy(parent_domain, 0, 0, | ||
259 | node, &exynos_pmu_domain_ops, | ||
260 | NULL); | ||
261 | if (!domain) { | ||
262 | iounmap(pmu_base_addr); | ||
263 | return -ENOMEM; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | #define EXYNOS_PMU_IRQ(symbol, name) OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init) | ||
270 | |||
271 | EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu"); | ||
272 | EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu"); | ||
273 | EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu"); | ||
274 | EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu"); | ||
275 | EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu"); | ||
276 | EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu"); | ||
277 | EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu"); | ||
278 | |||
170 | static int exynos_cpu_do_idle(void) | 279 | static int exynos_cpu_do_idle(void) |
171 | { | 280 | { |
172 | /* issue the standby signal into the pm unit. */ | 281 | /* issue the standby signal into the pm unit. */ |
@@ -615,17 +724,19 @@ static struct syscore_ops exynos_pm_syscore_ops; | |||
615 | void __init exynos_pm_init(void) | 724 | void __init exynos_pm_init(void) |
616 | { | 725 | { |
617 | const struct of_device_id *match; | 726 | const struct of_device_id *match; |
727 | struct device_node *np; | ||
618 | u32 tmp; | 728 | u32 tmp; |
619 | 729 | ||
620 | of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match); | 730 | np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match); |
621 | if (!match) { | 731 | if (!np) { |
622 | pr_err("Failed to find PMU node\n"); | 732 | pr_err("Failed to find PMU node\n"); |
623 | return; | 733 | return; |
624 | } | 734 | } |
625 | pm_data = (struct exynos_pm_data *) match->data; | ||
626 | 735 | ||
627 | /* Platform-specific GIC callback */ | 736 | if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) |
628 | gic_arch_extn.irq_set_wake = exynos_irq_set_wake; | 737 | pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); |
738 | |||
739 | pm_data = (struct exynos_pm_data *) match->data; | ||
629 | 740 | ||
630 | /* All wakeup disable */ | 741 | /* All wakeup disable */ |
631 | tmp = pmu_raw_readl(S5P_WAKEUP_MASK); | 742 | tmp = pmu_raw_readl(S5P_WAKEUP_MASK); |
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e8627e04e1e6..c8dffcee9736 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig | |||
@@ -631,6 +631,7 @@ config SOC_IMX6SX | |||
631 | 631 | ||
632 | config SOC_VF610 | 632 | config SOC_VF610 |
633 | bool "Vybrid Family VF610 support" | 633 | bool "Vybrid Family VF610 support" |
634 | select IRQ_DOMAIN_HIERARCHY | ||
634 | select ARM_GIC | 635 | select ARM_GIC |
635 | select PINCTRL_VF610 | 636 | select PINCTRL_VF610 |
636 | select PL310_ERRATA_769419 if CACHE_L2X0 | 637 | select PL310_ERRATA_769419 if CACHE_L2X0 |
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index f961c46453b9..3b56722dfd8a 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c | |||
@@ -20,11 +20,12 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/irqdomain.h> | ||
24 | #include <linux/of_address.h> | ||
23 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
24 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
25 | #include <linux/notifier.h> | 27 | #include <linux/notifier.h> |
26 | #include <linux/cpu_pm.h> | 28 | #include <linux/cpu_pm.h> |
27 | #include <linux/irqchip/arm-gic.h> | ||
28 | 29 | ||
29 | #include "omap-wakeupgen.h" | 30 | #include "omap-wakeupgen.h" |
30 | #include "omap-secure.h" | 31 | #include "omap-secure.h" |
@@ -78,29 +79,12 @@ static inline void sar_writel(u32 val, u32 offset, u8 idx) | |||
78 | 79 | ||
79 | static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index) | 80 | static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index) |
80 | { | 81 | { |
81 | unsigned int spi_irq; | ||
82 | |||
83 | /* | ||
84 | * PPIs and SGIs are not supported. | ||
85 | */ | ||
86 | if (irq < OMAP44XX_IRQ_GIC_START) | ||
87 | return -EINVAL; | ||
88 | |||
89 | /* | ||
90 | * Subtract the GIC offset. | ||
91 | */ | ||
92 | spi_irq = irq - OMAP44XX_IRQ_GIC_START; | ||
93 | if (spi_irq > MAX_IRQS) { | ||
94 | pr_err("omap wakeupGen: Invalid IRQ%d\n", irq); | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | |||
98 | /* | 82 | /* |
99 | * Each WakeupGen register controls 32 interrupt. | 83 | * Each WakeupGen register controls 32 interrupt. |
100 | * i.e. 1 bit per SPI IRQ | 84 | * i.e. 1 bit per SPI IRQ |
101 | */ | 85 | */ |
102 | *reg_index = spi_irq >> 5; | 86 | *reg_index = irq >> 5; |
103 | *bit_posn = spi_irq %= 32; | 87 | *bit_posn = irq %= 32; |
104 | 88 | ||
105 | return 0; | 89 | return 0; |
106 | } | 90 | } |
@@ -141,6 +125,7 @@ static void wakeupgen_mask(struct irq_data *d) | |||
141 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); | 125 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); |
142 | _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]); | 126 | _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]); |
143 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); | 127 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); |
128 | irq_chip_mask_parent(d); | ||
144 | } | 129 | } |
145 | 130 | ||
146 | /* | 131 | /* |
@@ -153,6 +138,7 @@ static void wakeupgen_unmask(struct irq_data *d) | |||
153 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); | 138 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); |
154 | _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]); | 139 | _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]); |
155 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); | 140 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); |
141 | irq_chip_unmask_parent(d); | ||
156 | } | 142 | } |
157 | 143 | ||
158 | #ifdef CONFIG_HOTPLUG_CPU | 144 | #ifdef CONFIG_HOTPLUG_CPU |
@@ -400,15 +386,91 @@ int omap_secure_apis_support(void) | |||
400 | return omap_secure_apis; | 386 | return omap_secure_apis; |
401 | } | 387 | } |
402 | 388 | ||
389 | static struct irq_chip wakeupgen_chip = { | ||
390 | .name = "WUGEN", | ||
391 | .irq_eoi = irq_chip_eoi_parent, | ||
392 | .irq_mask = wakeupgen_mask, | ||
393 | .irq_unmask = wakeupgen_unmask, | ||
394 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
395 | .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, | ||
396 | #ifdef CONFIG_SMP | ||
397 | .irq_set_affinity = irq_chip_set_affinity_parent, | ||
398 | #endif | ||
399 | }; | ||
400 | |||
401 | static int wakeupgen_domain_xlate(struct irq_domain *domain, | ||
402 | struct device_node *controller, | ||
403 | const u32 *intspec, | ||
404 | unsigned int intsize, | ||
405 | unsigned long *out_hwirq, | ||
406 | unsigned int *out_type) | ||
407 | { | ||
408 | if (domain->of_node != controller) | ||
409 | return -EINVAL; /* Shouldn't happen, really... */ | ||
410 | if (intsize != 3) | ||
411 | return -EINVAL; /* Not GIC compliant */ | ||
412 | if (intspec[0] != 0) | ||
413 | return -EINVAL; /* No PPI should point to this domain */ | ||
414 | |||
415 | *out_hwirq = intspec[1]; | ||
416 | *out_type = intspec[2]; | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int wakeupgen_domain_alloc(struct irq_domain *domain, | ||
421 | unsigned int virq, | ||
422 | unsigned int nr_irqs, void *data) | ||
423 | { | ||
424 | struct of_phandle_args *args = data; | ||
425 | struct of_phandle_args parent_args; | ||
426 | irq_hw_number_t hwirq; | ||
427 | int i; | ||
428 | |||
429 | if (args->args_count != 3) | ||
430 | return -EINVAL; /* Not GIC compliant */ | ||
431 | if (args->args[0] != 0) | ||
432 | return -EINVAL; /* No PPI should point to this domain */ | ||
433 | |||
434 | hwirq = args->args[1]; | ||
435 | if (hwirq >= MAX_IRQS) | ||
436 | return -EINVAL; /* Can't deal with this */ | ||
437 | |||
438 | for (i = 0; i < nr_irqs; i++) | ||
439 | irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, | ||
440 | &wakeupgen_chip, NULL); | ||
441 | |||
442 | parent_args = *args; | ||
443 | parent_args.np = domain->parent->of_node; | ||
444 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args); | ||
445 | } | ||
446 | |||
447 | static struct irq_domain_ops wakeupgen_domain_ops = { | ||
448 | .xlate = wakeupgen_domain_xlate, | ||
449 | .alloc = wakeupgen_domain_alloc, | ||
450 | .free = irq_domain_free_irqs_common, | ||
451 | }; | ||
452 | |||
403 | /* | 453 | /* |
404 | * Initialise the wakeupgen module. | 454 | * Initialise the wakeupgen module. |
405 | */ | 455 | */ |
406 | int __init omap_wakeupgen_init(void) | 456 | static int __init wakeupgen_init(struct device_node *node, |
457 | struct device_node *parent) | ||
407 | { | 458 | { |
459 | struct irq_domain *parent_domain, *domain; | ||
408 | int i; | 460 | int i; |
409 | unsigned int boot_cpu = smp_processor_id(); | 461 | unsigned int boot_cpu = smp_processor_id(); |
410 | u32 val; | 462 | u32 val; |
411 | 463 | ||
464 | if (!parent) { | ||
465 | pr_err("%s: no parent, giving up\n", node->full_name); | ||
466 | return -ENODEV; | ||
467 | } | ||
468 | |||
469 | parent_domain = irq_find_host(parent); | ||
470 | if (!parent_domain) { | ||
471 | pr_err("%s: unable to obtain parent domain\n", node->full_name); | ||
472 | return -ENXIO; | ||
473 | } | ||
412 | /* Not supported on OMAP4 ES1.0 silicon */ | 474 | /* Not supported on OMAP4 ES1.0 silicon */ |
413 | if (omap_rev() == OMAP4430_REV_ES1_0) { | 475 | if (omap_rev() == OMAP4430_REV_ES1_0) { |
414 | WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n"); | 476 | WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n"); |
@@ -416,7 +478,7 @@ int __init omap_wakeupgen_init(void) | |||
416 | } | 478 | } |
417 | 479 | ||
418 | /* Static mapping, never released */ | 480 | /* Static mapping, never released */ |
419 | wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K); | 481 | wakeupgen_base = of_iomap(node, 0); |
420 | if (WARN_ON(!wakeupgen_base)) | 482 | if (WARN_ON(!wakeupgen_base)) |
421 | return -ENOMEM; | 483 | return -ENOMEM; |
422 | 484 | ||
@@ -429,6 +491,14 @@ int __init omap_wakeupgen_init(void) | |||
429 | max_irqs = AM43XX_IRQS; | 491 | max_irqs = AM43XX_IRQS; |
430 | } | 492 | } |
431 | 493 | ||
494 | domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs, | ||
495 | node, &wakeupgen_domain_ops, | ||
496 | NULL); | ||
497 | if (!domain) { | ||
498 | iounmap(wakeupgen_base); | ||
499 | return -ENOMEM; | ||
500 | } | ||
501 | |||
432 | /* Clear all IRQ bitmasks at wakeupGen level */ | 502 | /* Clear all IRQ bitmasks at wakeupGen level */ |
433 | for (i = 0; i < irq_banks; i++) { | 503 | for (i = 0; i < irq_banks; i++) { |
434 | wakeupgen_writel(0, i, CPU0_ID); | 504 | wakeupgen_writel(0, i, CPU0_ID); |
@@ -437,14 +507,6 @@ int __init omap_wakeupgen_init(void) | |||
437 | } | 507 | } |
438 | 508 | ||
439 | /* | 509 | /* |
440 | * Override GIC architecture specific functions to add | ||
441 | * OMAP WakeupGen interrupt controller along with GIC | ||
442 | */ | ||
443 | gic_arch_extn.irq_mask = wakeupgen_mask; | ||
444 | gic_arch_extn.irq_unmask = wakeupgen_unmask; | ||
445 | gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE; | ||
446 | |||
447 | /* | ||
448 | * FIXME: Add support to set_smp_affinity() once the core | 510 | * FIXME: Add support to set_smp_affinity() once the core |
449 | * GIC code has necessary hooks in place. | 511 | * GIC code has necessary hooks in place. |
450 | */ | 512 | */ |
@@ -474,3 +536,9 @@ int __init omap_wakeupgen_init(void) | |||
474 | 536 | ||
475 | return 0; | 537 | return 0; |
476 | } | 538 | } |
539 | |||
540 | /* | ||
541 | * We cannot use the IRQCHIP_DECLARE macro that lives in | ||
542 | * drivers/irqchip, so we're forced to roll our own. Not very nice. | ||
543 | */ | ||
544 | OF_DECLARE_2(irqchip, ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init); | ||
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h index b3c8eccfae79..a3491ad12368 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.h +++ b/arch/arm/mach-omap2/omap-wakeupgen.h | |||
@@ -33,7 +33,6 @@ | |||
33 | #define OMAP_TIMESTAMPCYCLELO 0xc08 | 33 | #define OMAP_TIMESTAMPCYCLELO 0xc08 |
34 | #define OMAP_TIMESTAMPCYCLEHI 0xc0c | 34 | #define OMAP_TIMESTAMPCYCLEHI 0xc0c |
35 | 35 | ||
36 | extern int __init omap_wakeupgen_init(void); | ||
37 | extern void __iomem *omap_get_wakeupgen_base(void); | 36 | extern void __iomem *omap_get_wakeupgen_base(void); |
38 | extern int omap_secure_apis_support(void); | 37 | extern int omap_secure_apis_support(void); |
39 | #endif | 38 | #endif |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index cee0fe1ee6ff..7bb116a6f86f 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <linux/irqchip/arm-gic.h> | 24 | #include <linux/irqchip/arm-gic.h> |
25 | #include <linux/irqchip/irq-crossbar.h> | ||
26 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
27 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
28 | #include <linux/genalloc.h> | 27 | #include <linux/genalloc.h> |
@@ -242,26 +241,26 @@ static int __init omap4_sar_ram_init(void) | |||
242 | } | 241 | } |
243 | omap_early_initcall(omap4_sar_ram_init); | 242 | omap_early_initcall(omap4_sar_ram_init); |
244 | 243 | ||
245 | static const struct of_device_id gic_match[] = { | 244 | static const struct of_device_id intc_match[] = { |
246 | { .compatible = "arm,cortex-a9-gic", }, | 245 | { .compatible = "ti,omap4-wugen-mpu", }, |
247 | { .compatible = "arm,cortex-a15-gic", }, | 246 | { .compatible = "ti,omap5-wugen-mpu", }, |
248 | { }, | 247 | { }, |
249 | }; | 248 | }; |
250 | 249 | ||
251 | static struct device_node *gic_node; | 250 | static struct device_node *intc_node; |
252 | 251 | ||
253 | unsigned int omap4_xlate_irq(unsigned int hwirq) | 252 | unsigned int omap4_xlate_irq(unsigned int hwirq) |
254 | { | 253 | { |
255 | struct of_phandle_args irq_data; | 254 | struct of_phandle_args irq_data; |
256 | unsigned int irq; | 255 | unsigned int irq; |
257 | 256 | ||
258 | if (!gic_node) | 257 | if (!intc_node) |
259 | gic_node = of_find_matching_node(NULL, gic_match); | 258 | intc_node = of_find_matching_node(NULL, intc_match); |
260 | 259 | ||
261 | if (WARN_ON(!gic_node)) | 260 | if (WARN_ON(!intc_node)) |
262 | return hwirq; | 261 | return hwirq; |
263 | 262 | ||
264 | irq_data.np = gic_node; | 263 | irq_data.np = intc_node; |
265 | irq_data.args_count = 3; | 264 | irq_data.args_count = 3; |
266 | irq_data.args[0] = 0; | 265 | irq_data.args[0] = 0; |
267 | irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START; | 266 | irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START; |
@@ -278,6 +277,12 @@ void __init omap_gic_of_init(void) | |||
278 | { | 277 | { |
279 | struct device_node *np; | 278 | struct device_node *np; |
280 | 279 | ||
280 | intc_node = of_find_matching_node(NULL, intc_match); | ||
281 | if (WARN_ON(!intc_node)) { | ||
282 | pr_err("No WUGEN found in DT, system will misbehave.\n"); | ||
283 | pr_err("UPDATE YOUR DEVICE TREE!\n"); | ||
284 | } | ||
285 | |||
281 | /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */ | 286 | /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */ |
282 | if (!cpu_is_omap446x()) | 287 | if (!cpu_is_omap446x()) |
283 | goto skip_errata_init; | 288 | goto skip_errata_init; |
@@ -291,9 +296,5 @@ void __init omap_gic_of_init(void) | |||
291 | WARN_ON(!twd_base); | 296 | WARN_ON(!twd_base); |
292 | 297 | ||
293 | skip_errata_init: | 298 | skip_errata_init: |
294 | omap_wakeupgen_init(); | ||
295 | #ifdef CONFIG_IRQ_CROSSBAR | ||
296 | irqcrossbar_init(); | ||
297 | #endif | ||
298 | irqchip_init(); | 299 | irqchip_init(); |
299 | } | 300 | } |
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 9e3618028acc..fd63ae6532fc 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c | |||
@@ -252,11 +252,6 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) | |||
252 | return IRQ_HANDLED; | 252 | return IRQ_HANDLED; |
253 | } | 253 | } |
254 | 254 | ||
255 | static int sh73a0_set_wake(struct irq_data *data, unsigned int on) | ||
256 | { | ||
257 | return 0; /* always allow wakeup */ | ||
258 | } | ||
259 | |||
260 | #define PINTER0_PHYS 0xe69000a0 | 255 | #define PINTER0_PHYS 0xe69000a0 |
261 | #define PINTER1_PHYS 0xe69000a4 | 256 | #define PINTER1_PHYS 0xe69000a4 |
262 | #define PINTER0_VIRT IOMEM(0xe69000a0) | 257 | #define PINTER0_VIRT IOMEM(0xe69000a0) |
@@ -318,8 +313,8 @@ void __init sh73a0_init_irq(void) | |||
318 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); | 313 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); |
319 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); | 314 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); |
320 | 315 | ||
316 | gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE); | ||
321 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | 317 | gic_init(0, 29, gic_dist_base, gic_cpu_base); |
322 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; | ||
323 | 318 | ||
324 | register_intc_controller(&intcs_desc); | 319 | register_intc_controller(&intcs_desc); |
325 | register_intc_controller(&intc_pint0_desc); | 320 | register_intc_controller(&intc_pint0_desc); |
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 27dceaf9e688..c03e562be12b 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c | |||
@@ -713,18 +713,13 @@ void __init r8a7779_init_late(void) | |||
713 | } | 713 | } |
714 | 714 | ||
715 | #ifdef CONFIG_USE_OF | 715 | #ifdef CONFIG_USE_OF |
716 | static int r8a7779_set_wake(struct irq_data *data, unsigned int on) | ||
717 | { | ||
718 | return 0; /* always allow wakeup */ | ||
719 | } | ||
720 | |||
721 | void __init r8a7779_init_irq_dt(void) | 716 | void __init r8a7779_init_irq_dt(void) |
722 | { | 717 | { |
723 | #ifdef CONFIG_ARCH_SHMOBILE_LEGACY | 718 | #ifdef CONFIG_ARCH_SHMOBILE_LEGACY |
724 | void __iomem *gic_dist_base = ioremap_nocache(0xf0001000, 0x1000); | 719 | void __iomem *gic_dist_base = ioremap_nocache(0xf0001000, 0x1000); |
725 | void __iomem *gic_cpu_base = ioremap_nocache(0xf0000100, 0x1000); | 720 | void __iomem *gic_cpu_base = ioremap_nocache(0xf0000100, 0x1000); |
726 | #endif | 721 | #endif |
727 | gic_arch_extn.irq_set_wake = r8a7779_set_wake; | 722 | gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE); |
728 | 723 | ||
729 | #ifdef CONFIG_ARCH_SHMOBILE_LEGACY | 724 | #ifdef CONFIG_ARCH_SHMOBILE_LEGACY |
730 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | 725 | gic_init(0, 29, gic_dist_base, gic_cpu_base); |
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h index ee79808e93a3..81dc950b4881 100644 --- a/arch/arm/mach-tegra/iomap.h +++ b/arch/arm/mach-tegra/iomap.h | |||
@@ -31,21 +31,6 @@ | |||
31 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 | 31 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 |
32 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K | 32 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K |
33 | 33 | ||
34 | #define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 | ||
35 | #define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 | ||
36 | |||
37 | #define TEGRA_SECONDARY_ICTLR_BASE 0x60004100 | ||
38 | #define TEGRA_SECONDARY_ICTLR_SIZE SZ_64 | ||
39 | |||
40 | #define TEGRA_TERTIARY_ICTLR_BASE 0x60004200 | ||
41 | #define TEGRA_TERTIARY_ICTLR_SIZE SZ_64 | ||
42 | |||
43 | #define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300 | ||
44 | #define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64 | ||
45 | |||
46 | #define TEGRA_QUINARY_ICTLR_BASE 0x60004400 | ||
47 | #define TEGRA_QUINARY_ICTLR_SIZE SZ_64 | ||
48 | |||
49 | #define TEGRA_TMR1_BASE 0x60005000 | 34 | #define TEGRA_TMR1_BASE 0x60005000 |
50 | #define TEGRA_TMR1_SIZE SZ_8 | 35 | #define TEGRA_TMR1_SIZE SZ_8 |
51 | 36 | ||
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index ab95f5391a2b..3b9098d27ea5 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c | |||
@@ -30,43 +30,9 @@ | |||
30 | #include "board.h" | 30 | #include "board.h" |
31 | #include "iomap.h" | 31 | #include "iomap.h" |
32 | 32 | ||
33 | #define ICTLR_CPU_IEP_VFIQ 0x08 | ||
34 | #define ICTLR_CPU_IEP_FIR 0x14 | ||
35 | #define ICTLR_CPU_IEP_FIR_SET 0x18 | ||
36 | #define ICTLR_CPU_IEP_FIR_CLR 0x1c | ||
37 | |||
38 | #define ICTLR_CPU_IER 0x20 | ||
39 | #define ICTLR_CPU_IER_SET 0x24 | ||
40 | #define ICTLR_CPU_IER_CLR 0x28 | ||
41 | #define ICTLR_CPU_IEP_CLASS 0x2C | ||
42 | |||
43 | #define ICTLR_COP_IER 0x30 | ||
44 | #define ICTLR_COP_IER_SET 0x34 | ||
45 | #define ICTLR_COP_IER_CLR 0x38 | ||
46 | #define ICTLR_COP_IEP_CLASS 0x3c | ||
47 | |||
48 | #define FIRST_LEGACY_IRQ 32 | ||
49 | #define TEGRA_MAX_NUM_ICTLRS 5 | ||
50 | |||
51 | #define SGI_MASK 0xFFFF | 33 | #define SGI_MASK 0xFFFF |
52 | 34 | ||
53 | static int num_ictlrs; | ||
54 | |||
55 | static void __iomem *ictlr_reg_base[] = { | ||
56 | IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), | ||
57 | IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), | ||
58 | IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE), | ||
59 | IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), | ||
60 | IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE), | ||
61 | }; | ||
62 | |||
63 | #ifdef CONFIG_PM_SLEEP | 35 | #ifdef CONFIG_PM_SLEEP |
64 | static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS]; | ||
65 | static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS]; | ||
66 | static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS]; | ||
67 | static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS]; | ||
68 | |||
69 | static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS]; | ||
70 | static void __iomem *tegra_gic_cpu_base; | 36 | static void __iomem *tegra_gic_cpu_base; |
71 | #endif | 37 | #endif |
72 | 38 | ||
@@ -83,140 +49,7 @@ bool tegra_pending_sgi(void) | |||
83 | return false; | 49 | return false; |
84 | } | 50 | } |
85 | 51 | ||
86 | static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg) | ||
87 | { | ||
88 | void __iomem *base; | ||
89 | u32 mask; | ||
90 | |||
91 | BUG_ON(irq < FIRST_LEGACY_IRQ || | ||
92 | irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32); | ||
93 | |||
94 | base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32]; | ||
95 | mask = BIT((irq - FIRST_LEGACY_IRQ) % 32); | ||
96 | |||
97 | __raw_writel(mask, base + reg); | ||
98 | } | ||
99 | |||
100 | static void tegra_mask(struct irq_data *d) | ||
101 | { | ||
102 | if (d->hwirq < FIRST_LEGACY_IRQ) | ||
103 | return; | ||
104 | |||
105 | tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR); | ||
106 | } | ||
107 | |||
108 | static void tegra_unmask(struct irq_data *d) | ||
109 | { | ||
110 | if (d->hwirq < FIRST_LEGACY_IRQ) | ||
111 | return; | ||
112 | |||
113 | tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET); | ||
114 | } | ||
115 | |||
116 | static void tegra_ack(struct irq_data *d) | ||
117 | { | ||
118 | if (d->hwirq < FIRST_LEGACY_IRQ) | ||
119 | return; | ||
120 | |||
121 | tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR); | ||
122 | } | ||
123 | |||
124 | static void tegra_eoi(struct irq_data *d) | ||
125 | { | ||
126 | if (d->hwirq < FIRST_LEGACY_IRQ) | ||
127 | return; | ||
128 | |||
129 | tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR); | ||
130 | } | ||
131 | |||
132 | static int tegra_retrigger(struct irq_data *d) | ||
133 | { | ||
134 | if (d->hwirq < FIRST_LEGACY_IRQ) | ||
135 | return 0; | ||
136 | |||
137 | tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET); | ||
138 | |||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | #ifdef CONFIG_PM_SLEEP | 52 | #ifdef CONFIG_PM_SLEEP |
143 | static int tegra_set_wake(struct irq_data *d, unsigned int enable) | ||
144 | { | ||
145 | u32 irq = d->hwirq; | ||
146 | u32 index, mask; | ||
147 | |||
148 | if (irq < FIRST_LEGACY_IRQ || | ||
149 | irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32) | ||
150 | return -EINVAL; | ||
151 | |||
152 | index = ((irq - FIRST_LEGACY_IRQ) / 32); | ||
153 | mask = BIT((irq - FIRST_LEGACY_IRQ) % 32); | ||
154 | if (enable) | ||
155 | ictlr_wake_mask[index] |= mask; | ||
156 | else | ||
157 | ictlr_wake_mask[index] &= ~mask; | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int tegra_legacy_irq_suspend(void) | ||
163 | { | ||
164 | unsigned long flags; | ||
165 | int i; | ||
166 | |||
167 | local_irq_save(flags); | ||
168 | for (i = 0; i < num_ictlrs; i++) { | ||
169 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
170 | /* Save interrupt state */ | ||
171 | cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER); | ||
172 | cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS); | ||
173 | cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER); | ||
174 | cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS); | ||
175 | |||
176 | /* Disable COP interrupts */ | ||
177 | writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
178 | |||
179 | /* Disable CPU interrupts */ | ||
180 | writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
181 | |||
182 | /* Enable the wakeup sources of ictlr */ | ||
183 | writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET); | ||
184 | } | ||
185 | local_irq_restore(flags); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void tegra_legacy_irq_resume(void) | ||
191 | { | ||
192 | unsigned long flags; | ||
193 | int i; | ||
194 | |||
195 | local_irq_save(flags); | ||
196 | for (i = 0; i < num_ictlrs; i++) { | ||
197 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
198 | writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); | ||
199 | writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
200 | writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); | ||
201 | writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS); | ||
202 | writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
203 | writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET); | ||
204 | } | ||
205 | local_irq_restore(flags); | ||
206 | } | ||
207 | |||
208 | static struct syscore_ops tegra_legacy_irq_syscore_ops = { | ||
209 | .suspend = tegra_legacy_irq_suspend, | ||
210 | .resume = tegra_legacy_irq_resume, | ||
211 | }; | ||
212 | |||
213 | int tegra_legacy_irq_syscore_init(void) | ||
214 | { | ||
215 | register_syscore_ops(&tegra_legacy_irq_syscore_ops); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int tegra_gic_notifier(struct notifier_block *self, | 53 | static int tegra_gic_notifier(struct notifier_block *self, |
221 | unsigned long cmd, void *v) | 54 | unsigned long cmd, void *v) |
222 | { | 55 | { |
@@ -251,45 +84,19 @@ static void tegra114_gic_cpu_pm_registration(void) | |||
251 | cpu_pm_register_notifier(&tegra_gic_notifier_block); | 84 | cpu_pm_register_notifier(&tegra_gic_notifier_block); |
252 | } | 85 | } |
253 | #else | 86 | #else |
254 | #define tegra_set_wake NULL | ||
255 | static void tegra114_gic_cpu_pm_registration(void) { } | 87 | static void tegra114_gic_cpu_pm_registration(void) { } |
256 | #endif | 88 | #endif |
257 | 89 | ||
90 | static const struct of_device_id tegra_ictlr_match[] __initconst = { | ||
91 | { .compatible = "nvidia,tegra20-ictlr" }, | ||
92 | { .compatible = "nvidia,tegra30-ictlr" }, | ||
93 | { } | ||
94 | }; | ||
95 | |||
258 | void __init tegra_init_irq(void) | 96 | void __init tegra_init_irq(void) |
259 | { | 97 | { |
260 | int i; | 98 | if (WARN_ON(!of_find_matching_node(NULL, tegra_ictlr_match))) |
261 | void __iomem *distbase; | 99 | pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); |
262 | |||
263 | distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE); | ||
264 | num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f; | ||
265 | |||
266 | if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) { | ||
267 | WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.", | ||
268 | num_ictlrs, ARRAY_SIZE(ictlr_reg_base)); | ||
269 | num_ictlrs = ARRAY_SIZE(ictlr_reg_base); | ||
270 | } | ||
271 | |||
272 | for (i = 0; i < num_ictlrs; i++) { | ||
273 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
274 | writel(~0, ictlr + ICTLR_CPU_IER_CLR); | ||
275 | writel(0, ictlr + ICTLR_CPU_IEP_CLASS); | ||
276 | } | ||
277 | |||
278 | gic_arch_extn.irq_ack = tegra_ack; | ||
279 | gic_arch_extn.irq_eoi = tegra_eoi; | ||
280 | gic_arch_extn.irq_mask = tegra_mask; | ||
281 | gic_arch_extn.irq_unmask = tegra_unmask; | ||
282 | gic_arch_extn.irq_retrigger = tegra_retrigger; | ||
283 | gic_arch_extn.irq_set_wake = tegra_set_wake; | ||
284 | gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND; | ||
285 | |||
286 | /* | ||
287 | * Check if there is a devicetree present, since the GIC will be | ||
288 | * initialized elsewhere under DT. | ||
289 | */ | ||
290 | if (!of_have_populated_dt()) | ||
291 | gic_init(0, 29, distbase, | ||
292 | IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); | ||
293 | 100 | ||
294 | tegra114_gic_cpu_pm_registration(); | 101 | tegra114_gic_cpu_pm_registration(); |
295 | } | 102 | } |
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h index bc05ce5613fb..5142649bba05 100644 --- a/arch/arm/mach-tegra/irq.h +++ b/arch/arm/mach-tegra/irq.h | |||
@@ -19,10 +19,4 @@ | |||
19 | 19 | ||
20 | bool tegra_pending_sgi(void); | 20 | bool tegra_pending_sgi(void); |
21 | 21 | ||
22 | #ifdef CONFIG_PM_SLEEP | ||
23 | int tegra_legacy_irq_syscore_init(void); | ||
24 | #else | ||
25 | static inline int tegra_legacy_irq_syscore_init(void) { return 0; } | ||
26 | #endif | ||
27 | |||
28 | #endif | 22 | #endif |
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 914341bcef25..861d88486dbe 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c | |||
@@ -82,7 +82,6 @@ static void __init tegra_dt_init_irq(void) | |||
82 | { | 82 | { |
83 | tegra_init_irq(); | 83 | tegra_init_irq(); |
84 | irqchip_init(); | 84 | irqchip_init(); |
85 | tegra_legacy_irq_syscore_init(); | ||
86 | } | 85 | } |
87 | 86 | ||
88 | static void __init tegra_dt_init(void) | 87 | static void __init tegra_dt_init(void) |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index dbb2970ee7da..6ced0f680262 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -52,7 +52,7 @@ void ux500_restart(enum reboot_mode mode, const char *cmd) | |||
52 | */ | 52 | */ |
53 | void __init ux500_init_irq(void) | 53 | void __init ux500_init_irq(void) |
54 | { | 54 | { |
55 | gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; | 55 | gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND); |
56 | irqchip_init(); | 56 | irqchip_init(); |
57 | 57 | ||
58 | /* | 58 | /* |
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index c887196cfdbe..58ef2a700414 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c | |||
@@ -186,7 +186,7 @@ static void __init zynq_map_io(void) | |||
186 | 186 | ||
187 | static void __init zynq_irq_init(void) | 187 | static void __init zynq_irq_init(void) |
188 | { | 188 | { |
189 | gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; | 189 | gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND); |
190 | irqchip_init(); | 190 | irqchip_init(); |
191 | } | 191 | } |
192 | 192 | ||
diff --git a/arch/mips/loongson/loongson-3/hpet.c b/arch/mips/loongson/loongson-3/hpet.c index e898d68668a9..5c21cd3bd339 100644 --- a/arch/mips/loongson/loongson-3/hpet.c +++ b/arch/mips/loongson/loongson-3/hpet.c | |||
@@ -162,7 +162,7 @@ static irqreturn_t hpet_irq_handler(int irq, void *data) | |||
162 | 162 | ||
163 | static struct irqaction hpet_irq = { | 163 | static struct irqaction hpet_irq = { |
164 | .handler = hpet_irq_handler, | 164 | .handler = hpet_irq_handler, |
165 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, | 165 | .flags = IRQF_NOBALANCING | IRQF_TIMER, |
166 | .name = "hpet", | 166 | .name = "hpet", |
167 | }; | 167 | }; |
168 | 168 | ||
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 2b9440384536..f749df9e15cd 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
@@ -405,8 +405,8 @@ static int cpqarray_register_ctlr(int i, struct pci_dev *pdev) | |||
405 | goto Enomem4; | 405 | goto Enomem4; |
406 | } | 406 | } |
407 | hba[i]->access.set_intr_mask(hba[i], 0); | 407 | hba[i]->access.set_intr_mask(hba[i], 0); |
408 | if (request_irq(hba[i]->intr, do_ida_intr, | 408 | if (request_irq(hba[i]->intr, do_ida_intr, IRQF_SHARED, |
409 | IRQF_DISABLED|IRQF_SHARED, hba[i]->devname, hba[i])) | 409 | hba[i]->devname, hba[i])) |
410 | { | 410 | { |
411 | printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", | 411 | printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", |
412 | hba[i]->intr, hba[i]->devname); | 412 | hba[i]->intr, hba[i]->devname); |
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c index 029bc73de001..11f7982cbdb3 100644 --- a/drivers/bus/omap_l3_noc.c +++ b/drivers/bus/omap_l3_noc.c | |||
@@ -284,7 +284,7 @@ static int omap_l3_probe(struct platform_device *pdev) | |||
284 | */ | 284 | */ |
285 | l3->debug_irq = platform_get_irq(pdev, 0); | 285 | l3->debug_irq = platform_get_irq(pdev, 0); |
286 | ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler, | 286 | ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler, |
287 | IRQF_DISABLED, "l3-dbg-irq", l3); | 287 | 0x0, "l3-dbg-irq", l3); |
288 | if (ret) { | 288 | if (ret) { |
289 | dev_err(l3->dev, "request_irq failed for %d\n", | 289 | dev_err(l3->dev, "request_irq failed for %d\n", |
290 | l3->debug_irq); | 290 | l3->debug_irq); |
@@ -293,7 +293,7 @@ static int omap_l3_probe(struct platform_device *pdev) | |||
293 | 293 | ||
294 | l3->app_irq = platform_get_irq(pdev, 1); | 294 | l3->app_irq = platform_get_irq(pdev, 1); |
295 | ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler, | 295 | ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler, |
296 | IRQF_DISABLED, "l3-app-irq", l3); | 296 | 0x0, "l3-app-irq", l3); |
297 | if (ret) | 297 | if (ret) |
298 | dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq); | 298 | dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq); |
299 | 299 | ||
diff --git a/drivers/bus/omap_l3_smx.c b/drivers/bus/omap_l3_smx.c index 597fdaee7315..360a5c0a4ee0 100644 --- a/drivers/bus/omap_l3_smx.c +++ b/drivers/bus/omap_l3_smx.c | |||
@@ -251,18 +251,16 @@ static int omap3_l3_probe(struct platform_device *pdev) | |||
251 | } | 251 | } |
252 | 252 | ||
253 | l3->debug_irq = platform_get_irq(pdev, 0); | 253 | l3->debug_irq = platform_get_irq(pdev, 0); |
254 | ret = request_irq(l3->debug_irq, omap3_l3_app_irq, | 254 | ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING, |
255 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | 255 | "l3-debug-irq", l3); |
256 | "l3-debug-irq", l3); | ||
257 | if (ret) { | 256 | if (ret) { |
258 | dev_err(&pdev->dev, "couldn't request debug irq\n"); | 257 | dev_err(&pdev->dev, "couldn't request debug irq\n"); |
259 | goto err1; | 258 | goto err1; |
260 | } | 259 | } |
261 | 260 | ||
262 | l3->app_irq = platform_get_irq(pdev, 1); | 261 | l3->app_irq = platform_get_irq(pdev, 1); |
263 | ret = request_irq(l3->app_irq, omap3_l3_app_irq, | 262 | ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING, |
264 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | 263 | "l3-app-irq", l3); |
265 | "l3-app-irq", l3); | ||
266 | if (ret) { | 264 | if (ret) { |
267 | dev_err(&pdev->dev, "couldn't request app irq\n"); | 265 | dev_err(&pdev->dev, "couldn't request app irq\n"); |
268 | goto err2; | 266 | goto err2; |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cc79d2a5a8c2..c8d260e33a90 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -110,6 +110,13 @@ config RENESAS_IRQC | |||
110 | bool | 110 | bool |
111 | select IRQ_DOMAIN | 111 | select IRQ_DOMAIN |
112 | 112 | ||
113 | config ST_IRQCHIP | ||
114 | bool | ||
115 | select REGMAP | ||
116 | select MFD_SYSCON | ||
117 | help | ||
118 | Enables SysCfg Controlled IRQs on STi based platforms. | ||
119 | |||
113 | config TB10X_IRQC | 120 | config TB10X_IRQC |
114 | bool | 121 | bool |
115 | select IRQ_DOMAIN | 122 | select IRQ_DOMAIN |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 42965d2476bb..552a74027601 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o | |||
6 | obj-$(CONFIG_ARCH_MMP) += irq-mmp.o | 6 | obj-$(CONFIG_ARCH_MMP) += irq-mmp.o |
7 | obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o | 7 | obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o |
8 | obj-$(CONFIG_ARCH_MXS) += irq-mxs.o | 8 | obj-$(CONFIG_ARCH_MXS) += irq-mxs.o |
9 | obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o | ||
9 | obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o | 10 | obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o |
10 | obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o | 11 | obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o |
11 | obj-$(CONFIG_METAG) += irq-metag-ext.o | 12 | obj-$(CONFIG_METAG) += irq-metag-ext.o |
@@ -33,10 +34,12 @@ obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o | |||
33 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o | 34 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o |
34 | obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o | 35 | obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o |
35 | obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o | 36 | obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o |
37 | obj-$(CONFIG_ST_IRQCHIP) += irq-st.o | ||
36 | obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o | 38 | obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o |
37 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o | 39 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o |
38 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o | 40 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o |
39 | obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o | 41 | obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o |
42 | obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o | ||
40 | obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o | 43 | obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o |
41 | obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o | 44 | obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o |
42 | obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o | 45 | obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 4387dae14e45..daccc8bdbb42 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -38,6 +38,8 @@ | |||
38 | /* Interrupt Controller Registers Map */ | 38 | /* Interrupt Controller Registers Map */ |
39 | #define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) | 39 | #define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) |
40 | #define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C) | 40 | #define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C) |
41 | #define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54) | ||
42 | #define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu) | ||
41 | 43 | ||
42 | #define ARMADA_370_XP_INT_CONTROL (0x00) | 44 | #define ARMADA_370_XP_INT_CONTROL (0x00) |
43 | #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) | 45 | #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) |
@@ -56,6 +58,7 @@ | |||
56 | #define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) | 58 | #define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) |
57 | 59 | ||
58 | #define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5) | 60 | #define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5) |
61 | #define ARMADA_370_XP_FABRIC_IRQ (3) | ||
59 | 62 | ||
60 | #define IPI_DOORBELL_START (0) | 63 | #define IPI_DOORBELL_START (0) |
61 | #define IPI_DOORBELL_END (8) | 64 | #define IPI_DOORBELL_END (8) |
@@ -77,6 +80,17 @@ static DEFINE_MUTEX(msi_used_lock); | |||
77 | static phys_addr_t msi_doorbell_addr; | 80 | static phys_addr_t msi_doorbell_addr; |
78 | #endif | 81 | #endif |
79 | 82 | ||
83 | static inline bool is_percpu_irq(irq_hw_number_t irq) | ||
84 | { | ||
85 | switch (irq) { | ||
86 | case ARMADA_370_XP_TIMER0_PER_CPU_IRQ: | ||
87 | case ARMADA_370_XP_FABRIC_IRQ: | ||
88 | return true; | ||
89 | default: | ||
90 | return false; | ||
91 | } | ||
92 | } | ||
93 | |||
80 | /* | 94 | /* |
81 | * In SMP mode: | 95 | * In SMP mode: |
82 | * For shared global interrupts, mask/unmask global enable bit | 96 | * For shared global interrupts, mask/unmask global enable bit |
@@ -86,7 +100,7 @@ static void armada_370_xp_irq_mask(struct irq_data *d) | |||
86 | { | 100 | { |
87 | irq_hw_number_t hwirq = irqd_to_hwirq(d); | 101 | irq_hw_number_t hwirq = irqd_to_hwirq(d); |
88 | 102 | ||
89 | if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) | 103 | if (!is_percpu_irq(hwirq)) |
90 | writel(hwirq, main_int_base + | 104 | writel(hwirq, main_int_base + |
91 | ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); | 105 | ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); |
92 | else | 106 | else |
@@ -98,7 +112,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) | |||
98 | { | 112 | { |
99 | irq_hw_number_t hwirq = irqd_to_hwirq(d); | 113 | irq_hw_number_t hwirq = irqd_to_hwirq(d); |
100 | 114 | ||
101 | if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) | 115 | if (!is_percpu_irq(hwirq)) |
102 | writel(hwirq, main_int_base + | 116 | writel(hwirq, main_int_base + |
103 | ARMADA_370_XP_INT_SET_ENABLE_OFFS); | 117 | ARMADA_370_XP_INT_SET_ENABLE_OFFS); |
104 | else | 118 | else |
@@ -281,20 +295,21 @@ static struct irq_chip armada_370_xp_irq_chip = { | |||
281 | #ifdef CONFIG_SMP | 295 | #ifdef CONFIG_SMP |
282 | .irq_set_affinity = armada_xp_set_affinity, | 296 | .irq_set_affinity = armada_xp_set_affinity, |
283 | #endif | 297 | #endif |
298 | .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, | ||
284 | }; | 299 | }; |
285 | 300 | ||
286 | static int armada_370_xp_mpic_irq_map(struct irq_domain *h, | 301 | static int armada_370_xp_mpic_irq_map(struct irq_domain *h, |
287 | unsigned int virq, irq_hw_number_t hw) | 302 | unsigned int virq, irq_hw_number_t hw) |
288 | { | 303 | { |
289 | armada_370_xp_irq_mask(irq_get_irq_data(virq)); | 304 | armada_370_xp_irq_mask(irq_get_irq_data(virq)); |
290 | if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) | 305 | if (!is_percpu_irq(hw)) |
291 | writel(hw, per_cpu_int_base + | 306 | writel(hw, per_cpu_int_base + |
292 | ARMADA_370_XP_INT_CLEAR_MASK_OFFS); | 307 | ARMADA_370_XP_INT_CLEAR_MASK_OFFS); |
293 | else | 308 | else |
294 | writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); | 309 | writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); |
295 | irq_set_status_flags(virq, IRQ_LEVEL); | 310 | irq_set_status_flags(virq, IRQ_LEVEL); |
296 | 311 | ||
297 | if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) { | 312 | if (is_percpu_irq(hw)) { |
298 | irq_set_percpu_devid(virq); | 313 | irq_set_percpu_devid(virq); |
299 | irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, | 314 | irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, |
300 | handle_percpu_devid_irq); | 315 | handle_percpu_devid_irq); |
@@ -308,28 +323,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, | |||
308 | return 0; | 323 | return 0; |
309 | } | 324 | } |
310 | 325 | ||
311 | #ifdef CONFIG_SMP | ||
312 | static void armada_mpic_send_doorbell(const struct cpumask *mask, | ||
313 | unsigned int irq) | ||
314 | { | ||
315 | int cpu; | ||
316 | unsigned long map = 0; | ||
317 | |||
318 | /* Convert our logical CPU mask into a physical one. */ | ||
319 | for_each_cpu(cpu, mask) | ||
320 | map |= 1 << cpu_logical_map(cpu); | ||
321 | |||
322 | /* | ||
323 | * Ensure that stores to Normal memory are visible to the | ||
324 | * other CPUs before issuing the IPI. | ||
325 | */ | ||
326 | dsb(); | ||
327 | |||
328 | /* submit softirq */ | ||
329 | writel((map << 8) | irq, main_int_base + | ||
330 | ARMADA_370_XP_SW_TRIG_INT_OFFS); | ||
331 | } | ||
332 | |||
333 | static void armada_xp_mpic_smp_cpu_init(void) | 326 | static void armada_xp_mpic_smp_cpu_init(void) |
334 | { | 327 | { |
335 | u32 control; | 328 | u32 control; |
@@ -352,11 +345,44 @@ static void armada_xp_mpic_smp_cpu_init(void) | |||
352 | writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); | 345 | writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); |
353 | } | 346 | } |
354 | 347 | ||
348 | static void armada_xp_mpic_perf_init(void) | ||
349 | { | ||
350 | unsigned long cpuid = cpu_logical_map(smp_processor_id()); | ||
351 | |||
352 | /* Enable Performance Counter Overflow interrupts */ | ||
353 | writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid), | ||
354 | per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS); | ||
355 | } | ||
356 | |||
357 | #ifdef CONFIG_SMP | ||
358 | static void armada_mpic_send_doorbell(const struct cpumask *mask, | ||
359 | unsigned int irq) | ||
360 | { | ||
361 | int cpu; | ||
362 | unsigned long map = 0; | ||
363 | |||
364 | /* Convert our logical CPU mask into a physical one. */ | ||
365 | for_each_cpu(cpu, mask) | ||
366 | map |= 1 << cpu_logical_map(cpu); | ||
367 | |||
368 | /* | ||
369 | * Ensure that stores to Normal memory are visible to the | ||
370 | * other CPUs before issuing the IPI. | ||
371 | */ | ||
372 | dsb(); | ||
373 | |||
374 | /* submit softirq */ | ||
375 | writel((map << 8) | irq, main_int_base + | ||
376 | ARMADA_370_XP_SW_TRIG_INT_OFFS); | ||
377 | } | ||
378 | |||
355 | static int armada_xp_mpic_secondary_init(struct notifier_block *nfb, | 379 | static int armada_xp_mpic_secondary_init(struct notifier_block *nfb, |
356 | unsigned long action, void *hcpu) | 380 | unsigned long action, void *hcpu) |
357 | { | 381 | { |
358 | if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) | 382 | if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) { |
383 | armada_xp_mpic_perf_init(); | ||
359 | armada_xp_mpic_smp_cpu_init(); | 384 | armada_xp_mpic_smp_cpu_init(); |
385 | } | ||
360 | 386 | ||
361 | return NOTIFY_OK; | 387 | return NOTIFY_OK; |
362 | } | 388 | } |
@@ -369,8 +395,10 @@ static struct notifier_block armada_370_xp_mpic_cpu_notifier = { | |||
369 | static int mpic_cascaded_secondary_init(struct notifier_block *nfb, | 395 | static int mpic_cascaded_secondary_init(struct notifier_block *nfb, |
370 | unsigned long action, void *hcpu) | 396 | unsigned long action, void *hcpu) |
371 | { | 397 | { |
372 | if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) | 398 | if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) { |
399 | armada_xp_mpic_perf_init(); | ||
373 | enable_percpu_irq(parent_irq, IRQ_TYPE_NONE); | 400 | enable_percpu_irq(parent_irq, IRQ_TYPE_NONE); |
401 | } | ||
374 | 402 | ||
375 | return NOTIFY_OK; | 403 | return NOTIFY_OK; |
376 | } | 404 | } |
@@ -379,7 +407,6 @@ static struct notifier_block mpic_cascaded_cpu_notifier = { | |||
379 | .notifier_call = mpic_cascaded_secondary_init, | 407 | .notifier_call = mpic_cascaded_secondary_init, |
380 | .priority = 100, | 408 | .priority = 100, |
381 | }; | 409 | }; |
382 | |||
383 | #endif /* CONFIG_SMP */ | 410 | #endif /* CONFIG_SMP */ |
384 | 411 | ||
385 | static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { | 412 | static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { |
@@ -588,9 +615,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
588 | 615 | ||
589 | BUG_ON(!armada_370_xp_mpic_domain); | 616 | BUG_ON(!armada_370_xp_mpic_domain); |
590 | 617 | ||
591 | #ifdef CONFIG_SMP | 618 | /* Setup for the boot CPU */ |
619 | armada_xp_mpic_perf_init(); | ||
592 | armada_xp_mpic_smp_cpu_init(); | 620 | armada_xp_mpic_smp_cpu_init(); |
593 | #endif | ||
594 | 621 | ||
595 | armada_370_xp_msi_init(node, main_int_res.start); | 622 | armada_370_xp_msi_init(node, main_int_res.start); |
596 | 623 | ||
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index bbbaf5de65d2..692fe2bc8197 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c | |||
@@ -11,11 +11,12 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/irqdomain.h> | ||
14 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
15 | #include <linux/of_irq.h> | 16 | #include <linux/of_irq.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/irqchip/arm-gic.h> | 18 | |
18 | #include <linux/irqchip/irq-crossbar.h> | 19 | #include "irqchip.h" |
19 | 20 | ||
20 | #define IRQ_FREE -1 | 21 | #define IRQ_FREE -1 |
21 | #define IRQ_RESERVED -2 | 22 | #define IRQ_RESERVED -2 |
@@ -24,6 +25,7 @@ | |||
24 | 25 | ||
25 | /** | 26 | /** |
26 | * struct crossbar_device - crossbar device description | 27 | * struct crossbar_device - crossbar device description |
28 | * @lock: spinlock serializing access to @irq_map | ||
27 | * @int_max: maximum number of supported interrupts | 29 | * @int_max: maximum number of supported interrupts |
28 | * @safe_map: safe default value to initialize the crossbar | 30 | * @safe_map: safe default value to initialize the crossbar |
29 | * @max_crossbar_sources: Maximum number of crossbar sources | 31 | * @max_crossbar_sources: Maximum number of crossbar sources |
@@ -33,6 +35,7 @@ | |||
33 | * @write: register write function pointer | 35 | * @write: register write function pointer |
34 | */ | 36 | */ |
35 | struct crossbar_device { | 37 | struct crossbar_device { |
38 | raw_spinlock_t lock; | ||
36 | uint int_max; | 39 | uint int_max; |
37 | uint safe_map; | 40 | uint safe_map; |
38 | uint max_crossbar_sources; | 41 | uint max_crossbar_sources; |
@@ -44,72 +47,101 @@ struct crossbar_device { | |||
44 | 47 | ||
45 | static struct crossbar_device *cb; | 48 | static struct crossbar_device *cb; |
46 | 49 | ||
47 | static inline void crossbar_writel(int irq_no, int cb_no) | 50 | static void crossbar_writel(int irq_no, int cb_no) |
48 | { | 51 | { |
49 | writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | 52 | writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); |
50 | } | 53 | } |
51 | 54 | ||
52 | static inline void crossbar_writew(int irq_no, int cb_no) | 55 | static void crossbar_writew(int irq_no, int cb_no) |
53 | { | 56 | { |
54 | writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | 57 | writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); |
55 | } | 58 | } |
56 | 59 | ||
57 | static inline void crossbar_writeb(int irq_no, int cb_no) | 60 | static void crossbar_writeb(int irq_no, int cb_no) |
58 | { | 61 | { |
59 | writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | 62 | writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); |
60 | } | 63 | } |
61 | 64 | ||
62 | static inline int get_prev_map_irq(int cb_no) | 65 | static struct irq_chip crossbar_chip = { |
63 | { | 66 | .name = "CBAR", |
64 | int i; | 67 | .irq_eoi = irq_chip_eoi_parent, |
65 | 68 | .irq_mask = irq_chip_mask_parent, | |
66 | for (i = cb->int_max - 1; i >= 0; i--) | 69 | .irq_unmask = irq_chip_unmask_parent, |
67 | if (cb->irq_map[i] == cb_no) | 70 | .irq_retrigger = irq_chip_retrigger_hierarchy, |
68 | return i; | 71 | .irq_set_wake = irq_chip_set_wake_parent, |
69 | 72 | #ifdef CONFIG_SMP | |
70 | return -ENODEV; | 73 | .irq_set_affinity = irq_chip_set_affinity_parent, |
71 | } | 74 | #endif |
75 | }; | ||
72 | 76 | ||
73 | static inline int allocate_free_irq(int cb_no) | 77 | static int allocate_gic_irq(struct irq_domain *domain, unsigned virq, |
78 | irq_hw_number_t hwirq) | ||
74 | { | 79 | { |
80 | struct of_phandle_args args; | ||
75 | int i; | 81 | int i; |
82 | int err; | ||
76 | 83 | ||
84 | raw_spin_lock(&cb->lock); | ||
77 | for (i = cb->int_max - 1; i >= 0; i--) { | 85 | for (i = cb->int_max - 1; i >= 0; i--) { |
78 | if (cb->irq_map[i] == IRQ_FREE) { | 86 | if (cb->irq_map[i] == IRQ_FREE) { |
79 | cb->irq_map[i] = cb_no; | 87 | cb->irq_map[i] = hwirq; |
80 | return i; | 88 | break; |
81 | } | 89 | } |
82 | } | 90 | } |
91 | raw_spin_unlock(&cb->lock); | ||
83 | 92 | ||
84 | return -ENODEV; | 93 | if (i < 0) |
85 | } | 94 | return -ENODEV; |
86 | 95 | ||
87 | static inline bool needs_crossbar_write(irq_hw_number_t hw) | 96 | args.np = domain->parent->of_node; |
88 | { | 97 | args.args_count = 3; |
89 | int cb_no; | 98 | args.args[0] = 0; /* SPI */ |
99 | args.args[1] = i; | ||
100 | args.args[2] = IRQ_TYPE_LEVEL_HIGH; | ||
90 | 101 | ||
91 | if (hw > GIC_IRQ_START) { | 102 | err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args); |
92 | cb_no = cb->irq_map[hw - GIC_IRQ_START]; | 103 | if (err) |
93 | if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP) | 104 | cb->irq_map[i] = IRQ_FREE; |
94 | return true; | 105 | else |
95 | } | 106 | cb->write(i, hwirq); |
96 | 107 | ||
97 | return false; | 108 | return err; |
98 | } | 109 | } |
99 | 110 | ||
100 | static int crossbar_domain_map(struct irq_domain *d, unsigned int irq, | 111 | static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq, |
101 | irq_hw_number_t hw) | 112 | unsigned int nr_irqs, void *data) |
102 | { | 113 | { |
103 | if (needs_crossbar_write(hw)) | 114 | struct of_phandle_args *args = data; |
104 | cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]); | 115 | irq_hw_number_t hwirq; |
116 | int i; | ||
117 | |||
118 | if (args->args_count != 3) | ||
119 | return -EINVAL; /* Not GIC compliant */ | ||
120 | if (args->args[0] != 0) | ||
121 | return -EINVAL; /* No PPI should point to this domain */ | ||
122 | |||
123 | hwirq = args->args[1]; | ||
124 | if ((hwirq + nr_irqs) > cb->max_crossbar_sources) | ||
125 | return -EINVAL; /* Can't deal with this */ | ||
126 | |||
127 | for (i = 0; i < nr_irqs; i++) { | ||
128 | int err = allocate_gic_irq(d, virq + i, hwirq + i); | ||
129 | |||
130 | if (err) | ||
131 | return err; | ||
132 | |||
133 | irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i, | ||
134 | &crossbar_chip, NULL); | ||
135 | } | ||
105 | 136 | ||
106 | return 0; | 137 | return 0; |
107 | } | 138 | } |
108 | 139 | ||
109 | /** | 140 | /** |
110 | * crossbar_domain_unmap - unmap a crossbar<->irq connection | 141 | * crossbar_domain_free - unmap/free a crossbar<->irq connection |
111 | * @d: domain of irq to unmap | 142 | * @domain: domain of irq to unmap |
112 | * @irq: virq number | 143 | * @virq: virq number |
144 | * @nr_irqs: number of irqs to free | ||
113 | * | 145 | * |
114 | * We do not maintain a use count of total number of map/unmap | 146 | * We do not maintain a use count of total number of map/unmap |
115 | * calls for a particular irq to find out if a irq can be really | 147 | * calls for a particular irq to find out if a irq can be really |
@@ -117,14 +149,20 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq, | |||
117 | * after which irq is anyways unusable. So an explicit map has to be called | 149 | * after which irq is anyways unusable. So an explicit map has to be called |
118 | * after that. | 150 | * after that. |
119 | */ | 151 | */ |
120 | static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq) | 152 | static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq, |
153 | unsigned int nr_irqs) | ||
121 | { | 154 | { |
122 | irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq; | 155 | int i; |
123 | 156 | ||
124 | if (needs_crossbar_write(hw)) { | 157 | raw_spin_lock(&cb->lock); |
125 | cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE; | 158 | for (i = 0; i < nr_irqs; i++) { |
126 | cb->write(hw - GIC_IRQ_START, cb->safe_map); | 159 | struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); |
160 | |||
161 | irq_domain_reset_irq_data(d); | ||
162 | cb->irq_map[d->hwirq] = IRQ_FREE; | ||
163 | cb->write(d->hwirq, cb->safe_map); | ||
127 | } | 164 | } |
165 | raw_spin_unlock(&cb->lock); | ||
128 | } | 166 | } |
129 | 167 | ||
130 | static int crossbar_domain_xlate(struct irq_domain *d, | 168 | static int crossbar_domain_xlate(struct irq_domain *d, |
@@ -133,44 +171,22 @@ static int crossbar_domain_xlate(struct irq_domain *d, | |||
133 | unsigned long *out_hwirq, | 171 | unsigned long *out_hwirq, |
134 | unsigned int *out_type) | 172 | unsigned int *out_type) |
135 | { | 173 | { |
136 | int ret; | 174 | if (d->of_node != controller) |
137 | int req_num = intspec[1]; | 175 | return -EINVAL; /* Shouldn't happen, really... */ |
138 | int direct_map_num; | 176 | if (intsize != 3) |
139 | 177 | return -EINVAL; /* Not GIC compliant */ | |
140 | if (req_num >= cb->max_crossbar_sources) { | 178 | if (intspec[0] != 0) |
141 | direct_map_num = req_num - cb->max_crossbar_sources; | 179 | return -EINVAL; /* No PPI should point to this domain */ |
142 | if (direct_map_num < cb->int_max) { | 180 | |
143 | ret = cb->irq_map[direct_map_num]; | 181 | *out_hwirq = intspec[1]; |
144 | if (ret == IRQ_RESERVED || ret == IRQ_SKIP) { | 182 | *out_type = intspec[2]; |
145 | /* We use the interrupt num as h/w irq num */ | ||
146 | ret = direct_map_num; | ||
147 | goto found; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | pr_err("%s: requested crossbar number %d > max %d\n", | ||
152 | __func__, req_num, cb->max_crossbar_sources); | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | ret = get_prev_map_irq(req_num); | ||
157 | if (ret >= 0) | ||
158 | goto found; | ||
159 | |||
160 | ret = allocate_free_irq(req_num); | ||
161 | |||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | found: | ||
166 | *out_hwirq = ret + GIC_IRQ_START; | ||
167 | return 0; | 183 | return 0; |
168 | } | 184 | } |
169 | 185 | ||
170 | static const struct irq_domain_ops routable_irq_domain_ops = { | 186 | static const struct irq_domain_ops crossbar_domain_ops = { |
171 | .map = crossbar_domain_map, | 187 | .alloc = crossbar_domain_alloc, |
172 | .unmap = crossbar_domain_unmap, | 188 | .free = crossbar_domain_free, |
173 | .xlate = crossbar_domain_xlate | 189 | .xlate = crossbar_domain_xlate, |
174 | }; | 190 | }; |
175 | 191 | ||
176 | static int __init crossbar_of_init(struct device_node *node) | 192 | static int __init crossbar_of_init(struct device_node *node) |
@@ -293,7 +309,8 @@ static int __init crossbar_of_init(struct device_node *node) | |||
293 | cb->write(i, cb->safe_map); | 309 | cb->write(i, cb->safe_map); |
294 | } | 310 | } |
295 | 311 | ||
296 | register_routable_domain_ops(&routable_irq_domain_ops); | 312 | raw_spin_lock_init(&cb->lock); |
313 | |||
297 | return 0; | 314 | return 0; |
298 | 315 | ||
299 | err_reg_offset: | 316 | err_reg_offset: |
@@ -309,18 +326,37 @@ err_cb: | |||
309 | return ret; | 326 | return ret; |
310 | } | 327 | } |
311 | 328 | ||
312 | static const struct of_device_id crossbar_match[] __initconst = { | 329 | static int __init irqcrossbar_init(struct device_node *node, |
313 | { .compatible = "ti,irq-crossbar" }, | 330 | struct device_node *parent) |
314 | {} | ||
315 | }; | ||
316 | |||
317 | int __init irqcrossbar_init(void) | ||
318 | { | 331 | { |
319 | struct device_node *np; | 332 | struct irq_domain *parent_domain, *domain; |
320 | np = of_find_matching_node(NULL, crossbar_match); | 333 | int err; |
321 | if (!np) | 334 | |
335 | if (!parent) { | ||
336 | pr_err("%s: no parent, giving up\n", node->full_name); | ||
322 | return -ENODEV; | 337 | return -ENODEV; |
338 | } | ||
339 | |||
340 | parent_domain = irq_find_host(parent); | ||
341 | if (!parent_domain) { | ||
342 | pr_err("%s: unable to obtain parent domain\n", node->full_name); | ||
343 | return -ENXIO; | ||
344 | } | ||
345 | |||
346 | err = crossbar_of_init(node); | ||
347 | if (err) | ||
348 | return err; | ||
349 | |||
350 | domain = irq_domain_add_hierarchy(parent_domain, 0, | ||
351 | cb->max_crossbar_sources, | ||
352 | node, &crossbar_domain_ops, | ||
353 | NULL); | ||
354 | if (!domain) { | ||
355 | pr_err("%s: failed to allocated domain\n", node->full_name); | ||
356 | return -ENOMEM; | ||
357 | } | ||
323 | 358 | ||
324 | crossbar_of_init(np); | ||
325 | return 0; | 359 | return 0; |
326 | } | 360 | } |
361 | |||
362 | IRQCHIP_DECLARE(ti_irqcrossbar, "ti,irq-crossbar", irqcrossbar_init); | ||
diff --git a/drivers/irqchip/irq-digicolor.c b/drivers/irqchip/irq-digicolor.c index 930a2a2fac7f..3cbc658afe27 100644 --- a/drivers/irqchip/irq-digicolor.c +++ b/drivers/irqchip/irq-digicolor.c | |||
@@ -55,8 +55,8 @@ static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs) | |||
55 | } while (1); | 55 | } while (1); |
56 | } | 56 | } |
57 | 57 | ||
58 | static void digicolor_set_gc(void __iomem *reg_base, unsigned irq_base, | 58 | static void __init digicolor_set_gc(void __iomem *reg_base, unsigned irq_base, |
59 | unsigned en_reg, unsigned ack_reg) | 59 | unsigned en_reg, unsigned ack_reg) |
60 | { | 60 | { |
61 | struct irq_chip_generic *gc; | 61 | struct irq_chip_generic *gc; |
62 | 62 | ||
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index fd8850def1b8..4f2fb62e6f37 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -195,6 +195,19 @@ static void gic_enable_redist(bool enable) | |||
195 | /* | 195 | /* |
196 | * Routines to disable, enable, EOI and route interrupts | 196 | * Routines to disable, enable, EOI and route interrupts |
197 | */ | 197 | */ |
198 | static int gic_peek_irq(struct irq_data *d, u32 offset) | ||
199 | { | ||
200 | u32 mask = 1 << (gic_irq(d) % 32); | ||
201 | void __iomem *base; | ||
202 | |||
203 | if (gic_irq_in_rdist(d)) | ||
204 | base = gic_data_rdist_sgi_base(); | ||
205 | else | ||
206 | base = gic_data.dist_base; | ||
207 | |||
208 | return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask); | ||
209 | } | ||
210 | |||
198 | static void gic_poke_irq(struct irq_data *d, u32 offset) | 211 | static void gic_poke_irq(struct irq_data *d, u32 offset) |
199 | { | 212 | { |
200 | u32 mask = 1 << (gic_irq(d) % 32); | 213 | u32 mask = 1 << (gic_irq(d) % 32); |
@@ -223,6 +236,61 @@ static void gic_unmask_irq(struct irq_data *d) | |||
223 | gic_poke_irq(d, GICD_ISENABLER); | 236 | gic_poke_irq(d, GICD_ISENABLER); |
224 | } | 237 | } |
225 | 238 | ||
239 | static int gic_irq_set_irqchip_state(struct irq_data *d, | ||
240 | enum irqchip_irq_state which, bool val) | ||
241 | { | ||
242 | u32 reg; | ||
243 | |||
244 | if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */ | ||
245 | return -EINVAL; | ||
246 | |||
247 | switch (which) { | ||
248 | case IRQCHIP_STATE_PENDING: | ||
249 | reg = val ? GICD_ISPENDR : GICD_ICPENDR; | ||
250 | break; | ||
251 | |||
252 | case IRQCHIP_STATE_ACTIVE: | ||
253 | reg = val ? GICD_ISACTIVER : GICD_ICACTIVER; | ||
254 | break; | ||
255 | |||
256 | case IRQCHIP_STATE_MASKED: | ||
257 | reg = val ? GICD_ICENABLER : GICD_ISENABLER; | ||
258 | break; | ||
259 | |||
260 | default: | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | |||
264 | gic_poke_irq(d, reg); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int gic_irq_get_irqchip_state(struct irq_data *d, | ||
269 | enum irqchip_irq_state which, bool *val) | ||
270 | { | ||
271 | if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */ | ||
272 | return -EINVAL; | ||
273 | |||
274 | switch (which) { | ||
275 | case IRQCHIP_STATE_PENDING: | ||
276 | *val = gic_peek_irq(d, GICD_ISPENDR); | ||
277 | break; | ||
278 | |||
279 | case IRQCHIP_STATE_ACTIVE: | ||
280 | *val = gic_peek_irq(d, GICD_ISACTIVER); | ||
281 | break; | ||
282 | |||
283 | case IRQCHIP_STATE_MASKED: | ||
284 | *val = !gic_peek_irq(d, GICD_ISENABLER); | ||
285 | break; | ||
286 | |||
287 | default: | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
226 | static void gic_eoi_irq(struct irq_data *d) | 294 | static void gic_eoi_irq(struct irq_data *d) |
227 | { | 295 | { |
228 | gic_write_eoir(gic_irq(d)); | 296 | gic_write_eoir(gic_irq(d)); |
@@ -418,19 +486,6 @@ static void gic_cpu_init(void) | |||
418 | } | 486 | } |
419 | 487 | ||
420 | #ifdef CONFIG_SMP | 488 | #ifdef CONFIG_SMP |
421 | static int gic_peek_irq(struct irq_data *d, u32 offset) | ||
422 | { | ||
423 | u32 mask = 1 << (gic_irq(d) % 32); | ||
424 | void __iomem *base; | ||
425 | |||
426 | if (gic_irq_in_rdist(d)) | ||
427 | base = gic_data_rdist_sgi_base(); | ||
428 | else | ||
429 | base = gic_data.dist_base; | ||
430 | |||
431 | return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask); | ||
432 | } | ||
433 | |||
434 | static int gic_secondary_init(struct notifier_block *nfb, | 489 | static int gic_secondary_init(struct notifier_block *nfb, |
435 | unsigned long action, void *hcpu) | 490 | unsigned long action, void *hcpu) |
436 | { | 491 | { |
@@ -601,6 +656,8 @@ static struct irq_chip gic_chip = { | |||
601 | .irq_eoi = gic_eoi_irq, | 656 | .irq_eoi = gic_eoi_irq, |
602 | .irq_set_type = gic_set_type, | 657 | .irq_set_type = gic_set_type, |
603 | .irq_set_affinity = gic_set_affinity, | 658 | .irq_set_affinity = gic_set_affinity, |
659 | .irq_get_irqchip_state = gic_irq_get_irqchip_state, | ||
660 | .irq_set_irqchip_state = gic_irq_set_irqchip_state, | ||
604 | }; | 661 | }; |
605 | 662 | ||
606 | #define GIC_ID_NR (1U << gic_data.rdists.id_bits) | 663 | #define GIC_ID_NR (1U << gic_data.rdists.id_bits) |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 471e1cdc1933..a6ce3476834e 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -151,13 +151,24 @@ static inline unsigned int gic_irq(struct irq_data *d) | |||
151 | /* | 151 | /* |
152 | * Routines to acknowledge, disable and enable interrupts | 152 | * Routines to acknowledge, disable and enable interrupts |
153 | */ | 153 | */ |
154 | static void gic_mask_irq(struct irq_data *d) | 154 | static void gic_poke_irq(struct irq_data *d, u32 offset) |
155 | { | 155 | { |
156 | u32 mask = 1 << (gic_irq(d) % 32); | 156 | u32 mask = 1 << (gic_irq(d) % 32); |
157 | writel_relaxed(mask, gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4); | ||
158 | } | ||
159 | |||
160 | static int gic_peek_irq(struct irq_data *d, u32 offset) | ||
161 | { | ||
162 | u32 mask = 1 << (gic_irq(d) % 32); | ||
163 | return !!(readl_relaxed(gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4) & mask); | ||
164 | } | ||
165 | |||
166 | static void gic_mask_irq(struct irq_data *d) | ||
167 | { | ||
157 | unsigned long flags; | 168 | unsigned long flags; |
158 | 169 | ||
159 | raw_spin_lock_irqsave(&irq_controller_lock, flags); | 170 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
160 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); | 171 | gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR); |
161 | if (gic_arch_extn.irq_mask) | 172 | if (gic_arch_extn.irq_mask) |
162 | gic_arch_extn.irq_mask(d); | 173 | gic_arch_extn.irq_mask(d); |
163 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); | 174 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
@@ -165,13 +176,12 @@ static void gic_mask_irq(struct irq_data *d) | |||
165 | 176 | ||
166 | static void gic_unmask_irq(struct irq_data *d) | 177 | static void gic_unmask_irq(struct irq_data *d) |
167 | { | 178 | { |
168 | u32 mask = 1 << (gic_irq(d) % 32); | ||
169 | unsigned long flags; | 179 | unsigned long flags; |
170 | 180 | ||
171 | raw_spin_lock_irqsave(&irq_controller_lock, flags); | 181 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
172 | if (gic_arch_extn.irq_unmask) | 182 | if (gic_arch_extn.irq_unmask) |
173 | gic_arch_extn.irq_unmask(d); | 183 | gic_arch_extn.irq_unmask(d); |
174 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); | 184 | gic_poke_irq(d, GIC_DIST_ENABLE_SET); |
175 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); | 185 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
176 | } | 186 | } |
177 | 187 | ||
@@ -186,6 +196,55 @@ static void gic_eoi_irq(struct irq_data *d) | |||
186 | writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); | 196 | writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); |
187 | } | 197 | } |
188 | 198 | ||
199 | static int gic_irq_set_irqchip_state(struct irq_data *d, | ||
200 | enum irqchip_irq_state which, bool val) | ||
201 | { | ||
202 | u32 reg; | ||
203 | |||
204 | switch (which) { | ||
205 | case IRQCHIP_STATE_PENDING: | ||
206 | reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR; | ||
207 | break; | ||
208 | |||
209 | case IRQCHIP_STATE_ACTIVE: | ||
210 | reg = val ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR; | ||
211 | break; | ||
212 | |||
213 | case IRQCHIP_STATE_MASKED: | ||
214 | reg = val ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET; | ||
215 | break; | ||
216 | |||
217 | default: | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | gic_poke_irq(d, reg); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int gic_irq_get_irqchip_state(struct irq_data *d, | ||
226 | enum irqchip_irq_state which, bool *val) | ||
227 | { | ||
228 | switch (which) { | ||
229 | case IRQCHIP_STATE_PENDING: | ||
230 | *val = gic_peek_irq(d, GIC_DIST_PENDING_SET); | ||
231 | break; | ||
232 | |||
233 | case IRQCHIP_STATE_ACTIVE: | ||
234 | *val = gic_peek_irq(d, GIC_DIST_ACTIVE_SET); | ||
235 | break; | ||
236 | |||
237 | case IRQCHIP_STATE_MASKED: | ||
238 | *val = !gic_peek_irq(d, GIC_DIST_ENABLE_SET); | ||
239 | break; | ||
240 | |||
241 | default: | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
189 | static int gic_set_type(struct irq_data *d, unsigned int type) | 248 | static int gic_set_type(struct irq_data *d, unsigned int type) |
190 | { | 249 | { |
191 | void __iomem *base = gic_dist_base(d); | 250 | void __iomem *base = gic_dist_base(d); |
@@ -329,6 +388,8 @@ static struct irq_chip gic_chip = { | |||
329 | .irq_set_affinity = gic_set_affinity, | 388 | .irq_set_affinity = gic_set_affinity, |
330 | #endif | 389 | #endif |
331 | .irq_set_wake = gic_set_wake, | 390 | .irq_set_wake = gic_set_wake, |
391 | .irq_get_irqchip_state = gic_irq_get_irqchip_state, | ||
392 | .irq_set_irqchip_state = gic_irq_set_irqchip_state, | ||
332 | }; | 393 | }; |
333 | 394 | ||
334 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | 395 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) |
@@ -353,7 +414,7 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic) | |||
353 | break; | 414 | break; |
354 | } | 415 | } |
355 | 416 | ||
356 | if (!mask) | 417 | if (!mask && num_possible_cpus() > 1) |
357 | pr_crit("GIC CPU mask not found - kernel will fail to boot.\n"); | 418 | pr_crit("GIC CPU mask not found - kernel will fail to boot.\n"); |
358 | 419 | ||
359 | return mask; | 420 | return mask; |
@@ -802,15 +863,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | |||
802 | irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data, | 863 | irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data, |
803 | handle_fasteoi_irq, NULL, NULL); | 864 | handle_fasteoi_irq, NULL, NULL); |
804 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 865 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
805 | |||
806 | gic_routable_irq_domain_ops->map(d, irq, hw); | ||
807 | } | 866 | } |
808 | return 0; | 867 | return 0; |
809 | } | 868 | } |
810 | 869 | ||
811 | static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq) | 870 | static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq) |
812 | { | 871 | { |
813 | gic_routable_irq_domain_ops->unmap(d, irq); | ||
814 | } | 872 | } |
815 | 873 | ||
816 | static int gic_irq_domain_xlate(struct irq_domain *d, | 874 | static int gic_irq_domain_xlate(struct irq_domain *d, |
@@ -829,16 +887,8 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
829 | *out_hwirq = intspec[1] + 16; | 887 | *out_hwirq = intspec[1] + 16; |
830 | 888 | ||
831 | /* For SPIs, we need to add 16 more to get the GIC irq ID number */ | 889 | /* For SPIs, we need to add 16 more to get the GIC irq ID number */ |
832 | if (!intspec[0]) { | 890 | if (!intspec[0]) |
833 | ret = gic_routable_irq_domain_ops->xlate(d, controller, | 891 | *out_hwirq += 16; |
834 | intspec, | ||
835 | intsize, | ||
836 | out_hwirq, | ||
837 | out_type); | ||
838 | |||
839 | if (IS_ERR_VALUE(ret)) | ||
840 | return ret; | ||
841 | } | ||
842 | 892 | ||
843 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; | 893 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; |
844 | 894 | ||
@@ -895,37 +945,11 @@ static const struct irq_domain_ops gic_irq_domain_ops = { | |||
895 | .xlate = gic_irq_domain_xlate, | 945 | .xlate = gic_irq_domain_xlate, |
896 | }; | 946 | }; |
897 | 947 | ||
898 | /* Default functions for routable irq domain */ | 948 | void gic_set_irqchip_flags(unsigned long flags) |
899 | static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq, | ||
900 | irq_hw_number_t hw) | ||
901 | { | 949 | { |
902 | return 0; | 950 | gic_chip.flags |= flags; |
903 | } | 951 | } |
904 | 952 | ||
905 | static void gic_routable_irq_domain_unmap(struct irq_domain *d, | ||
906 | unsigned int irq) | ||
907 | { | ||
908 | } | ||
909 | |||
910 | static int gic_routable_irq_domain_xlate(struct irq_domain *d, | ||
911 | struct device_node *controller, | ||
912 | const u32 *intspec, unsigned int intsize, | ||
913 | unsigned long *out_hwirq, | ||
914 | unsigned int *out_type) | ||
915 | { | ||
916 | *out_hwirq += 16; | ||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static const struct irq_domain_ops gic_default_routable_irq_domain_ops = { | ||
921 | .map = gic_routable_irq_domain_map, | ||
922 | .unmap = gic_routable_irq_domain_unmap, | ||
923 | .xlate = gic_routable_irq_domain_xlate, | ||
924 | }; | ||
925 | |||
926 | const struct irq_domain_ops *gic_routable_irq_domain_ops = | ||
927 | &gic_default_routable_irq_domain_ops; | ||
928 | |||
929 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, | 953 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, |
930 | void __iomem *dist_base, void __iomem *cpu_base, | 954 | void __iomem *dist_base, void __iomem *cpu_base, |
931 | u32 percpu_offset, struct device_node *node) | 955 | u32 percpu_offset, struct device_node *node) |
@@ -933,7 +957,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
933 | irq_hw_number_t hwirq_base; | 957 | irq_hw_number_t hwirq_base; |
934 | struct gic_chip_data *gic; | 958 | struct gic_chip_data *gic; |
935 | int gic_irqs, irq_base, i; | 959 | int gic_irqs, irq_base, i; |
936 | int nr_routable_irqs; | ||
937 | 960 | ||
938 | BUG_ON(gic_nr >= MAX_GIC_NR); | 961 | BUG_ON(gic_nr >= MAX_GIC_NR); |
939 | 962 | ||
@@ -989,15 +1012,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
989 | gic->gic_irqs = gic_irqs; | 1012 | gic->gic_irqs = gic_irqs; |
990 | 1013 | ||
991 | if (node) { /* DT case */ | 1014 | if (node) { /* DT case */ |
992 | const struct irq_domain_ops *ops = &gic_irq_domain_hierarchy_ops; | 1015 | gic->domain = irq_domain_add_linear(node, gic_irqs, |
993 | 1016 | &gic_irq_domain_hierarchy_ops, | |
994 | if (!of_property_read_u32(node, "arm,routable-irqs", | 1017 | gic); |
995 | &nr_routable_irqs)) { | ||
996 | ops = &gic_irq_domain_ops; | ||
997 | gic_irqs = nr_routable_irqs; | ||
998 | } | ||
999 | |||
1000 | gic->domain = irq_domain_add_linear(node, gic_irqs, ops, gic); | ||
1001 | } else { /* Non-DT case */ | 1018 | } else { /* Non-DT case */ |
1002 | /* | 1019 | /* |
1003 | * For primary GICs, skip over SGIs. | 1020 | * For primary GICs, skip over SGIs. |
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 9acdc080e7ec..f2d269bca789 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -166,6 +166,27 @@ cycle_t gic_read_compare(void) | |||
166 | 166 | ||
167 | return (((cycle_t) hi) << 32) + lo; | 167 | return (((cycle_t) hi) << 32) + lo; |
168 | } | 168 | } |
169 | |||
170 | void gic_start_count(void) | ||
171 | { | ||
172 | u32 gicconfig; | ||
173 | |||
174 | /* Start the counter */ | ||
175 | gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG)); | ||
176 | gicconfig &= ~(1 << GIC_SH_CONFIG_COUNTSTOP_SHF); | ||
177 | gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); | ||
178 | } | ||
179 | |||
180 | void gic_stop_count(void) | ||
181 | { | ||
182 | u32 gicconfig; | ||
183 | |||
184 | /* Stop the counter */ | ||
185 | gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG)); | ||
186 | gicconfig |= 1 << GIC_SH_CONFIG_COUNTSTOP_SHF; | ||
187 | gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); | ||
188 | } | ||
189 | |||
169 | #endif | 190 | #endif |
170 | 191 | ||
171 | static bool gic_local_irq_is_routable(int intr) | 192 | static bool gic_local_irq_is_routable(int intr) |
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 384e6ed61d7c..cdf80b7794cd 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/clk.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
@@ -29,15 +30,26 @@ | |||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/platform_data/irq-renesas-irqc.h> | 32 | #include <linux/platform_data/irq-renesas-irqc.h> |
33 | #include <linux/pm_runtime.h> | ||
32 | 34 | ||
33 | #define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */ | 35 | #define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */ |
34 | 36 | ||
35 | #define IRQC_REQ_STS 0x00 | 37 | #define IRQC_REQ_STS 0x00 /* Interrupt Request Status Register */ |
36 | #define IRQC_EN_STS 0x04 | 38 | #define IRQC_EN_STS 0x04 /* Interrupt Enable Status Register */ |
37 | #define IRQC_EN_SET 0x08 | 39 | #define IRQC_EN_SET 0x08 /* Interrupt Enable Set Register */ |
38 | #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10)) | 40 | #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10)) |
39 | #define DETECT_STATUS 0x100 | 41 | /* SYS-CPU vs. RT-CPU */ |
42 | #define DETECT_STATUS 0x100 /* IRQn Detect Status Register */ | ||
43 | #define MONITOR 0x104 /* IRQn Signal Level Monitor Register */ | ||
44 | #define HLVL_STS 0x108 /* IRQn High Level Detect Status Register */ | ||
45 | #define LLVL_STS 0x10c /* IRQn Low Level Detect Status Register */ | ||
46 | #define S_R_EDGE_STS 0x110 /* IRQn Sync Rising Edge Detect Status Reg. */ | ||
47 | #define S_F_EDGE_STS 0x114 /* IRQn Sync Falling Edge Detect Status Reg. */ | ||
48 | #define A_R_EDGE_STS 0x118 /* IRQn Async Rising Edge Detect Status Reg. */ | ||
49 | #define A_F_EDGE_STS 0x11c /* IRQn Async Falling Edge Detect Status Reg. */ | ||
50 | #define CHTEN_STS 0x120 /* Chattering Reduction Status Register */ | ||
40 | #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04)) | 51 | #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04)) |
52 | /* IRQn Configuration Register */ | ||
41 | 53 | ||
42 | struct irqc_irq { | 54 | struct irqc_irq { |
43 | int hw_irq; | 55 | int hw_irq; |
@@ -55,6 +67,7 @@ struct irqc_priv { | |||
55 | struct platform_device *pdev; | 67 | struct platform_device *pdev; |
56 | struct irq_chip irq_chip; | 68 | struct irq_chip irq_chip; |
57 | struct irq_domain *irq_domain; | 69 | struct irq_domain *irq_domain; |
70 | struct clk *clk; | ||
58 | }; | 71 | }; |
59 | 72 | ||
60 | static void irqc_dbg(struct irqc_irq *i, char *str) | 73 | static void irqc_dbg(struct irqc_irq *i, char *str) |
@@ -94,7 +107,7 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type) | |||
94 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | 107 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); |
95 | int hw_irq = irqd_to_hwirq(d); | 108 | int hw_irq = irqd_to_hwirq(d); |
96 | unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK]; | 109 | unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK]; |
97 | unsigned long tmp; | 110 | u32 tmp; |
98 | 111 | ||
99 | irqc_dbg(&p->irq[hw_irq], "sense"); | 112 | irqc_dbg(&p->irq[hw_irq], "sense"); |
100 | 113 | ||
@@ -108,11 +121,26 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type) | |||
108 | return 0; | 121 | return 0; |
109 | } | 122 | } |
110 | 123 | ||
124 | static int irqc_irq_set_wake(struct irq_data *d, unsigned int on) | ||
125 | { | ||
126 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
127 | |||
128 | if (!p->clk) | ||
129 | return 0; | ||
130 | |||
131 | if (on) | ||
132 | clk_enable(p->clk); | ||
133 | else | ||
134 | clk_disable(p->clk); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
111 | static irqreturn_t irqc_irq_handler(int irq, void *dev_id) | 139 | static irqreturn_t irqc_irq_handler(int irq, void *dev_id) |
112 | { | 140 | { |
113 | struct irqc_irq *i = dev_id; | 141 | struct irqc_irq *i = dev_id; |
114 | struct irqc_priv *p = i->p; | 142 | struct irqc_priv *p = i->p; |
115 | unsigned long bit = BIT(i->hw_irq); | 143 | u32 bit = BIT(i->hw_irq); |
116 | 144 | ||
117 | irqc_dbg(i, "demux1"); | 145 | irqc_dbg(i, "demux1"); |
118 | 146 | ||
@@ -170,6 +198,15 @@ static int irqc_probe(struct platform_device *pdev) | |||
170 | p->pdev = pdev; | 198 | p->pdev = pdev; |
171 | platform_set_drvdata(pdev, p); | 199 | platform_set_drvdata(pdev, p); |
172 | 200 | ||
201 | p->clk = devm_clk_get(&pdev->dev, NULL); | ||
202 | if (IS_ERR(p->clk)) { | ||
203 | dev_warn(&pdev->dev, "unable to get clock\n"); | ||
204 | p->clk = NULL; | ||
205 | } | ||
206 | |||
207 | pm_runtime_enable(&pdev->dev); | ||
208 | pm_runtime_get_sync(&pdev->dev); | ||
209 | |||
173 | /* get hold of manadatory IOMEM */ | 210 | /* get hold of manadatory IOMEM */ |
174 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 211 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
175 | if (!io) { | 212 | if (!io) { |
@@ -210,7 +247,8 @@ static int irqc_probe(struct platform_device *pdev) | |||
210 | irq_chip->irq_mask = irqc_irq_disable; | 247 | irq_chip->irq_mask = irqc_irq_disable; |
211 | irq_chip->irq_unmask = irqc_irq_enable; | 248 | irq_chip->irq_unmask = irqc_irq_enable; |
212 | irq_chip->irq_set_type = irqc_irq_set_type; | 249 | irq_chip->irq_set_type = irqc_irq_set_type; |
213 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; | 250 | irq_chip->irq_set_wake = irqc_irq_set_wake; |
251 | irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND; | ||
214 | 252 | ||
215 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | 253 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, |
216 | p->number_of_irqs, | 254 | p->number_of_irqs, |
@@ -250,6 +288,8 @@ err3: | |||
250 | err2: | 288 | err2: |
251 | iounmap(p->iomem); | 289 | iounmap(p->iomem); |
252 | err1: | 290 | err1: |
291 | pm_runtime_put(&pdev->dev); | ||
292 | pm_runtime_disable(&pdev->dev); | ||
253 | kfree(p); | 293 | kfree(p); |
254 | err0: | 294 | err0: |
255 | return ret; | 295 | return ret; |
@@ -265,6 +305,8 @@ static int irqc_remove(struct platform_device *pdev) | |||
265 | 305 | ||
266 | irq_domain_remove(p->irq_domain); | 306 | irq_domain_remove(p->irq_domain); |
267 | iounmap(p->iomem); | 307 | iounmap(p->iomem); |
308 | pm_runtime_put(&pdev->dev); | ||
309 | pm_runtime_disable(&pdev->dev); | ||
268 | kfree(p); | 310 | kfree(p); |
269 | return 0; | 311 | return 0; |
270 | } | 312 | } |
diff --git a/drivers/irqchip/irq-st.c b/drivers/irqchip/irq-st.c new file mode 100644 index 000000000000..9af48a85c16f --- /dev/null +++ b/drivers/irqchip/irq-st.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics – All Rights Reserved | ||
3 | * | ||
4 | * Author: Lee Jones <lee.jones@linaro.org> | ||
5 | * | ||
6 | * This is a re-write of Christophe Kerello's PMU driver. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <dt-bindings/interrupt-controller/irq-st.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/mfd/syscon.h> | ||
16 | #include <linux/of_device.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #define STIH415_SYSCFG_642 0x0a8 | ||
22 | #define STIH416_SYSCFG_7543 0x87c | ||
23 | #define STIH407_SYSCFG_5102 0x198 | ||
24 | #define STID127_SYSCFG_734 0x088 | ||
25 | |||
26 | #define ST_A9_IRQ_MASK 0x001FFFFF | ||
27 | #define ST_A9_IRQ_MAX_CHANS 2 | ||
28 | |||
29 | #define ST_A9_IRQ_EN_CTI_0 BIT(0) | ||
30 | #define ST_A9_IRQ_EN_CTI_1 BIT(1) | ||
31 | #define ST_A9_IRQ_EN_PMU_0 BIT(2) | ||
32 | #define ST_A9_IRQ_EN_PMU_1 BIT(3) | ||
33 | #define ST_A9_IRQ_EN_PL310_L2 BIT(4) | ||
34 | #define ST_A9_IRQ_EN_EXT_0 BIT(5) | ||
35 | #define ST_A9_IRQ_EN_EXT_1 BIT(6) | ||
36 | #define ST_A9_IRQ_EN_EXT_2 BIT(7) | ||
37 | |||
38 | #define ST_A9_FIQ_N_SEL(dev, chan) (dev << (8 + (chan * 3))) | ||
39 | #define ST_A9_IRQ_N_SEL(dev, chan) (dev << (14 + (chan * 3))) | ||
40 | #define ST_A9_EXTIRQ_INV_SEL(dev) (dev << 20) | ||
41 | |||
42 | struct st_irq_syscfg { | ||
43 | struct regmap *regmap; | ||
44 | unsigned int syscfg; | ||
45 | unsigned int config; | ||
46 | bool ext_inverted; | ||
47 | }; | ||
48 | |||
49 | static const struct of_device_id st_irq_syscfg_match[] = { | ||
50 | { | ||
51 | .compatible = "st,stih415-irq-syscfg", | ||
52 | .data = (void *)STIH415_SYSCFG_642, | ||
53 | }, | ||
54 | { | ||
55 | .compatible = "st,stih416-irq-syscfg", | ||
56 | .data = (void *)STIH416_SYSCFG_7543, | ||
57 | }, | ||
58 | { | ||
59 | .compatible = "st,stih407-irq-syscfg", | ||
60 | .data = (void *)STIH407_SYSCFG_5102, | ||
61 | }, | ||
62 | { | ||
63 | .compatible = "st,stid127-irq-syscfg", | ||
64 | .data = (void *)STID127_SYSCFG_734, | ||
65 | }, | ||
66 | {} | ||
67 | }; | ||
68 | |||
69 | static int st_irq_xlate(struct platform_device *pdev, | ||
70 | int device, int channel, bool irq) | ||
71 | { | ||
72 | struct st_irq_syscfg *ddata = dev_get_drvdata(&pdev->dev); | ||
73 | |||
74 | /* Set the device enable bit. */ | ||
75 | switch (device) { | ||
76 | case ST_IRQ_SYSCFG_EXT_0: | ||
77 | ddata->config |= ST_A9_IRQ_EN_EXT_0; | ||
78 | break; | ||
79 | case ST_IRQ_SYSCFG_EXT_1: | ||
80 | ddata->config |= ST_A9_IRQ_EN_EXT_1; | ||
81 | break; | ||
82 | case ST_IRQ_SYSCFG_EXT_2: | ||
83 | ddata->config |= ST_A9_IRQ_EN_EXT_2; | ||
84 | break; | ||
85 | case ST_IRQ_SYSCFG_CTI_0: | ||
86 | ddata->config |= ST_A9_IRQ_EN_CTI_0; | ||
87 | break; | ||
88 | case ST_IRQ_SYSCFG_CTI_1: | ||
89 | ddata->config |= ST_A9_IRQ_EN_CTI_1; | ||
90 | break; | ||
91 | case ST_IRQ_SYSCFG_PMU_0: | ||
92 | ddata->config |= ST_A9_IRQ_EN_PMU_0; | ||
93 | break; | ||
94 | case ST_IRQ_SYSCFG_PMU_1: | ||
95 | ddata->config |= ST_A9_IRQ_EN_PMU_1; | ||
96 | break; | ||
97 | case ST_IRQ_SYSCFG_pl310_L2: | ||
98 | ddata->config |= ST_A9_IRQ_EN_PL310_L2; | ||
99 | break; | ||
100 | case ST_IRQ_SYSCFG_DISABLED: | ||
101 | return 0; | ||
102 | default: | ||
103 | dev_err(&pdev->dev, "Unrecognised device %d\n", device); | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | |||
107 | /* Select IRQ/FIQ channel for device. */ | ||
108 | ddata->config |= irq ? | ||
109 | ST_A9_IRQ_N_SEL(device, channel) : | ||
110 | ST_A9_FIQ_N_SEL(device, channel); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int st_irq_syscfg_enable(struct platform_device *pdev) | ||
116 | { | ||
117 | struct device_node *np = pdev->dev.of_node; | ||
118 | struct st_irq_syscfg *ddata = dev_get_drvdata(&pdev->dev); | ||
119 | int channels, ret, i; | ||
120 | u32 device, invert; | ||
121 | |||
122 | channels = of_property_count_u32_elems(np, "st,irq-device"); | ||
123 | if (channels != ST_A9_IRQ_MAX_CHANS) { | ||
124 | dev_err(&pdev->dev, "st,enable-irq-device must have 2 elems\n"); | ||
125 | return -EINVAL; | ||
126 | } | ||
127 | |||
128 | channels = of_property_count_u32_elems(np, "st,fiq-device"); | ||
129 | if (channels != ST_A9_IRQ_MAX_CHANS) { | ||
130 | dev_err(&pdev->dev, "st,enable-fiq-device must have 2 elems\n"); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | for (i = 0; i < ST_A9_IRQ_MAX_CHANS; i++) { | ||
135 | of_property_read_u32_index(np, "st,irq-device", i, &device); | ||
136 | |||
137 | ret = st_irq_xlate(pdev, device, i, true); | ||
138 | if (ret) | ||
139 | return ret; | ||
140 | |||
141 | of_property_read_u32_index(np, "st,fiq-device", i, &device); | ||
142 | |||
143 | ret = st_irq_xlate(pdev, device, i, false); | ||
144 | if (ret) | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | /* External IRQs may be inverted. */ | ||
149 | of_property_read_u32(np, "st,invert-ext", &invert); | ||
150 | ddata->config |= ST_A9_EXTIRQ_INV_SEL(invert); | ||
151 | |||
152 | return regmap_update_bits(ddata->regmap, ddata->syscfg, | ||
153 | ST_A9_IRQ_MASK, ddata->config); | ||
154 | } | ||
155 | |||
156 | static int st_irq_syscfg_probe(struct platform_device *pdev) | ||
157 | { | ||
158 | struct device_node *np = pdev->dev.of_node; | ||
159 | const struct of_device_id *match; | ||
160 | struct st_irq_syscfg *ddata; | ||
161 | |||
162 | ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); | ||
163 | if (!ddata) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | match = of_match_device(st_irq_syscfg_match, &pdev->dev); | ||
167 | if (!match) | ||
168 | return -ENODEV; | ||
169 | |||
170 | ddata->syscfg = (unsigned int)match->data; | ||
171 | |||
172 | ddata->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
173 | if (IS_ERR(ddata->regmap)) { | ||
174 | dev_err(&pdev->dev, "syscfg phandle missing\n"); | ||
175 | return PTR_ERR(ddata->regmap); | ||
176 | } | ||
177 | |||
178 | dev_set_drvdata(&pdev->dev, ddata); | ||
179 | |||
180 | return st_irq_syscfg_enable(pdev); | ||
181 | } | ||
182 | |||
183 | static int st_irq_syscfg_resume(struct device *dev) | ||
184 | { | ||
185 | struct st_irq_syscfg *ddata = dev_get_drvdata(dev); | ||
186 | |||
187 | return regmap_update_bits(ddata->regmap, ddata->syscfg, | ||
188 | ST_A9_IRQ_MASK, ddata->config); | ||
189 | } | ||
190 | |||
191 | static SIMPLE_DEV_PM_OPS(st_irq_syscfg_pm_ops, NULL, st_irq_syscfg_resume); | ||
192 | |||
193 | static struct platform_driver st_irq_syscfg_driver = { | ||
194 | .driver = { | ||
195 | .name = "st_irq_syscfg", | ||
196 | .pm = &st_irq_syscfg_pm_ops, | ||
197 | .of_match_table = st_irq_syscfg_match, | ||
198 | }, | ||
199 | .probe = st_irq_syscfg_probe, | ||
200 | }; | ||
201 | |||
202 | static int __init st_irq_syscfg_init(void) | ||
203 | { | ||
204 | return platform_driver_register(&st_irq_syscfg_driver); | ||
205 | } | ||
206 | core_initcall(st_irq_syscfg_init); | ||
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c new file mode 100644 index 000000000000..51c485d9a877 --- /dev/null +++ b/drivers/irqchip/irq-tegra.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * Driver code for Tegra's Legacy Interrupt Controller | ||
3 | * | ||
4 | * Author: Marc Zyngier <marc.zyngier@arm.com> | ||
5 | * | ||
6 | * Heavily based on the original arch/arm/mach-tegra/irq.c code: | ||
7 | * Copyright (C) 2011 Google, Inc. | ||
8 | * | ||
9 | * Author: | ||
10 | * Colin Cross <ccross@android.com> | ||
11 | * | ||
12 | * Copyright (C) 2010,2013, NVIDIA Corporation | ||
13 | * | ||
14 | * This software is licensed under the terms of the GNU General Public | ||
15 | * License version 2, as published by the Free Software Foundation, and | ||
16 | * may be copied, distributed, and modified under those terms. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | #include <linux/of_address.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/syscore_ops.h> | ||
31 | |||
32 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
33 | |||
34 | #include "irqchip.h" | ||
35 | |||
36 | #define ICTLR_CPU_IEP_VFIQ 0x08 | ||
37 | #define ICTLR_CPU_IEP_FIR 0x14 | ||
38 | #define ICTLR_CPU_IEP_FIR_SET 0x18 | ||
39 | #define ICTLR_CPU_IEP_FIR_CLR 0x1c | ||
40 | |||
41 | #define ICTLR_CPU_IER 0x20 | ||
42 | #define ICTLR_CPU_IER_SET 0x24 | ||
43 | #define ICTLR_CPU_IER_CLR 0x28 | ||
44 | #define ICTLR_CPU_IEP_CLASS 0x2C | ||
45 | |||
46 | #define ICTLR_COP_IER 0x30 | ||
47 | #define ICTLR_COP_IER_SET 0x34 | ||
48 | #define ICTLR_COP_IER_CLR 0x38 | ||
49 | #define ICTLR_COP_IEP_CLASS 0x3c | ||
50 | |||
51 | #define TEGRA_MAX_NUM_ICTLRS 6 | ||
52 | |||
53 | static unsigned int num_ictlrs; | ||
54 | |||
55 | struct tegra_ictlr_soc { | ||
56 | unsigned int num_ictlrs; | ||
57 | }; | ||
58 | |||
59 | static const struct tegra_ictlr_soc tegra20_ictlr_soc = { | ||
60 | .num_ictlrs = 4, | ||
61 | }; | ||
62 | |||
63 | static const struct tegra_ictlr_soc tegra30_ictlr_soc = { | ||
64 | .num_ictlrs = 5, | ||
65 | }; | ||
66 | |||
67 | static const struct tegra_ictlr_soc tegra210_ictlr_soc = { | ||
68 | .num_ictlrs = 6, | ||
69 | }; | ||
70 | |||
71 | static const struct of_device_id ictlr_matches[] = { | ||
72 | { .compatible = "nvidia,tegra210-ictlr", .data = &tegra210_ictlr_soc }, | ||
73 | { .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc }, | ||
74 | { .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc }, | ||
75 | { } | ||
76 | }; | ||
77 | |||
78 | struct tegra_ictlr_info { | ||
79 | void __iomem *base[TEGRA_MAX_NUM_ICTLRS]; | ||
80 | #ifdef CONFIG_PM_SLEEP | ||
81 | u32 cop_ier[TEGRA_MAX_NUM_ICTLRS]; | ||
82 | u32 cop_iep[TEGRA_MAX_NUM_ICTLRS]; | ||
83 | u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS]; | ||
84 | u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS]; | ||
85 | |||
86 | u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS]; | ||
87 | #endif | ||
88 | }; | ||
89 | |||
90 | static struct tegra_ictlr_info *lic; | ||
91 | |||
92 | static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg) | ||
93 | { | ||
94 | void __iomem *base = d->chip_data; | ||
95 | u32 mask; | ||
96 | |||
97 | mask = BIT(d->hwirq % 32); | ||
98 | writel_relaxed(mask, base + reg); | ||
99 | } | ||
100 | |||
101 | static void tegra_mask(struct irq_data *d) | ||
102 | { | ||
103 | tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR); | ||
104 | irq_chip_mask_parent(d); | ||
105 | } | ||
106 | |||
107 | static void tegra_unmask(struct irq_data *d) | ||
108 | { | ||
109 | tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET); | ||
110 | irq_chip_unmask_parent(d); | ||
111 | } | ||
112 | |||
113 | static void tegra_eoi(struct irq_data *d) | ||
114 | { | ||
115 | tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR); | ||
116 | irq_chip_eoi_parent(d); | ||
117 | } | ||
118 | |||
119 | static int tegra_retrigger(struct irq_data *d) | ||
120 | { | ||
121 | tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET); | ||
122 | return irq_chip_retrigger_hierarchy(d); | ||
123 | } | ||
124 | |||
125 | #ifdef CONFIG_PM_SLEEP | ||
126 | static int tegra_set_wake(struct irq_data *d, unsigned int enable) | ||
127 | { | ||
128 | u32 irq = d->hwirq; | ||
129 | u32 index, mask; | ||
130 | |||
131 | index = (irq / 32); | ||
132 | mask = BIT(irq % 32); | ||
133 | if (enable) | ||
134 | lic->ictlr_wake_mask[index] |= mask; | ||
135 | else | ||
136 | lic->ictlr_wake_mask[index] &= ~mask; | ||
137 | |||
138 | /* | ||
139 | * Do *not* call into the parent, as the GIC doesn't have any | ||
140 | * wake-up facility... | ||
141 | */ | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int tegra_ictlr_suspend(void) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | unsigned int i; | ||
149 | |||
150 | local_irq_save(flags); | ||
151 | for (i = 0; i < num_ictlrs; i++) { | ||
152 | void __iomem *ictlr = lic->base[i]; | ||
153 | |||
154 | /* Save interrupt state */ | ||
155 | lic->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER); | ||
156 | lic->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS); | ||
157 | lic->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER); | ||
158 | lic->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS); | ||
159 | |||
160 | /* Disable COP interrupts */ | ||
161 | writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
162 | |||
163 | /* Disable CPU interrupts */ | ||
164 | writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
165 | |||
166 | /* Enable the wakeup sources of ictlr */ | ||
167 | writel_relaxed(lic->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET); | ||
168 | } | ||
169 | local_irq_restore(flags); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void tegra_ictlr_resume(void) | ||
175 | { | ||
176 | unsigned long flags; | ||
177 | unsigned int i; | ||
178 | |||
179 | local_irq_save(flags); | ||
180 | for (i = 0; i < num_ictlrs; i++) { | ||
181 | void __iomem *ictlr = lic->base[i]; | ||
182 | |||
183 | writel_relaxed(lic->cpu_iep[i], | ||
184 | ictlr + ICTLR_CPU_IEP_CLASS); | ||
185 | writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
186 | writel_relaxed(lic->cpu_ier[i], | ||
187 | ictlr + ICTLR_CPU_IER_SET); | ||
188 | writel_relaxed(lic->cop_iep[i], | ||
189 | ictlr + ICTLR_COP_IEP_CLASS); | ||
190 | writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
191 | writel_relaxed(lic->cop_ier[i], | ||
192 | ictlr + ICTLR_COP_IER_SET); | ||
193 | } | ||
194 | local_irq_restore(flags); | ||
195 | } | ||
196 | |||
197 | static struct syscore_ops tegra_ictlr_syscore_ops = { | ||
198 | .suspend = tegra_ictlr_suspend, | ||
199 | .resume = tegra_ictlr_resume, | ||
200 | }; | ||
201 | |||
202 | static void tegra_ictlr_syscore_init(void) | ||
203 | { | ||
204 | register_syscore_ops(&tegra_ictlr_syscore_ops); | ||
205 | } | ||
206 | #else | ||
207 | #define tegra_set_wake NULL | ||
208 | static inline void tegra_ictlr_syscore_init(void) {} | ||
209 | #endif | ||
210 | |||
211 | static struct irq_chip tegra_ictlr_chip = { | ||
212 | .name = "LIC", | ||
213 | .irq_eoi = tegra_eoi, | ||
214 | .irq_mask = tegra_mask, | ||
215 | .irq_unmask = tegra_unmask, | ||
216 | .irq_retrigger = tegra_retrigger, | ||
217 | .irq_set_wake = tegra_set_wake, | ||
218 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
219 | #ifdef CONFIG_SMP | ||
220 | .irq_set_affinity = irq_chip_set_affinity_parent, | ||
221 | #endif | ||
222 | }; | ||
223 | |||
224 | static int tegra_ictlr_domain_xlate(struct irq_domain *domain, | ||
225 | struct device_node *controller, | ||
226 | const u32 *intspec, | ||
227 | unsigned int intsize, | ||
228 | unsigned long *out_hwirq, | ||
229 | unsigned int *out_type) | ||
230 | { | ||
231 | if (domain->of_node != controller) | ||
232 | return -EINVAL; /* Shouldn't happen, really... */ | ||
233 | if (intsize != 3) | ||
234 | return -EINVAL; /* Not GIC compliant */ | ||
235 | if (intspec[0] != GIC_SPI) | ||
236 | return -EINVAL; /* No PPI should point to this domain */ | ||
237 | |||
238 | *out_hwirq = intspec[1]; | ||
239 | *out_type = intspec[2]; | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int tegra_ictlr_domain_alloc(struct irq_domain *domain, | ||
244 | unsigned int virq, | ||
245 | unsigned int nr_irqs, void *data) | ||
246 | { | ||
247 | struct of_phandle_args *args = data; | ||
248 | struct of_phandle_args parent_args; | ||
249 | struct tegra_ictlr_info *info = domain->host_data; | ||
250 | irq_hw_number_t hwirq; | ||
251 | unsigned int i; | ||
252 | |||
253 | if (args->args_count != 3) | ||
254 | return -EINVAL; /* Not GIC compliant */ | ||
255 | if (args->args[0] != GIC_SPI) | ||
256 | return -EINVAL; /* No PPI should point to this domain */ | ||
257 | |||
258 | hwirq = args->args[1]; | ||
259 | if (hwirq >= (num_ictlrs * 32)) | ||
260 | return -EINVAL; | ||
261 | |||
262 | for (i = 0; i < nr_irqs; i++) { | ||
263 | int ictlr = (hwirq + i) / 32; | ||
264 | |||
265 | irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, | ||
266 | &tegra_ictlr_chip, | ||
267 | &info->base[ictlr]); | ||
268 | } | ||
269 | |||
270 | parent_args = *args; | ||
271 | parent_args.np = domain->parent->of_node; | ||
272 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args); | ||
273 | } | ||
274 | |||
275 | static void tegra_ictlr_domain_free(struct irq_domain *domain, | ||
276 | unsigned int virq, | ||
277 | unsigned int nr_irqs) | ||
278 | { | ||
279 | unsigned int i; | ||
280 | |||
281 | for (i = 0; i < nr_irqs; i++) { | ||
282 | struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); | ||
283 | irq_domain_reset_irq_data(d); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | static const struct irq_domain_ops tegra_ictlr_domain_ops = { | ||
288 | .xlate = tegra_ictlr_domain_xlate, | ||
289 | .alloc = tegra_ictlr_domain_alloc, | ||
290 | .free = tegra_ictlr_domain_free, | ||
291 | }; | ||
292 | |||
293 | static int __init tegra_ictlr_init(struct device_node *node, | ||
294 | struct device_node *parent) | ||
295 | { | ||
296 | struct irq_domain *parent_domain, *domain; | ||
297 | const struct of_device_id *match; | ||
298 | const struct tegra_ictlr_soc *soc; | ||
299 | unsigned int i; | ||
300 | int err; | ||
301 | |||
302 | if (!parent) { | ||
303 | pr_err("%s: no parent, giving up\n", node->full_name); | ||
304 | return -ENODEV; | ||
305 | } | ||
306 | |||
307 | parent_domain = irq_find_host(parent); | ||
308 | if (!parent_domain) { | ||
309 | pr_err("%s: unable to obtain parent domain\n", node->full_name); | ||
310 | return -ENXIO; | ||
311 | } | ||
312 | |||
313 | match = of_match_node(ictlr_matches, node); | ||
314 | if (!match) /* Should never happen... */ | ||
315 | return -ENODEV; | ||
316 | |||
317 | soc = match->data; | ||
318 | |||
319 | lic = kzalloc(sizeof(*lic), GFP_KERNEL); | ||
320 | if (!lic) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) { | ||
324 | void __iomem *base; | ||
325 | |||
326 | base = of_iomap(node, i); | ||
327 | if (!base) | ||
328 | break; | ||
329 | |||
330 | lic->base[i] = base; | ||
331 | |||
332 | /* Disable all interrupts */ | ||
333 | writel_relaxed(~0UL, base + ICTLR_CPU_IER_CLR); | ||
334 | /* All interrupts target IRQ */ | ||
335 | writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS); | ||
336 | |||
337 | num_ictlrs++; | ||
338 | } | ||
339 | |||
340 | if (!num_ictlrs) { | ||
341 | pr_err("%s: no valid regions, giving up\n", node->full_name); | ||
342 | err = -ENOMEM; | ||
343 | goto out_free; | ||
344 | } | ||
345 | |||
346 | WARN(num_ictlrs != soc->num_ictlrs, | ||
347 | "%s: Found %u interrupt controllers in DT; expected %u.\n", | ||
348 | node->full_name, num_ictlrs, soc->num_ictlrs); | ||
349 | |||
350 | |||
351 | domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32, | ||
352 | node, &tegra_ictlr_domain_ops, | ||
353 | lic); | ||
354 | if (!domain) { | ||
355 | pr_err("%s: failed to allocated domain\n", node->full_name); | ||
356 | err = -ENOMEM; | ||
357 | goto out_unmap; | ||
358 | } | ||
359 | |||
360 | tegra_ictlr_syscore_init(); | ||
361 | |||
362 | pr_info("%s: %d interrupts forwarded to %s\n", | ||
363 | node->full_name, num_ictlrs * 32, parent->full_name); | ||
364 | |||
365 | return 0; | ||
366 | |||
367 | out_unmap: | ||
368 | for (i = 0; i < num_ictlrs; i++) | ||
369 | iounmap(lic->base[i]); | ||
370 | out_free: | ||
371 | kfree(lic); | ||
372 | return err; | ||
373 | } | ||
374 | |||
375 | IRQCHIP_DECLARE(tegra20_ictlr, "nvidia,tegra20-ictlr", tegra_ictlr_init); | ||
376 | IRQCHIP_DECLARE(tegra30_ictlr, "nvidia,tegra30-ictlr", tegra_ictlr_init); | ||
377 | IRQCHIP_DECLARE(tegra210_ictlr, "nvidia,tegra210-ictlr", tegra_ictlr_init); | ||
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c new file mode 100644 index 000000000000..9521057d4744 --- /dev/null +++ b/drivers/irqchip/irq-vf610-mscm-ir.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2015 Toradex AG | ||
3 | * Author: Stefan Agner <stefan@agner.ch> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * | ||
10 | * IRQ chip driver for MSCM interrupt router available on Vybrid SoC's. | ||
11 | * The interrupt router is between the CPU's interrupt controller and the | ||
12 | * peripheral. The router allows to route the peripheral interrupts to | ||
13 | * one of the two available CPU's on Vybrid VF6xx SoC's (Cortex-A5 or | ||
14 | * Cortex-M4). The router will be configured transparently on a IRQ | ||
15 | * request. | ||
16 | * | ||
17 | * o All peripheral interrupts of the Vybrid SoC can be routed to | ||
18 | * CPU 0, CPU 1 or both. The routing is useful for dual-core | ||
19 | * variants of Vybrid SoC such as VF6xx. This driver routes the | ||
20 | * requested interrupt to the CPU currently running on. | ||
21 | * | ||
22 | * o It is required to setup the interrupt router even on single-core | ||
23 | * variants of Vybrid. | ||
24 | */ | ||
25 | |||
26 | #include <linux/cpu_pm.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/irqdomain.h> | ||
30 | #include <linux/mfd/syscon.h> | ||
31 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
32 | #include <linux/of.h> | ||
33 | #include <linux/of_address.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/regmap.h> | ||
36 | |||
37 | #include "irqchip.h" | ||
38 | |||
39 | #define MSCM_CPxNUM 0x4 | ||
40 | |||
41 | #define MSCM_IRSPRC(n) (0x80 + 2 * (n)) | ||
42 | #define MSCM_IRSPRC_CPEN_MASK 0x3 | ||
43 | |||
44 | #define MSCM_IRSPRC_NUM 112 | ||
45 | |||
46 | struct vf610_mscm_ir_chip_data { | ||
47 | void __iomem *mscm_ir_base; | ||
48 | u16 cpu_mask; | ||
49 | u16 saved_irsprc[MSCM_IRSPRC_NUM]; | ||
50 | }; | ||
51 | |||
52 | static struct vf610_mscm_ir_chip_data *mscm_ir_data; | ||
53 | |||
54 | static inline void vf610_mscm_ir_save(struct vf610_mscm_ir_chip_data *data) | ||
55 | { | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < MSCM_IRSPRC_NUM; i++) | ||
59 | data->saved_irsprc[i] = readw_relaxed(data->mscm_ir_base + MSCM_IRSPRC(i)); | ||
60 | } | ||
61 | |||
62 | static inline void vf610_mscm_ir_restore(struct vf610_mscm_ir_chip_data *data) | ||
63 | { | ||
64 | int i; | ||
65 | |||
66 | for (i = 0; i < MSCM_IRSPRC_NUM; i++) | ||
67 | writew_relaxed(data->saved_irsprc[i], data->mscm_ir_base + MSCM_IRSPRC(i)); | ||
68 | } | ||
69 | |||
70 | static int vf610_mscm_ir_notifier(struct notifier_block *self, | ||
71 | unsigned long cmd, void *v) | ||
72 | { | ||
73 | switch (cmd) { | ||
74 | case CPU_CLUSTER_PM_ENTER: | ||
75 | vf610_mscm_ir_save(mscm_ir_data); | ||
76 | break; | ||
77 | case CPU_CLUSTER_PM_ENTER_FAILED: | ||
78 | case CPU_CLUSTER_PM_EXIT: | ||
79 | vf610_mscm_ir_restore(mscm_ir_data); | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | return NOTIFY_OK; | ||
84 | } | ||
85 | |||
86 | static struct notifier_block mscm_ir_notifier_block = { | ||
87 | .notifier_call = vf610_mscm_ir_notifier, | ||
88 | }; | ||
89 | |||
90 | static void vf610_mscm_ir_enable(struct irq_data *data) | ||
91 | { | ||
92 | irq_hw_number_t hwirq = data->hwirq; | ||
93 | struct vf610_mscm_ir_chip_data *chip_data = data->chip_data; | ||
94 | u16 irsprc; | ||
95 | |||
96 | irsprc = readw_relaxed(chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); | ||
97 | irsprc &= MSCM_IRSPRC_CPEN_MASK; | ||
98 | |||
99 | WARN_ON(irsprc & ~chip_data->cpu_mask); | ||
100 | |||
101 | writew_relaxed(chip_data->cpu_mask, | ||
102 | chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); | ||
103 | |||
104 | irq_chip_unmask_parent(data); | ||
105 | } | ||
106 | |||
107 | static void vf610_mscm_ir_disable(struct irq_data *data) | ||
108 | { | ||
109 | irq_hw_number_t hwirq = data->hwirq; | ||
110 | struct vf610_mscm_ir_chip_data *chip_data = data->chip_data; | ||
111 | |||
112 | writew_relaxed(0x0, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); | ||
113 | |||
114 | irq_chip_mask_parent(data); | ||
115 | } | ||
116 | |||
117 | static struct irq_chip vf610_mscm_ir_irq_chip = { | ||
118 | .name = "mscm-ir", | ||
119 | .irq_mask = irq_chip_mask_parent, | ||
120 | .irq_unmask = irq_chip_unmask_parent, | ||
121 | .irq_eoi = irq_chip_eoi_parent, | ||
122 | .irq_enable = vf610_mscm_ir_enable, | ||
123 | .irq_disable = vf610_mscm_ir_disable, | ||
124 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
125 | .irq_set_affinity = irq_chip_set_affinity_parent, | ||
126 | }; | ||
127 | |||
128 | static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
129 | unsigned int nr_irqs, void *arg) | ||
130 | { | ||
131 | int i; | ||
132 | irq_hw_number_t hwirq; | ||
133 | struct of_phandle_args *irq_data = arg; | ||
134 | struct of_phandle_args gic_data; | ||
135 | |||
136 | if (irq_data->args_count != 2) | ||
137 | return -EINVAL; | ||
138 | |||
139 | hwirq = irq_data->args[0]; | ||
140 | for (i = 0; i < nr_irqs; i++) | ||
141 | irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, | ||
142 | &vf610_mscm_ir_irq_chip, | ||
143 | domain->host_data); | ||
144 | |||
145 | gic_data.np = domain->parent->of_node; | ||
146 | gic_data.args_count = 3; | ||
147 | gic_data.args[0] = GIC_SPI; | ||
148 | gic_data.args[1] = irq_data->args[0]; | ||
149 | gic_data.args[2] = irq_data->args[1]; | ||
150 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); | ||
151 | } | ||
152 | |||
153 | static const struct irq_domain_ops mscm_irq_domain_ops = { | ||
154 | .xlate = irq_domain_xlate_twocell, | ||
155 | .alloc = vf610_mscm_ir_domain_alloc, | ||
156 | .free = irq_domain_free_irqs_common, | ||
157 | }; | ||
158 | |||
159 | static int __init vf610_mscm_ir_of_init(struct device_node *node, | ||
160 | struct device_node *parent) | ||
161 | { | ||
162 | struct irq_domain *domain, *domain_parent; | ||
163 | struct regmap *mscm_cp_regmap; | ||
164 | int ret, cpuid; | ||
165 | |||
166 | domain_parent = irq_find_host(parent); | ||
167 | if (!domain_parent) { | ||
168 | pr_err("vf610_mscm_ir: interrupt-parent not found\n"); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | mscm_ir_data = kzalloc(sizeof(*mscm_ir_data), GFP_KERNEL); | ||
173 | if (!mscm_ir_data) | ||
174 | return -ENOMEM; | ||
175 | |||
176 | mscm_ir_data->mscm_ir_base = of_io_request_and_map(node, 0, "mscm-ir"); | ||
177 | |||
178 | if (!mscm_ir_data->mscm_ir_base) { | ||
179 | pr_err("vf610_mscm_ir: unable to map mscm register\n"); | ||
180 | ret = -ENOMEM; | ||
181 | goto out_free; | ||
182 | } | ||
183 | |||
184 | mscm_cp_regmap = syscon_regmap_lookup_by_phandle(node, "fsl,cpucfg"); | ||
185 | if (IS_ERR(mscm_cp_regmap)) { | ||
186 | ret = PTR_ERR(mscm_cp_regmap); | ||
187 | pr_err("vf610_mscm_ir: regmap lookup for cpucfg failed\n"); | ||
188 | goto out_unmap; | ||
189 | } | ||
190 | |||
191 | regmap_read(mscm_cp_regmap, MSCM_CPxNUM, &cpuid); | ||
192 | mscm_ir_data->cpu_mask = 0x1 << cpuid; | ||
193 | |||
194 | domain = irq_domain_add_hierarchy(domain_parent, 0, | ||
195 | MSCM_IRSPRC_NUM, node, | ||
196 | &mscm_irq_domain_ops, mscm_ir_data); | ||
197 | if (!domain) { | ||
198 | ret = -ENOMEM; | ||
199 | goto out_unmap; | ||
200 | } | ||
201 | |||
202 | cpu_pm_register_notifier(&mscm_ir_notifier_block); | ||
203 | |||
204 | return 0; | ||
205 | |||
206 | out_unmap: | ||
207 | iounmap(mscm_ir_data->mscm_ir_base); | ||
208 | out_free: | ||
209 | kfree(mscm_ir_data); | ||
210 | return ret; | ||
211 | } | ||
212 | IRQCHIP_DECLARE(vf610_mscm_ir, "fsl,vf610-mscm-ir", vf610_mscm_ir_of_init); | ||
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 289ad3ac3e80..8dcc7b8fee40 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c | |||
@@ -758,8 +758,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) | |||
758 | 758 | ||
759 | hisi_nfc_host_init(host); | 759 | hisi_nfc_host_init(host); |
760 | 760 | ||
761 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, IRQF_DISABLED, | 761 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, 0x0, "nandc", host); |
762 | "nandc", host); | ||
763 | if (ret) { | 762 | if (ret) { |
764 | dev_err(dev, "failed to request IRQ\n"); | 763 | dev_err(dev, "failed to request IRQ\n"); |
765 | goto err_res; | 764 | goto err_res; |
diff --git a/include/dt-bindings/interrupt-controller/irq-st.h b/include/dt-bindings/interrupt-controller/irq-st.h new file mode 100644 index 000000000000..4c59aceb9be0 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/irq-st.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * include/linux/irqchip/irq-st.h | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics – All Rights Reserved | ||
5 | * | ||
6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ST_H | ||
14 | #define _DT_BINDINGS_INTERRUPT_CONTROLLER_ST_H | ||
15 | |||
16 | #define ST_IRQ_SYSCFG_EXT_0 0 | ||
17 | #define ST_IRQ_SYSCFG_EXT_1 1 | ||
18 | #define ST_IRQ_SYSCFG_EXT_2 2 | ||
19 | #define ST_IRQ_SYSCFG_CTI_0 3 | ||
20 | #define ST_IRQ_SYSCFG_CTI_1 4 | ||
21 | #define ST_IRQ_SYSCFG_PMU_0 5 | ||
22 | #define ST_IRQ_SYSCFG_PMU_1 6 | ||
23 | #define ST_IRQ_SYSCFG_pl310_L2 7 | ||
24 | #define ST_IRQ_SYSCFG_DISABLED 0xFFFFFFFF | ||
25 | |||
26 | #define ST_IRQ_SYSCFG_EXT_1_INV 0x1 | ||
27 | #define ST_IRQ_SYSCFG_EXT_2_INV 0x2 | ||
28 | #define ST_IRQ_SYSCFG_EXT_3_INV 0x4 | ||
29 | |||
30 | #endif | ||
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index cba442ec3c66..f4af03404b97 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | 10 | ||
11 | extern void synchronize_irq(unsigned int irq); | 11 | extern void synchronize_irq(unsigned int irq); |
12 | extern void synchronize_hardirq(unsigned int irq); | 12 | extern bool synchronize_hardirq(unsigned int irq); |
13 | 13 | ||
14 | #if defined(CONFIG_TINY_RCU) | 14 | #if defined(CONFIG_TINY_RCU) |
15 | 15 | ||
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 2e88580194f0..950ae4501826 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -39,8 +39,6 @@ | |||
39 | * These flags used only by the kernel as part of the | 39 | * These flags used only by the kernel as part of the |
40 | * irq handling routines. | 40 | * irq handling routines. |
41 | * | 41 | * |
42 | * IRQF_DISABLED - keep irqs disabled when calling the action handler. | ||
43 | * DEPRECATED. This flag is a NOOP and scheduled to be removed | ||
44 | * IRQF_SHARED - allow sharing the irq among several devices | 42 | * IRQF_SHARED - allow sharing the irq among several devices |
45 | * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur | 43 | * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur |
46 | * IRQF_TIMER - Flag to mark this interrupt as timer interrupt | 44 | * IRQF_TIMER - Flag to mark this interrupt as timer interrupt |
@@ -64,7 +62,6 @@ | |||
64 | * wakeup devices users need to implement wakeup detection in | 62 | * wakeup devices users need to implement wakeup detection in |
65 | * their interrupt handlers. | 63 | * their interrupt handlers. |
66 | */ | 64 | */ |
67 | #define IRQF_DISABLED 0x00000020 | ||
68 | #define IRQF_SHARED 0x00000080 | 65 | #define IRQF_SHARED 0x00000080 |
69 | #define IRQF_PROBE_SHARED 0x00000100 | 66 | #define IRQF_PROBE_SHARED 0x00000100 |
70 | #define __IRQF_TIMER 0x00000200 | 67 | #define __IRQF_TIMER 0x00000200 |
@@ -191,6 +188,7 @@ extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id); | |||
191 | #endif | 188 | #endif |
192 | 189 | ||
193 | extern void disable_irq_nosync(unsigned int irq); | 190 | extern void disable_irq_nosync(unsigned int irq); |
191 | extern bool disable_hardirq(unsigned int irq); | ||
194 | extern void disable_irq(unsigned int irq); | 192 | extern void disable_irq(unsigned int irq); |
195 | extern void disable_percpu_irq(unsigned int irq); | 193 | extern void disable_percpu_irq(unsigned int irq); |
196 | extern void enable_irq(unsigned int irq); | 194 | extern void enable_irq(unsigned int irq); |
@@ -363,6 +361,20 @@ static inline int disable_irq_wake(unsigned int irq) | |||
363 | return irq_set_irq_wake(irq, 0); | 361 | return irq_set_irq_wake(irq, 0); |
364 | } | 362 | } |
365 | 363 | ||
364 | /* | ||
365 | * irq_get_irqchip_state/irq_set_irqchip_state specific flags | ||
366 | */ | ||
367 | enum irqchip_irq_state { | ||
368 | IRQCHIP_STATE_PENDING, /* Is interrupt pending? */ | ||
369 | IRQCHIP_STATE_ACTIVE, /* Is interrupt in progress? */ | ||
370 | IRQCHIP_STATE_MASKED, /* Is interrupt masked? */ | ||
371 | IRQCHIP_STATE_LINE_LEVEL, /* Is IRQ line high? */ | ||
372 | }; | ||
373 | |||
374 | extern int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which, | ||
375 | bool *state); | ||
376 | extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, | ||
377 | bool state); | ||
366 | 378 | ||
367 | #ifdef CONFIG_IRQ_FORCED_THREADING | 379 | #ifdef CONFIG_IRQ_FORCED_THREADING |
368 | extern bool force_irqthreads; | 380 | extern bool force_irqthreads; |
diff --git a/include/linux/irq.h b/include/linux/irq.h index d09ec7a1243e..62c6901cab55 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -30,6 +30,7 @@ | |||
30 | struct seq_file; | 30 | struct seq_file; |
31 | struct module; | 31 | struct module; |
32 | struct msi_msg; | 32 | struct msi_msg; |
33 | enum irqchip_irq_state; | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * IRQ line status. | 36 | * IRQ line status. |
@@ -324,6 +325,8 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) | |||
324 | * irq_request_resources | 325 | * irq_request_resources |
325 | * @irq_compose_msi_msg: optional to compose message content for MSI | 326 | * @irq_compose_msi_msg: optional to compose message content for MSI |
326 | * @irq_write_msi_msg: optional to write message content for MSI | 327 | * @irq_write_msi_msg: optional to write message content for MSI |
328 | * @irq_get_irqchip_state: return the internal state of an interrupt | ||
329 | * @irq_set_irqchip_state: set the internal state of a interrupt | ||
327 | * @flags: chip specific flags | 330 | * @flags: chip specific flags |
328 | */ | 331 | */ |
329 | struct irq_chip { | 332 | struct irq_chip { |
@@ -363,6 +366,9 @@ struct irq_chip { | |||
363 | void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg); | 366 | void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg); |
364 | void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg); | 367 | void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg); |
365 | 368 | ||
369 | int (*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state); | ||
370 | int (*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state); | ||
371 | |||
366 | unsigned long flags; | 372 | unsigned long flags; |
367 | }; | 373 | }; |
368 | 374 | ||
@@ -460,6 +466,7 @@ extern void irq_chip_eoi_parent(struct irq_data *data); | |||
460 | extern int irq_chip_set_affinity_parent(struct irq_data *data, | 466 | extern int irq_chip_set_affinity_parent(struct irq_data *data, |
461 | const struct cpumask *dest, | 467 | const struct cpumask *dest, |
462 | bool force); | 468 | bool force); |
469 | extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on); | ||
463 | #endif | 470 | #endif |
464 | 471 | ||
465 | /* Handling of unhandled and spurious interrupts: */ | 472 | /* Handling of unhandled and spurious interrupts: */ |
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 71d706d5f169..36ec4ae74634 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h | |||
@@ -97,6 +97,7 @@ struct device_node; | |||
97 | 97 | ||
98 | extern struct irq_chip gic_arch_extn; | 98 | extern struct irq_chip gic_arch_extn; |
99 | 99 | ||
100 | void gic_set_irqchip_flags(unsigned long flags); | ||
100 | void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, | 101 | void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, |
101 | u32 offset, struct device_node *); | 102 | u32 offset, struct device_node *); |
102 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); | 103 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); |
@@ -115,11 +116,5 @@ int gic_get_cpu_id(unsigned int cpu); | |||
115 | void gic_migrate_target(unsigned int new_cpu_id); | 116 | void gic_migrate_target(unsigned int new_cpu_id); |
116 | unsigned long gic_get_sgir_physaddr(void); | 117 | unsigned long gic_get_sgir_physaddr(void); |
117 | 118 | ||
118 | extern const struct irq_domain_ops *gic_routable_irq_domain_ops; | ||
119 | static inline void __init register_routable_domain_ops | ||
120 | (const struct irq_domain_ops *ops) | ||
121 | { | ||
122 | gic_routable_irq_domain_ops = ops; | ||
123 | } | ||
124 | #endif /* __ASSEMBLY */ | 119 | #endif /* __ASSEMBLY */ |
125 | #endif | 120 | #endif |
diff --git a/include/linux/irqchip/irq-crossbar.h b/include/linux/irqchip/irq-crossbar.h deleted file mode 100644 index e5537b81df8d..000000000000 --- a/include/linux/irqchip/irq-crossbar.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/irqchip/irq-crossbar.h | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | int irqcrossbar_init(void); | ||
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h index e6a6aac451db..3ea2e4754c40 100644 --- a/include/linux/irqchip/mips-gic.h +++ b/include/linux/irqchip/mips-gic.h | |||
@@ -240,6 +240,8 @@ extern unsigned int gic_get_count_width(void); | |||
240 | extern cycle_t gic_read_compare(void); | 240 | extern cycle_t gic_read_compare(void); |
241 | extern void gic_write_compare(cycle_t cnt); | 241 | extern void gic_write_compare(cycle_t cnt); |
242 | extern void gic_write_cpu_compare(cycle_t cnt, int cpu); | 242 | extern void gic_write_cpu_compare(cycle_t cnt, int cpu); |
243 | extern void gic_start_count(void); | ||
244 | extern void gic_stop_count(void); | ||
243 | extern void gic_send_ipi(unsigned int intr); | 245 | extern void gic_send_ipi(unsigned int intr); |
244 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); | 246 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); |
245 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); | 247 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); |
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index d176d658fe25..5dd1272d1ab2 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h | |||
@@ -85,7 +85,7 @@ | |||
85 | * The local_irq_*() APIs are equal to the raw_local_irq*() | 85 | * The local_irq_*() APIs are equal to the raw_local_irq*() |
86 | * if !TRACE_IRQFLAGS. | 86 | * if !TRACE_IRQFLAGS. |
87 | */ | 87 | */ |
88 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 88 | #ifdef CONFIG_TRACE_IRQFLAGS |
89 | #define local_irq_enable() \ | 89 | #define local_irq_enable() \ |
90 | do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) | 90 | do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) |
91 | #define local_irq_disable() \ | 91 | #define local_irq_disable() \ |
@@ -107,22 +107,6 @@ | |||
107 | raw_local_irq_restore(flags); \ | 107 | raw_local_irq_restore(flags); \ |
108 | } \ | 108 | } \ |
109 | } while (0) | 109 | } while (0) |
110 | #define local_save_flags(flags) \ | ||
111 | do { \ | ||
112 | raw_local_save_flags(flags); \ | ||
113 | } while (0) | ||
114 | |||
115 | #define irqs_disabled_flags(flags) \ | ||
116 | ({ \ | ||
117 | raw_irqs_disabled_flags(flags); \ | ||
118 | }) | ||
119 | |||
120 | #define irqs_disabled() \ | ||
121 | ({ \ | ||
122 | unsigned long _flags; \ | ||
123 | raw_local_save_flags(_flags); \ | ||
124 | raw_irqs_disabled_flags(_flags); \ | ||
125 | }) | ||
126 | 110 | ||
127 | #define safe_halt() \ | 111 | #define safe_halt() \ |
128 | do { \ | 112 | do { \ |
@@ -131,7 +115,7 @@ | |||
131 | } while (0) | 115 | } while (0) |
132 | 116 | ||
133 | 117 | ||
134 | #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ | 118 | #else /* !CONFIG_TRACE_IRQFLAGS */ |
135 | 119 | ||
136 | #define local_irq_enable() do { raw_local_irq_enable(); } while (0) | 120 | #define local_irq_enable() do { raw_local_irq_enable(); } while (0) |
137 | #define local_irq_disable() do { raw_local_irq_disable(); } while (0) | 121 | #define local_irq_disable() do { raw_local_irq_disable(); } while (0) |
@@ -140,11 +124,28 @@ | |||
140 | raw_local_irq_save(flags); \ | 124 | raw_local_irq_save(flags); \ |
141 | } while (0) | 125 | } while (0) |
142 | #define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0) | 126 | #define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0) |
143 | #define local_save_flags(flags) do { raw_local_save_flags(flags); } while (0) | ||
144 | #define irqs_disabled() (raw_irqs_disabled()) | ||
145 | #define irqs_disabled_flags(flags) (raw_irqs_disabled_flags(flags)) | ||
146 | #define safe_halt() do { raw_safe_halt(); } while (0) | 127 | #define safe_halt() do { raw_safe_halt(); } while (0) |
147 | 128 | ||
129 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
130 | |||
131 | #define local_save_flags(flags) raw_local_save_flags(flags) | ||
132 | |||
133 | /* | ||
134 | * Some architectures don't define arch_irqs_disabled(), so even if either | ||
135 | * definition would be fine we need to use different ones for the time being | ||
136 | * to avoid build issues. | ||
137 | */ | ||
138 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | ||
139 | #define irqs_disabled() \ | ||
140 | ({ \ | ||
141 | unsigned long _flags; \ | ||
142 | raw_local_save_flags(_flags); \ | ||
143 | raw_irqs_disabled_flags(_flags); \ | ||
144 | }) | ||
145 | #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ | ||
146 | #define irqs_disabled() raw_irqs_disabled() | ||
148 | #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ | 147 | #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ |
149 | 148 | ||
149 | #define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) | ||
150 | |||
150 | #endif | 151 | #endif |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6f1c7a566b95..eb9a4ea394ab 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -948,6 +948,22 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data) | |||
948 | 948 | ||
949 | return -ENOSYS; | 949 | return -ENOSYS; |
950 | } | 950 | } |
951 | |||
952 | /** | ||
953 | * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt | ||
954 | * @data: Pointer to interrupt specific data | ||
955 | * @on: Whether to set or reset the wake-up capability of this irq | ||
956 | * | ||
957 | * Conditional, as the underlying parent chip might not implement it. | ||
958 | */ | ||
959 | int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on) | ||
960 | { | ||
961 | data = data->parent_data; | ||
962 | if (data->chip->irq_set_wake) | ||
963 | return data->chip->irq_set_wake(data, on); | ||
964 | |||
965 | return -ENOSYS; | ||
966 | } | ||
951 | #endif | 967 | #endif |
952 | 968 | ||
953 | /** | 969 | /** |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 886d09e691d5..e68932bb308e 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -68,14 +68,20 @@ static void __synchronize_hardirq(struct irq_desc *desc) | |||
68 | * Do not use this for shutdown scenarios where you must be sure | 68 | * Do not use this for shutdown scenarios where you must be sure |
69 | * that all parts (hardirq and threaded handler) have completed. | 69 | * that all parts (hardirq and threaded handler) have completed. |
70 | * | 70 | * |
71 | * Returns: false if a threaded handler is active. | ||
72 | * | ||
71 | * This function may be called - with care - from IRQ context. | 73 | * This function may be called - with care - from IRQ context. |
72 | */ | 74 | */ |
73 | void synchronize_hardirq(unsigned int irq) | 75 | bool synchronize_hardirq(unsigned int irq) |
74 | { | 76 | { |
75 | struct irq_desc *desc = irq_to_desc(irq); | 77 | struct irq_desc *desc = irq_to_desc(irq); |
76 | 78 | ||
77 | if (desc) | 79 | if (desc) { |
78 | __synchronize_hardirq(desc); | 80 | __synchronize_hardirq(desc); |
81 | return !atomic_read(&desc->threads_active); | ||
82 | } | ||
83 | |||
84 | return true; | ||
79 | } | 85 | } |
80 | EXPORT_SYMBOL(synchronize_hardirq); | 86 | EXPORT_SYMBOL(synchronize_hardirq); |
81 | 87 | ||
@@ -440,6 +446,32 @@ void disable_irq(unsigned int irq) | |||
440 | } | 446 | } |
441 | EXPORT_SYMBOL(disable_irq); | 447 | EXPORT_SYMBOL(disable_irq); |
442 | 448 | ||
449 | /** | ||
450 | * disable_hardirq - disables an irq and waits for hardirq completion | ||
451 | * @irq: Interrupt to disable | ||
452 | * | ||
453 | * Disable the selected interrupt line. Enables and Disables are | ||
454 | * nested. | ||
455 | * This function waits for any pending hard IRQ handlers for this | ||
456 | * interrupt to complete before returning. If you use this function while | ||
457 | * holding a resource the hard IRQ handler may need you will deadlock. | ||
458 | * | ||
459 | * When used to optimistically disable an interrupt from atomic context | ||
460 | * the return value must be checked. | ||
461 | * | ||
462 | * Returns: false if a threaded handler is active. | ||
463 | * | ||
464 | * This function may be called - with care - from IRQ context. | ||
465 | */ | ||
466 | bool disable_hardirq(unsigned int irq) | ||
467 | { | ||
468 | if (!__disable_irq_nosync(irq)) | ||
469 | return synchronize_hardirq(irq); | ||
470 | |||
471 | return false; | ||
472 | } | ||
473 | EXPORT_SYMBOL_GPL(disable_hardirq); | ||
474 | |||
443 | void __enable_irq(struct irq_desc *desc, unsigned int irq) | 475 | void __enable_irq(struct irq_desc *desc, unsigned int irq) |
444 | { | 476 | { |
445 | switch (desc->depth) { | 477 | switch (desc->depth) { |
@@ -1766,3 +1798,94 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler, | |||
1766 | 1798 | ||
1767 | return retval; | 1799 | return retval; |
1768 | } | 1800 | } |
1801 | |||
1802 | /** | ||
1803 | * irq_get_irqchip_state - returns the irqchip state of a interrupt. | ||
1804 | * @irq: Interrupt line that is forwarded to a VM | ||
1805 | * @which: One of IRQCHIP_STATE_* the caller wants to know about | ||
1806 | * @state: a pointer to a boolean where the state is to be storeed | ||
1807 | * | ||
1808 | * This call snapshots the internal irqchip state of an | ||
1809 | * interrupt, returning into @state the bit corresponding to | ||
1810 | * stage @which | ||
1811 | * | ||
1812 | * This function should be called with preemption disabled if the | ||
1813 | * interrupt controller has per-cpu registers. | ||
1814 | */ | ||
1815 | int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which, | ||
1816 | bool *state) | ||
1817 | { | ||
1818 | struct irq_desc *desc; | ||
1819 | struct irq_data *data; | ||
1820 | struct irq_chip *chip; | ||
1821 | unsigned long flags; | ||
1822 | int err = -EINVAL; | ||
1823 | |||
1824 | desc = irq_get_desc_buslock(irq, &flags, 0); | ||
1825 | if (!desc) | ||
1826 | return err; | ||
1827 | |||
1828 | data = irq_desc_get_irq_data(desc); | ||
1829 | |||
1830 | do { | ||
1831 | chip = irq_data_get_irq_chip(data); | ||
1832 | if (chip->irq_get_irqchip_state) | ||
1833 | break; | ||
1834 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY | ||
1835 | data = data->parent_data; | ||
1836 | #else | ||
1837 | data = NULL; | ||
1838 | #endif | ||
1839 | } while (data); | ||
1840 | |||
1841 | if (data) | ||
1842 | err = chip->irq_get_irqchip_state(data, which, state); | ||
1843 | |||
1844 | irq_put_desc_busunlock(desc, flags); | ||
1845 | return err; | ||
1846 | } | ||
1847 | |||
1848 | /** | ||
1849 | * irq_set_irqchip_state - set the state of a forwarded interrupt. | ||
1850 | * @irq: Interrupt line that is forwarded to a VM | ||
1851 | * @which: State to be restored (one of IRQCHIP_STATE_*) | ||
1852 | * @val: Value corresponding to @which | ||
1853 | * | ||
1854 | * This call sets the internal irqchip state of an interrupt, | ||
1855 | * depending on the value of @which. | ||
1856 | * | ||
1857 | * This function should be called with preemption disabled if the | ||
1858 | * interrupt controller has per-cpu registers. | ||
1859 | */ | ||
1860 | int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, | ||
1861 | bool val) | ||
1862 | { | ||
1863 | struct irq_desc *desc; | ||
1864 | struct irq_data *data; | ||
1865 | struct irq_chip *chip; | ||
1866 | unsigned long flags; | ||
1867 | int err = -EINVAL; | ||
1868 | |||
1869 | desc = irq_get_desc_buslock(irq, &flags, 0); | ||
1870 | if (!desc) | ||
1871 | return err; | ||
1872 | |||
1873 | data = irq_desc_get_irq_data(desc); | ||
1874 | |||
1875 | do { | ||
1876 | chip = irq_data_get_irq_chip(data); | ||
1877 | if (chip->irq_set_irqchip_state) | ||
1878 | break; | ||
1879 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY | ||
1880 | data = data->parent_data; | ||
1881 | #else | ||
1882 | data = NULL; | ||
1883 | #endif | ||
1884 | } while (data); | ||
1885 | |||
1886 | if (data) | ||
1887 | err = chip->irq_set_irqchip_state(data, which, val); | ||
1888 | |||
1889 | irq_put_desc_busunlock(desc, flags); | ||
1890 | return err; | ||
1891 | } | ||
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 3e18163f336f..474de5cb394d 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c | |||
@@ -310,8 +310,15 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) | |||
310 | struct msi_desc *desc; | 310 | struct msi_desc *desc; |
311 | 311 | ||
312 | for_each_msi_entry(desc, dev) { | 312 | for_each_msi_entry(desc, dev) { |
313 | irq_domain_free_irqs(desc->irq, desc->nvec_used); | 313 | /* |
314 | desc->irq = 0; | 314 | * We might have failed to allocate an MSI early |
315 | * enough that there is no IRQ associated to this | ||
316 | * entry. If that's the case, don't do anything. | ||
317 | */ | ||
318 | if (desc->irq) { | ||
319 | irq_domain_free_irqs(desc->irq, desc->nvec_used); | ||
320 | desc->irq = 0; | ||
321 | } | ||
315 | } | 322 | } |
316 | } | 323 | } |
317 | 324 | ||