Skip to content

Commit 8d9d51b

Browse files
committed
Merge tag 'irqchip-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates for v4.13 from Marc Zyngier - support for the new Marvell wire-to-MSI bridge - support for the Aspeed I2C irqchip - Armada XP370 per-cpu interrupt fixes - GICv3 ITS ACPI NUMA support - sunxi-nmi cleanup and updates for new platform support - various GICv3 ITS cleanups and fixes - some constifying in various places
2 parents 6a6544e + 6c31e12 commit 8d9d51b

25 files changed

+1134
-90
lines changed

Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ Allwinner Sunxi NMI Controller
33

44
Required properties:
55

6-
- compatible : should be "allwinner,sun7i-a20-sc-nmi" or
7-
"allwinner,sun6i-a31-sc-nmi" or "allwinner,sun9i-a80-nmi"
6+
- compatible : should be one of the following:
7+
- "allwinner,sun7i-a20-sc-nmi"
8+
- "allwinner,sun6i-a31-sc-nmi" (deprecated)
9+
- "allwinner,sun6i-a31-r-intc"
10+
- "allwinner,sun9i-a80-nmi"
811
- reg : Specifies base physical address and size of the registers.
912
- interrupt-controller : Identifies the node as an interrupt controller
1013
- #interrupt-cells : Specifies the number of cells needed to encode an
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Device tree configuration for the I2C Interrupt Controller on the AST24XX and
2+
AST25XX SoCs.
3+
4+
Required Properties:
5+
- #address-cells : should be 1
6+
- #size-cells : should be 1
7+
- #interrupt-cells : should be 1
8+
- compatible : should be "aspeed,ast2400-i2c-ic"
9+
or "aspeed,ast2500-i2c-ic"
10+
- reg : address start and range of controller
11+
- interrupts : interrupt number
12+
- interrupt-controller : denotes that the controller receives and fires
13+
new interrupts for child busses
14+
15+
Example:
16+
17+
i2c_ic: interrupt-controller@0 {
18+
#address-cells = <1>;
19+
#size-cells = <1>;
20+
#interrupt-cells = <1>;
21+
compatible = "aspeed,ast2400-i2c-ic";
22+
reg = <0x0 0x40>;
23+
interrupts = <12>;
24+
interrupt-controller;
25+
};

Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
Aspeed Vectored Interrupt Controller
22

3-
These bindings are for the Aspeed AST2400 interrupt controller register layout.
4-
The SoC has an legacy register layout, but this driver does not support that
5-
mode of operation.
3+
These bindings are for the Aspeed interrupt controller. The AST2400 and
4+
AST2500 SoC families include a legacy register layout before a re-designed
5+
layout, but the bindings do not prescribe the use of one or the other.
66

77
Required properties:
88

9-
- compatible : should be "aspeed,ast2400-vic".
9+
- compatible : "aspeed,ast2400-vic"
10+
"aspeed,ast2500-vic"
1011

1112
- interrupt-controller : Identifies the node as an interrupt controller
1213
- #interrupt-cells : Specifies the number of cells needed to encode an
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Marvell GICP Controller
2+
-----------------------
3+
4+
GICP is a Marvell extension of the GIC that allows to trigger GIC SPI
5+
interrupts by doing a memory transaction. It is used by the ICU
6+
located in the Marvell CP110 to turn wired interrupts inside the CP
7+
into GIC SPI interrupts.
8+
9+
Required properties:
10+
11+
- compatible: Must be "marvell,ap806-gicp"
12+
13+
- reg: Must be the address and size of the GICP SPI registers
14+
15+
- marvell,spi-ranges: tuples of GIC SPI interrupts ranges available
16+
for this GICP
17+
18+
- msi-controller: indicates that this is an MSI controller
19+
20+
Example:
21+
22+
gicp_spi: gicp-spi@3f0040 {
23+
compatible = "marvell,ap806-gicp";
24+
reg = <0x3f0040 0x10>;
25+
marvell,spi-ranges = <64 64>, <288 64>;
26+
msi-controller;
27+
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
Marvell ICU Interrupt Controller
2+
--------------------------------
3+
4+
The Marvell ICU (Interrupt Consolidation Unit) controller is
5+
responsible for collecting all wired-interrupt sources in the CP and
6+
communicating them to the GIC in the AP, the unit translates interrupt
7+
requests on input wires to MSG memory mapped transactions to the GIC.
8+
9+
Required properties:
10+
11+
- compatible: Should be "marvell,cp110-icu"
12+
13+
- reg: Should contain ICU registers location and length.
14+
15+
- #interrupt-cells: Specifies the number of cells needed to encode an
16+
interrupt source. The value shall be 3.
17+
18+
The 1st cell is the group type of the ICU interrupt. Possible group
19+
types are:
20+
21+
ICU_GRP_NSR (0x0) : Shared peripheral interrupt, non-secure
22+
ICU_GRP_SR (0x1) : Shared peripheral interrupt, secure
23+
ICU_GRP_SEI (0x4) : System error interrupt
24+
ICU_GRP_REI (0x5) : RAM error interrupt
25+
26+
The 2nd cell is the index of the interrupt in the ICU unit.
27+
28+
The 3rd cell is the type of the interrupt. See arm,gic.txt for
29+
details.
30+
31+
- interrupt-controller: Identifies the node as an interrupt
32+
controller.
33+
34+
- msi-parent: Should point to the GICP controller, the GIC extension
35+
that allows to trigger interrupts using MSG memory mapped
36+
transactions.
37+
38+
Example:
39+
40+
icu: interrupt-controller@1e0000 {
41+
compatible = "marvell,cp110-icu";
42+
reg = <0x1e0000 0x10>;
43+
#interrupt-cells = <3>;
44+
interrupt-controller;
45+
msi-parent = <&gicp>;
46+
};
47+
48+
usb3h0: usb3@500000 {
49+
interrupt-parent = <&icu>;
50+
interrupts = <ICU_GRP_NSR 106 IRQ_TYPE_LEVEL_HIGH>;
51+
};

drivers/irqchip/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ config IRQ_MXS
268268
select IRQ_DOMAIN
269269
select STMP_DEVICE
270270

271+
config MVEBU_GICP
272+
bool
273+
274+
config MVEBU_ICU
275+
bool
276+
271277
config MVEBU_ODMI
272278
bool
273279
select GENERIC_MSI_IRQ_DOMAIN

drivers/irqchip/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
6969
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
7070
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
7171
obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o
72+
obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o
73+
obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o
7274
obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
7375
obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
7476
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
7577
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
76-
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
78+
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
7779
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
7880
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o

drivers/irqchip/irq-armada-370-xp.c

Lines changed: 129 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,104 @@
3434
#include <asm/smp_plat.h>
3535
#include <asm/mach/irq.h>
3636

37-
/* Interrupt Controller Registers Map */
38-
#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
39-
#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
40-
#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
41-
#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)
37+
/*
38+
* Overall diagram of the Armada XP interrupt controller:
39+
*
40+
* To CPU 0 To CPU 1
41+
*
42+
* /\ /\
43+
* || ||
44+
* +---------------+ +---------------+
45+
* | | | |
46+
* | per-CPU | | per-CPU |
47+
* | mask/unmask | | mask/unmask |
48+
* | CPU0 | | CPU1 |
49+
* | | | |
50+
* +---------------+ +---------------+
51+
* /\ /\
52+
* || ||
53+
* \\_______________________//
54+
* ||
55+
* +-------------------+
56+
* | |
57+
* | Global interrupt |
58+
* | mask/unmask |
59+
* | |
60+
* +-------------------+
61+
* /\
62+
* ||
63+
* interrupt from
64+
* device
65+
*
66+
* The "global interrupt mask/unmask" is modified using the
67+
* ARMADA_370_XP_INT_SET_ENABLE_OFFS and
68+
* ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS registers, which are relative
69+
* to "main_int_base".
70+
*
71+
* The "per-CPU mask/unmask" is modified using the
72+
* ARMADA_370_XP_INT_SET_MASK_OFFS and
73+
* ARMADA_370_XP_INT_CLEAR_MASK_OFFS registers, which are relative to
74+
* "per_cpu_int_base". This base address points to a special address,
75+
* which automatically accesses the registers of the current CPU.
76+
*
77+
* The per-CPU mask/unmask can also be adjusted using the global
78+
* per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use
79+
* to configure interrupt affinity.
80+
*
81+
* Due to this model, all interrupts need to be mask/unmasked at two
82+
* different levels: at the global level and at the per-CPU level.
83+
*
84+
* This driver takes the following approach to deal with this:
85+
*
86+
* - For global interrupts:
87+
*
88+
* At ->map() time, a global interrupt is unmasked at the per-CPU
89+
* mask/unmask level. It is therefore unmasked at this level for
90+
* the current CPU, running the ->map() code. This allows to have
91+
* the interrupt unmasked at this level in non-SMP
92+
* configurations. In SMP configurations, the ->set_affinity()
93+
* callback is called, which using the
94+
* ARMADA_370_XP_INT_SOURCE_CTL() readjusts the per-CPU mask/unmask
95+
* for the interrupt.
96+
*
97+
* The ->mask() and ->unmask() operations only mask/unmask the
98+
* interrupt at the "global" level.
99+
*
100+
* So, a global interrupt is enabled at the per-CPU level as soon
101+
* as it is mapped. At run time, the masking/unmasking takes place
102+
* at the global level.
103+
*
104+
* - For per-CPU interrupts
105+
*
106+
* At ->map() time, a per-CPU interrupt is unmasked at the global
107+
* mask/unmask level.
108+
*
109+
* The ->mask() and ->unmask() operations mask/unmask the interrupt
110+
* at the per-CPU level.
111+
*
112+
* So, a per-CPU interrupt is enabled at the global level as soon
113+
* as it is mapped. At run time, the masking/unmasking takes place
114+
* at the per-CPU level.
115+
*/
42116

117+
/* Registers relative to main_int_base */
43118
#define ARMADA_370_XP_INT_CONTROL (0x00)
119+
#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x04)
44120
#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
45121
#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
46122
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
47123
#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF
48124
#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid)
49125

50-
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
126+
/* Registers relative to per_cpu_int_base */
127+
#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x08)
128+
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0x0c)
51129
#define ARMADA_375_PPI_CAUSE (0x10)
52-
53-
#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
54-
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
55-
#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8)
130+
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
131+
#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
132+
#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
133+
#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
134+
#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)
56135

57136
#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
58137

@@ -281,13 +360,11 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
281360
irq_set_percpu_devid(virq);
282361
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
283362
handle_percpu_devid_irq);
284-
285363
} else {
286364
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
287365
handle_level_irq);
288366
}
289367
irq_set_probe(virq);
290-
irq_clear_status_flags(virq, IRQ_NOAUTOEN);
291368

292369
return 0;
293370
}
@@ -345,16 +422,40 @@ static void armada_mpic_send_doorbell(const struct cpumask *mask,
345422
ARMADA_370_XP_SW_TRIG_INT_OFFS);
346423
}
347424

425+
static void armada_xp_mpic_reenable_percpu(void)
426+
{
427+
unsigned int irq;
428+
429+
/* Re-enable per-CPU interrupts that were enabled before suspend */
430+
for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) {
431+
struct irq_data *data;
432+
int virq;
433+
434+
virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
435+
if (virq == 0)
436+
continue;
437+
438+
data = irq_get_irq_data(virq);
439+
440+
if (!irq_percpu_is_enabled(virq))
441+
continue;
442+
443+
armada_370_xp_irq_unmask(data);
444+
}
445+
}
446+
348447
static int armada_xp_mpic_starting_cpu(unsigned int cpu)
349448
{
350449
armada_xp_mpic_perf_init();
351450
armada_xp_mpic_smp_cpu_init();
451+
armada_xp_mpic_reenable_percpu();
352452
return 0;
353453
}
354454

355455
static int mpic_cascaded_starting_cpu(unsigned int cpu)
356456
{
357457
armada_xp_mpic_perf_init();
458+
armada_xp_mpic_reenable_percpu();
358459
enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
359460
return 0;
360461
}
@@ -502,16 +603,27 @@ static void armada_370_xp_mpic_resume(void)
502603
if (virq == 0)
503604
continue;
504605

505-
if (!is_percpu_irq(irq))
606+
data = irq_get_irq_data(virq);
607+
608+
if (!is_percpu_irq(irq)) {
609+
/* Non per-CPU interrupts */
506610
writel(irq, per_cpu_int_base +
507611
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
508-
else
612+
if (!irqd_irq_disabled(data))
613+
armada_370_xp_irq_unmask(data);
614+
} else {
615+
/* Per-CPU interrupts */
509616
writel(irq, main_int_base +
510617
ARMADA_370_XP_INT_SET_ENABLE_OFFS);
511618

512-
data = irq_get_irq_data(virq);
513-
if (!irqd_irq_disabled(data))
514-
armada_370_xp_irq_unmask(data);
619+
/*
620+
* Re-enable on the current CPU,
621+
* armada_xp_mpic_reenable_percpu() will take
622+
* care of secondary CPUs when they come up.
623+
*/
624+
if (irq_percpu_is_enabled(virq))
625+
armada_370_xp_irq_unmask(data);
626+
}
515627
}
516628

517629
/* Reconfigure doorbells for IPIs and MSIs */

0 commit comments

Comments
 (0)