aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-25 14:43:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-25 14:43:47 -0400
commit5947a64a7e0c70cc16d5d1e5af3cf3b44535047a (patch)
treed6b7c1cfbf4f02117814d54a90980f9f87002abf
parent4dcb9239dad6cee17c538482619a5b659774ee51 (diff)
parent746a923b863a1065ef77324e1e43f19b1a3eab5c (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "The interrupt brigade came up with the following updates: - Driver for the Marvell System Error Interrupt machinery - Overhaul of the GIC-V3 ITS driver - Small updates and fixes all over the place" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (31 commits) genirq: Fix race on spurious interrupt detection softirq: Fix typo in __do_softirq() comments genirq: Fix grammar s/an /a / irqchip/gic: Unify GIC priority definitions irqchip/gic-v3: Remove acknowledge loop dt-bindings/interrupt-controller: Add documentation for Marvell SEI controller dt-bindings/interrupt-controller: Update Marvell ICU bindings irqchip/irq-mvebu-icu: Add support for System Error Interrupts (SEI) arm64: marvell: Enable SEI driver irqchip/irq-mvebu-sei: Add new driver for Marvell SEI irqchip/irq-mvebu-icu: Support ICU subnodes irqchip/irq-mvebu-icu: Disociate ICU and NSR irqchip/irq-mvebu-icu: Clarify the reset operation of configured interrupts irqchip/irq-mvebu-icu: Fix wrong private data retrieval dt-bindings/interrupt-controller: Fix Marvell ICU length in the example genirq/msi: Allow creation of a tree-based irqdomain for platform-msi dt-bindings: irqchip: renesas-irqc: Document r8a7744 support dt-bindings: irqchip: renesas-irqc: Document R-Car E3 support irqchip/pdc: Setup all edge interrupts as rising edge at GIC irqchip/gic-v3-its: Allow use of LPI tables in reserved memory ...
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/marvell,icu.txt85
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/marvell,sei.txt36
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt5
-rw-r--r--arch/arm64/Kconfig.platforms1
-rw-r--r--drivers/base/platform-msi.c14
-rw-r--r--drivers/irqchip/Kconfig3
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c249
-rw-r--r--drivers/irqchip/irq-gic-v3.c85
-rw-r--r--drivers/irqchip/irq-mvebu-icu.c253
-rw-r--r--drivers/irqchip/irq-mvebu-sei.c507
-rw-r--r--drivers/irqchip/qcom-pdc.c1
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/irqchip/arm-gic-common.h6
-rw-r--r--include/linux/irqchip/arm-gic-v3.h4
-rw-r--r--include/linux/irqchip/arm-gic.h5
-rw-r--r--include/linux/irqdomain.h1
-rw-r--r--include/linux/msi.h17
-rw-r--r--kernel/irq/irqdomain.c5
-rw-r--r--kernel/irq/manage.c8
-rw-r--r--kernel/softirq.c6
21 files changed, 1093 insertions, 201 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,icu.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,icu.txt
index aa8bf2ec8905..1c94a57a661e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/marvell,icu.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,icu.txt
@@ -5,6 +5,8 @@ The Marvell ICU (Interrupt Consolidation Unit) controller is
5responsible for collecting all wired-interrupt sources in the CP and 5responsible for collecting all wired-interrupt sources in the CP and
6communicating them to the GIC in the AP, the unit translates interrupt 6communicating them to the GIC in the AP, the unit translates interrupt
7requests on input wires to MSG memory mapped transactions to the GIC. 7requests on input wires to MSG memory mapped transactions to the GIC.
8These messages will access a different GIC memory area depending on
9their type (NSR, SR, SEI, REI, etc).
8 10
9Required properties: 11Required properties:
10 12
@@ -12,20 +14,23 @@ Required properties:
12 14
13- reg: Should contain ICU registers location and length. 15- reg: Should contain ICU registers location and length.
14 16
15- #interrupt-cells: Specifies the number of cells needed to encode an 17Subnodes: Each group of interrupt is declared as a subnode of the ICU,
16 interrupt source. The value shall be 3. 18with their own compatible.
19
20Required properties for the icu_nsr/icu_sei subnodes:
17 21
18 The 1st cell is the group type of the ICU interrupt. Possible group 22- compatible: Should be one of:
19 types are: 23 * "marvell,cp110-icu-nsr"
24 * "marvell,cp110-icu-sr"
25 * "marvell,cp110-icu-sei"
26 * "marvell,cp110-icu-rei"
20 27
21 ICU_GRP_NSR (0x0) : Shared peripheral interrupt, non-secure 28- #interrupt-cells: Specifies the number of cells needed to encode an
22 ICU_GRP_SR (0x1) : Shared peripheral interrupt, secure 29 interrupt source. The value shall be 2.
23 ICU_GRP_SEI (0x4) : System error interrupt
24 ICU_GRP_REI (0x5) : RAM error interrupt
25 30
26 The 2nd cell is the index of the interrupt in the ICU unit. 31 The 1st cell is the index of the interrupt in the ICU unit.
27 32
28 The 3rd cell is the type of the interrupt. See arm,gic.txt for 33 The 2nd cell is the type of the interrupt. See arm,gic.txt for
29 details. 34 details.
30 35
31- interrupt-controller: Identifies the node as an interrupt 36- interrupt-controller: Identifies the node as an interrupt
@@ -35,17 +40,73 @@ Required properties:
35 that allows to trigger interrupts using MSG memory mapped 40 that allows to trigger interrupts using MSG memory mapped
36 transactions. 41 transactions.
37 42
43Note: each 'interrupts' property referring to any 'icu_xxx' node shall
44 have a different number within [0:206].
45
38Example: 46Example:
39 47
40icu: interrupt-controller@1e0000 { 48icu: interrupt-controller@1e0000 {
41 compatible = "marvell,cp110-icu"; 49 compatible = "marvell,cp110-icu";
42 reg = <0x1e0000 0x10>; 50 reg = <0x1e0000 0x440>;
51
52 CP110_LABEL(icu_nsr): interrupt-controller@10 {
53 compatible = "marvell,cp110-icu-nsr";
54 reg = <0x10 0x20>;
55 #interrupt-cells = <2>;
56 interrupt-controller;
57 msi-parent = <&gicp>;
58 };
59
60 CP110_LABEL(icu_sei): interrupt-controller@50 {
61 compatible = "marvell,cp110-icu-sei";
62 reg = <0x50 0x10>;
63 #interrupt-cells = <2>;
64 interrupt-controller;
65 msi-parent = <&sei>;
66 };
67};
68
69node1 {
70 interrupt-parent = <&icu_nsr>;
71 interrupts = <106 IRQ_TYPE_LEVEL_HIGH>;
72};
73
74node2 {
75 interrupt-parent = <&icu_sei>;
76 interrupts = <107 IRQ_TYPE_LEVEL_HIGH>;
77};
78
79/* Would not work with the above nodes */
80node3 {
81 interrupt-parent = <&icu_nsr>;
82 interrupts = <107 IRQ_TYPE_LEVEL_HIGH>;
83};
84
85The legacy bindings were different in this way:
86
87- #interrupt-cells: The value was 3.
88 The 1st cell was the group type of the ICU interrupt. Possible
89 group types were:
90 ICU_GRP_NSR (0x0) : Shared peripheral interrupt, non-secure
91 ICU_GRP_SR (0x1) : Shared peripheral interrupt, secure
92 ICU_GRP_SEI (0x4) : System error interrupt
93 ICU_GRP_REI (0x5) : RAM error interrupt
94 The 2nd cell was the index of the interrupt in the ICU unit.
95 The 3rd cell was the type of the interrupt. See arm,gic.txt for
96 details.
97
98Example:
99
100icu: interrupt-controller@1e0000 {
101 compatible = "marvell,cp110-icu";
102 reg = <0x1e0000 0x440>;
103
43 #interrupt-cells = <3>; 104 #interrupt-cells = <3>;
44 interrupt-controller; 105 interrupt-controller;
45 msi-parent = <&gicp>; 106 msi-parent = <&gicp>;
46}; 107};
47 108
48usb3h0: usb3@500000 { 109node1 {
49 interrupt-parent = <&icu>; 110 interrupt-parent = <&icu>;
50 interrupts = <ICU_GRP_NSR 106 IRQ_TYPE_LEVEL_HIGH>; 111 interrupts = <ICU_GRP_NSR 106 IRQ_TYPE_LEVEL_HIGH>;
51}; 112};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,sei.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,sei.txt
new file mode 100644
index 000000000000..0beafed502f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,sei.txt
@@ -0,0 +1,36 @@
1Marvell SEI (System Error Interrupt) Controller
2-----------------------------------------------
3
4Marvell SEI (System Error Interrupt) controller is an interrupt
5aggregator. It receives interrupts from several sources and aggregates
6them to a single interrupt line (an SPI) on the parent interrupt
7controller.
8
9This interrupt controller can handle up to 64 SEIs, a set comes from the
10AP and is wired while a second set comes from the CPs by the mean of
11MSIs.
12
13Required properties:
14
15- compatible: should be one of:
16 * "marvell,ap806-sei"
17- reg: SEI registers location and length.
18- interrupts: identifies the parent IRQ that will be triggered.
19- #interrupt-cells: number of cells to define an SEI wired interrupt
20 coming from the AP, should be 1. The cell is the IRQ
21 number.
22- interrupt-controller: identifies the node as an interrupt controller
23 for AP interrupts.
24- msi-controller: identifies the node as an MSI controller for the CPs
25 interrupts.
26
27Example:
28
29 sei: interrupt-controller@3f0200 {
30 compatible = "marvell,ap806-sei";
31 reg = <0x3f0200 0x40>;
32 interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
33 #interrupt-cells = <1>;
34 interrupt-controller;
35 msi-controller;
36 };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt
index a046ed374d80..8de96a4fb2d5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt
@@ -2,10 +2,12 @@ DT bindings for the R-Mobile/R-Car/RZ/G interrupt controller
2 2
3Required properties: 3Required properties:
4 4
5- compatible: has to be "renesas,irqc-<soctype>", "renesas,irqc" as fallback. 5- compatible: must be "renesas,irqc-<soctype>" or "renesas,intc-ex-<soctype>",
6 and "renesas,irqc" as fallback.
6 Examples with soctypes are: 7 Examples with soctypes are:
7 - "renesas,irqc-r8a73a4" (R-Mobile APE6) 8 - "renesas,irqc-r8a73a4" (R-Mobile APE6)
8 - "renesas,irqc-r8a7743" (RZ/G1M) 9 - "renesas,irqc-r8a7743" (RZ/G1M)
10 - "renesas,irqc-r8a7744" (RZ/G1N)
9 - "renesas,irqc-r8a7745" (RZ/G1E) 11 - "renesas,irqc-r8a7745" (RZ/G1E)
10 - "renesas,irqc-r8a77470" (RZ/G1C) 12 - "renesas,irqc-r8a77470" (RZ/G1C)
11 - "renesas,irqc-r8a7790" (R-Car H2) 13 - "renesas,irqc-r8a7790" (R-Car H2)
@@ -19,6 +21,7 @@ Required properties:
19 - "renesas,intc-ex-r8a77965" (R-Car M3-N) 21 - "renesas,intc-ex-r8a77965" (R-Car M3-N)
20 - "renesas,intc-ex-r8a77970" (R-Car V3M) 22 - "renesas,intc-ex-r8a77970" (R-Car V3M)
21 - "renesas,intc-ex-r8a77980" (R-Car V3H) 23 - "renesas,intc-ex-r8a77980" (R-Car V3H)
24 - "renesas,intc-ex-r8a77990" (R-Car E3)
22 - "renesas,intc-ex-r8a77995" (R-Car D3) 25 - "renesas,intc-ex-r8a77995" (R-Car D3)
23- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in 26- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
24 interrupts.txt in this directory 27 interrupts.txt in this directory
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 393d2b524284..5a89a957641b 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -128,6 +128,7 @@ config ARCH_MVEBU
128 select MVEBU_ICU 128 select MVEBU_ICU
129 select MVEBU_ODMI 129 select MVEBU_ODMI
130 select MVEBU_PIC 130 select MVEBU_PIC
131 select MVEBU_SEI
131 select OF_GPIO 132 select OF_GPIO
132 select PINCTRL 133 select PINCTRL
133 select PINCTRL_ARMADA_37XX 134 select PINCTRL_ARMADA_37XX
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 60d6cc618f1c..f39a920496fb 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -321,11 +321,12 @@ void *platform_msi_get_host_data(struct irq_domain *domain)
321 * Returns an irqdomain for @nvec interrupts 321 * Returns an irqdomain for @nvec interrupts
322 */ 322 */
323struct irq_domain * 323struct irq_domain *
324platform_msi_create_device_domain(struct device *dev, 324__platform_msi_create_device_domain(struct device *dev,
325 unsigned int nvec, 325 unsigned int nvec,
326 irq_write_msi_msg_t write_msi_msg, 326 bool is_tree,
327 const struct irq_domain_ops *ops, 327 irq_write_msi_msg_t write_msi_msg,
328 void *host_data) 328 const struct irq_domain_ops *ops,
329 void *host_data)
329{ 330{
330 struct platform_msi_priv_data *data; 331 struct platform_msi_priv_data *data;
331 struct irq_domain *domain; 332 struct irq_domain *domain;
@@ -336,7 +337,8 @@ platform_msi_create_device_domain(struct device *dev,
336 return NULL; 337 return NULL;
337 338
338 data->host_data = host_data; 339 data->host_data = host_data;
339 domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec, 340 domain = irq_domain_create_hierarchy(dev->msi_domain, 0,
341 is_tree ? 0 : nvec,
340 dev->fwnode, ops, data); 342 dev->fwnode, ops, data);
341 if (!domain) 343 if (!domain)
342 goto free_priv; 344 goto free_priv;
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 383e7b70221d..96451b581452 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -310,6 +310,9 @@ config MVEBU_ODMI
310config MVEBU_PIC 310config MVEBU_PIC
311 bool 311 bool
312 312
313config MVEBU_SEI
314 bool
315
313config LS_SCFG_MSI 316config LS_SCFG_MSI
314 def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE 317 def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE
315 depends on PCI && PCI_MSI 318 depends on PCI && PCI_MSI
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index fbd1ec8070ef..b822199445ff 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o
76obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o 76obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o
77obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o 77obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
78obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o 78obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
79obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o
79obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o 80obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
80obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o 81obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
81obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o 82obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index c2df341ff6fa..db20e992a40f 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -19,13 +19,16 @@
19#include <linux/acpi_iort.h> 19#include <linux/acpi_iort.h>
20#include <linux/bitmap.h> 20#include <linux/bitmap.h>
21#include <linux/cpu.h> 21#include <linux/cpu.h>
22#include <linux/crash_dump.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/dma-iommu.h> 24#include <linux/dma-iommu.h>
25#include <linux/efi.h>
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
25#include <linux/irqdomain.h> 27#include <linux/irqdomain.h>
26#include <linux/list.h> 28#include <linux/list.h>
27#include <linux/list_sort.h> 29#include <linux/list_sort.h>
28#include <linux/log2.h> 30#include <linux/log2.h>
31#include <linux/memblock.h>
29#include <linux/mm.h> 32#include <linux/mm.h>
30#include <linux/msi.h> 33#include <linux/msi.h>
31#include <linux/of.h> 34#include <linux/of.h>
@@ -52,6 +55,7 @@
52#define ITS_FLAGS_SAVE_SUSPEND_STATE (1ULL << 3) 55#define ITS_FLAGS_SAVE_SUSPEND_STATE (1ULL << 3)
53 56
54#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) 57#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
58#define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
55 59
56static u32 lpi_id_bits; 60static u32 lpi_id_bits;
57 61
@@ -64,7 +68,7 @@ static u32 lpi_id_bits;
64#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) 68#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
65#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) 69#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
66 70
67#define LPI_PROP_DEFAULT_PRIO 0xa0 71#define LPI_PROP_DEFAULT_PRIO GICD_INT_DEF_PRI
68 72
69/* 73/*
70 * Collection structure - just an ID, and a redistributor address to 74 * Collection structure - just an ID, and a redistributor address to
@@ -173,6 +177,7 @@ static DEFINE_RAW_SPINLOCK(vmovp_lock);
173static DEFINE_IDA(its_vpeid_ida); 177static DEFINE_IDA(its_vpeid_ida);
174 178
175#define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist)) 179#define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist))
180#define gic_data_rdist_cpu(cpu) (per_cpu_ptr(gic_rdists->rdist, cpu))
176#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) 181#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
177#define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) 182#define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K)
178 183
@@ -1028,7 +1033,7 @@ static inline u32 its_get_event_id(struct irq_data *d)
1028static void lpi_write_config(struct irq_data *d, u8 clr, u8 set) 1033static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
1029{ 1034{
1030 irq_hw_number_t hwirq; 1035 irq_hw_number_t hwirq;
1031 struct page *prop_page; 1036 void *va;
1032 u8 *cfg; 1037 u8 *cfg;
1033 1038
1034 if (irqd_is_forwarded_to_vcpu(d)) { 1039 if (irqd_is_forwarded_to_vcpu(d)) {
@@ -1036,7 +1041,7 @@ static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
1036 u32 event = its_get_event_id(d); 1041 u32 event = its_get_event_id(d);
1037 struct its_vlpi_map *map; 1042 struct its_vlpi_map *map;
1038 1043
1039 prop_page = its_dev->event_map.vm->vprop_page; 1044 va = page_address(its_dev->event_map.vm->vprop_page);
1040 map = &its_dev->event_map.vlpi_maps[event]; 1045 map = &its_dev->event_map.vlpi_maps[event];
1041 hwirq = map->vintid; 1046 hwirq = map->vintid;
1042 1047
@@ -1044,11 +1049,11 @@ static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
1044 map->properties &= ~clr; 1049 map->properties &= ~clr;
1045 map->properties |= set | LPI_PROP_GROUP1; 1050 map->properties |= set | LPI_PROP_GROUP1;
1046 } else { 1051 } else {
1047 prop_page = gic_rdists->prop_page; 1052 va = gic_rdists->prop_table_va;
1048 hwirq = d->hwirq; 1053 hwirq = d->hwirq;
1049 } 1054 }
1050 1055
1051 cfg = page_address(prop_page) + hwirq - 8192; 1056 cfg = va + hwirq - 8192;
1052 *cfg &= ~clr; 1057 *cfg &= ~clr;
1053 *cfg |= set | LPI_PROP_GROUP1; 1058 *cfg |= set | LPI_PROP_GROUP1;
1054 1059
@@ -1597,6 +1602,15 @@ static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)
1597 kfree(bitmap); 1602 kfree(bitmap);
1598} 1603}
1599 1604
1605static void gic_reset_prop_table(void *va)
1606{
1607 /* Priority 0xa0, Group-1, disabled */
1608 memset(va, LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);
1609
1610 /* Make sure the GIC will observe the written configuration */
1611 gic_flush_dcache_to_poc(va, LPI_PROPBASE_SZ);
1612}
1613
1600static struct page *its_allocate_prop_table(gfp_t gfp_flags) 1614static struct page *its_allocate_prop_table(gfp_t gfp_flags)
1601{ 1615{
1602 struct page *prop_page; 1616 struct page *prop_page;
@@ -1605,13 +1619,7 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
1605 if (!prop_page) 1619 if (!prop_page)
1606 return NULL; 1620 return NULL;
1607 1621
1608 /* Priority 0xa0, Group-1, disabled */ 1622 gic_reset_prop_table(page_address(prop_page));
1609 memset(page_address(prop_page),
1610 LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1,
1611 LPI_PROPBASE_SZ);
1612
1613 /* Make sure the GIC will observe the written configuration */
1614 gic_flush_dcache_to_poc(page_address(prop_page), LPI_PROPBASE_SZ);
1615 1623
1616 return prop_page; 1624 return prop_page;
1617} 1625}
@@ -1622,20 +1630,74 @@ static void its_free_prop_table(struct page *prop_page)
1622 get_order(LPI_PROPBASE_SZ)); 1630 get_order(LPI_PROPBASE_SZ));
1623} 1631}
1624 1632
1625static int __init its_alloc_lpi_tables(void) 1633static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size)
1626{ 1634{
1627 phys_addr_t paddr; 1635 phys_addr_t start, end, addr_end;
1636 u64 i;
1628 1637
1629 lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gic_rdists->gicd_typer), 1638 /*
1630 ITS_MAX_LPI_NRBITS); 1639 * We don't bother checking for a kdump kernel as by
1631 gic_rdists->prop_page = its_allocate_prop_table(GFP_NOWAIT); 1640 * construction, the LPI tables are out of this kernel's
1632 if (!gic_rdists->prop_page) { 1641 * memory map.
1633 pr_err("Failed to allocate PROPBASE\n"); 1642 */
1634 return -ENOMEM; 1643 if (is_kdump_kernel())
1644 return true;
1645
1646 addr_end = addr + size - 1;
1647
1648 for_each_reserved_mem_region(i, &start, &end) {
1649 if (addr >= start && addr_end <= end)
1650 return true;
1651 }
1652
1653 /* Not found, not a good sign... */
1654 pr_warn("GICv3: Expected reserved range [%pa:%pa], not found\n",
1655 &addr, &addr_end);
1656 add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
1657 return false;
1658}
1659
1660static int gic_reserve_range(phys_addr_t addr, unsigned long size)
1661{
1662 if (efi_enabled(EFI_CONFIG_TABLES))
1663 return efi_mem_reserve_persistent(addr, size);
1664
1665 return 0;
1666}
1667
1668static int __init its_setup_lpi_prop_table(void)
1669{
1670 if (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED) {
1671 u64 val;
1672
1673 val = gicr_read_propbaser(gic_data_rdist_rd_base() + GICR_PROPBASER);
1674 lpi_id_bits = (val & GICR_PROPBASER_IDBITS_MASK) + 1;
1675
1676 gic_rdists->prop_table_pa = val & GENMASK_ULL(51, 12);
1677 gic_rdists->prop_table_va = memremap(gic_rdists->prop_table_pa,
1678 LPI_PROPBASE_SZ,
1679 MEMREMAP_WB);
1680 gic_reset_prop_table(gic_rdists->prop_table_va);
1681 } else {
1682 struct page *page;
1683
1684 lpi_id_bits = min_t(u32,
1685 GICD_TYPER_ID_BITS(gic_rdists->gicd_typer),
1686 ITS_MAX_LPI_NRBITS);
1687 page = its_allocate_prop_table(GFP_NOWAIT);
1688 if (!page) {
1689 pr_err("Failed to allocate PROPBASE\n");
1690 return -ENOMEM;
1691 }
1692
1693 gic_rdists->prop_table_pa = page_to_phys(page);
1694 gic_rdists->prop_table_va = page_address(page);
1695 WARN_ON(gic_reserve_range(gic_rdists->prop_table_pa,
1696 LPI_PROPBASE_SZ));
1635 } 1697 }
1636 1698
1637 paddr = page_to_phys(gic_rdists->prop_page); 1699 pr_info("GICv3: using LPI property table @%pa\n",
1638 pr_info("GIC: using LPI property table @%pa\n", &paddr); 1700 &gic_rdists->prop_table_pa);
1639 1701
1640 return its_lpi_init(lpi_id_bits); 1702 return its_lpi_init(lpi_id_bits);
1641} 1703}
@@ -1924,12 +1986,9 @@ static int its_alloc_collections(struct its_node *its)
1924static struct page *its_allocate_pending_table(gfp_t gfp_flags) 1986static struct page *its_allocate_pending_table(gfp_t gfp_flags)
1925{ 1987{
1926 struct page *pend_page; 1988 struct page *pend_page;
1927 /* 1989
1928 * The pending pages have to be at least 64kB aligned,
1929 * hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
1930 */
1931 pend_page = alloc_pages(gfp_flags | __GFP_ZERO, 1990 pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
1932 get_order(max_t(u32, LPI_PENDBASE_SZ, SZ_64K))); 1991 get_order(LPI_PENDBASE_SZ));
1933 if (!pend_page) 1992 if (!pend_page)
1934 return NULL; 1993 return NULL;
1935 1994
@@ -1941,36 +2000,103 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
1941 2000
1942static void its_free_pending_table(struct page *pt) 2001static void its_free_pending_table(struct page *pt)
1943{ 2002{
1944 free_pages((unsigned long)page_address(pt), 2003 free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ));
1945 get_order(max_t(u32, LPI_PENDBASE_SZ, SZ_64K))); 2004}
2005
2006/*
2007 * Booting with kdump and LPIs enabled is generally fine. Any other
2008 * case is wrong in the absence of firmware/EFI support.
2009 */
2010static bool enabled_lpis_allowed(void)
2011{
2012 phys_addr_t addr;
2013 u64 val;
2014
2015 /* Check whether the property table is in a reserved region */
2016 val = gicr_read_propbaser(gic_data_rdist_rd_base() + GICR_PROPBASER);
2017 addr = val & GENMASK_ULL(51, 12);
2018
2019 return gic_check_reserved_range(addr, LPI_PROPBASE_SZ);
2020}
2021
2022static int __init allocate_lpi_tables(void)
2023{
2024 u64 val;
2025 int err, cpu;
2026
2027 /*
2028 * If LPIs are enabled while we run this from the boot CPU,
2029 * flag the RD tables as pre-allocated if the stars do align.
2030 */
2031 val = readl_relaxed(gic_data_rdist_rd_base() + GICR_CTLR);
2032 if ((val & GICR_CTLR_ENABLE_LPIS) && enabled_lpis_allowed()) {
2033 gic_rdists->flags |= (RDIST_FLAGS_RD_TABLES_PREALLOCATED |
2034 RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING);
2035 pr_info("GICv3: Using preallocated redistributor tables\n");
2036 }
2037
2038 err = its_setup_lpi_prop_table();
2039 if (err)
2040 return err;
2041
2042 /*
2043 * We allocate all the pending tables anyway, as we may have a
2044 * mix of RDs that have had LPIs enabled, and some that
2045 * don't. We'll free the unused ones as each CPU comes online.
2046 */
2047 for_each_possible_cpu(cpu) {
2048 struct page *pend_page;
2049
2050 pend_page = its_allocate_pending_table(GFP_NOWAIT);
2051 if (!pend_page) {
2052 pr_err("Failed to allocate PENDBASE for CPU%d\n", cpu);
2053 return -ENOMEM;
2054 }
2055
2056 gic_data_rdist_cpu(cpu)->pend_page = pend_page;
2057 }
2058
2059 return 0;
1946} 2060}
1947 2061
1948static void its_cpu_init_lpis(void) 2062static void its_cpu_init_lpis(void)
1949{ 2063{
1950 void __iomem *rbase = gic_data_rdist_rd_base(); 2064 void __iomem *rbase = gic_data_rdist_rd_base();
1951 struct page *pend_page; 2065 struct page *pend_page;
2066 phys_addr_t paddr;
1952 u64 val, tmp; 2067 u64 val, tmp;
1953 2068
1954 /* If we didn't allocate the pending table yet, do it now */ 2069 if (gic_data_rdist()->lpi_enabled)
1955 pend_page = gic_data_rdist()->pend_page; 2070 return;
1956 if (!pend_page) {
1957 phys_addr_t paddr;
1958 2071
1959 pend_page = its_allocate_pending_table(GFP_NOWAIT); 2072 val = readl_relaxed(rbase + GICR_CTLR);
1960 if (!pend_page) { 2073 if ((gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED) &&
1961 pr_err("Failed to allocate PENDBASE for CPU%d\n", 2074 (val & GICR_CTLR_ENABLE_LPIS)) {
1962 smp_processor_id()); 2075 /*
1963 return; 2076 * Check that we get the same property table on all
1964 } 2077 * RDs. If we don't, this is hopeless.
2078 */
2079 paddr = gicr_read_propbaser(rbase + GICR_PROPBASER);
2080 paddr &= GENMASK_ULL(51, 12);
2081 if (WARN_ON(gic_rdists->prop_table_pa != paddr))
2082 add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
2083
2084 paddr = gicr_read_pendbaser(rbase + GICR_PENDBASER);
2085 paddr &= GENMASK_ULL(51, 16);
1965 2086
1966 paddr = page_to_phys(pend_page); 2087 WARN_ON(!gic_check_reserved_range(paddr, LPI_PENDBASE_SZ));
1967 pr_info("CPU%d: using LPI pending table @%pa\n", 2088 its_free_pending_table(gic_data_rdist()->pend_page);
1968 smp_processor_id(), &paddr); 2089 gic_data_rdist()->pend_page = NULL;
1969 gic_data_rdist()->pend_page = pend_page; 2090
2091 goto out;
1970 } 2092 }
1971 2093
2094 pend_page = gic_data_rdist()->pend_page;
2095 paddr = page_to_phys(pend_page);
2096 WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ));
2097
1972 /* set PROPBASE */ 2098 /* set PROPBASE */
1973 val = (page_to_phys(gic_rdists->prop_page) | 2099 val = (gic_rdists->prop_table_pa |
1974 GICR_PROPBASER_InnerShareable | 2100 GICR_PROPBASER_InnerShareable |
1975 GICR_PROPBASER_RaWaWb | 2101 GICR_PROPBASER_RaWaWb |
1976 ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); 2102 ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
@@ -2020,6 +2146,12 @@ static void its_cpu_init_lpis(void)
2020 2146
2021 /* Make sure the GIC has seen the above */ 2147 /* Make sure the GIC has seen the above */
2022 dsb(sy); 2148 dsb(sy);
2149out:
2150 gic_data_rdist()->lpi_enabled = true;
2151 pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
2152 smp_processor_id(),
2153 gic_data_rdist()->pend_page ? "allocated" : "reserved",
2154 &paddr);
2023} 2155}
2024 2156
2025static void its_cpu_init_collection(struct its_node *its) 2157static void its_cpu_init_collection(struct its_node *its)
@@ -3498,16 +3630,6 @@ static int redist_disable_lpis(void)
3498 u64 timeout = USEC_PER_SEC; 3630 u64 timeout = USEC_PER_SEC;
3499 u64 val; 3631 u64 val;
3500 3632
3501 /*
3502 * If coming via a CPU hotplug event, we don't need to disable
3503 * LPIs before trying to re-enable them. They are already
3504 * configured and all is well in the world. Detect this case
3505 * by checking the allocation of the pending table for the
3506 * current CPU.
3507 */
3508 if (gic_data_rdist()->pend_page)
3509 return 0;
3510
3511 if (!gic_rdists_supports_plpis()) { 3633 if (!gic_rdists_supports_plpis()) {
3512 pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); 3634 pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
3513 return -ENXIO; 3635 return -ENXIO;
@@ -3517,7 +3639,21 @@ static int redist_disable_lpis(void)
3517 if (!(val & GICR_CTLR_ENABLE_LPIS)) 3639 if (!(val & GICR_CTLR_ENABLE_LPIS))
3518 return 0; 3640 return 0;
3519 3641
3520 pr_warn("CPU%d: Booted with LPIs enabled, memory probably corrupted\n", 3642 /*
3643 * If coming via a CPU hotplug event, we don't need to disable
3644 * LPIs before trying to re-enable them. They are already
3645 * configured and all is well in the world.
3646 *
3647 * If running with preallocated tables, there is nothing to do.
3648 */
3649 if (gic_data_rdist()->lpi_enabled ||
3650 (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED))
3651 return 0;
3652
3653 /*
3654 * From that point on, we only try to do some damage control.
3655 */
3656 pr_warn("GICv3: CPU%d: Booted with LPIs enabled, memory probably corrupted\n",
3521 smp_processor_id()); 3657 smp_processor_id());
3522 add_taint(TAINT_CRAP, LOCKDEP_STILL_OK); 3658 add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
3523 3659
@@ -3773,7 +3909,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
3773 } 3909 }
3774 3910
3775 gic_rdists = rdists; 3911 gic_rdists = rdists;
3776 err = its_alloc_lpi_tables(); 3912
3913 err = allocate_lpi_tables();
3777 if (err) 3914 if (err)
3778 return err; 3915 return err;
3779 3916
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index d5912f1ec884..8f87f40c9460 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -348,48 +348,45 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
348{ 348{
349 u32 irqnr; 349 u32 irqnr;
350 350
351 do { 351 irqnr = gic_read_iar();
352 irqnr = gic_read_iar();
353 352
354 if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) { 353 if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
355 int err; 354 int err;
356 355
357 if (static_branch_likely(&supports_deactivate_key)) 356 if (static_branch_likely(&supports_deactivate_key))
357 gic_write_eoir(irqnr);
358 else
359 isb();
360
361 err = handle_domain_irq(gic_data.domain, irqnr, regs);
362 if (err) {
363 WARN_ONCE(true, "Unexpected interrupt received!\n");
364 if (static_branch_likely(&supports_deactivate_key)) {
365 if (irqnr < 8192)
366 gic_write_dir(irqnr);
367 } else {
358 gic_write_eoir(irqnr); 368 gic_write_eoir(irqnr);
359 else
360 isb();
361
362 err = handle_domain_irq(gic_data.domain, irqnr, regs);
363 if (err) {
364 WARN_ONCE(true, "Unexpected interrupt received!\n");
365 if (static_branch_likely(&supports_deactivate_key)) {
366 if (irqnr < 8192)
367 gic_write_dir(irqnr);
368 } else {
369 gic_write_eoir(irqnr);
370 }
371 } 369 }
372 continue;
373 } 370 }
374 if (irqnr < 16) { 371 return;
375 gic_write_eoir(irqnr); 372 }
376 if (static_branch_likely(&supports_deactivate_key)) 373 if (irqnr < 16) {
377 gic_write_dir(irqnr); 374 gic_write_eoir(irqnr);
375 if (static_branch_likely(&supports_deactivate_key))
376 gic_write_dir(irqnr);
378#ifdef CONFIG_SMP 377#ifdef CONFIG_SMP
379 /* 378 /*
380 * Unlike GICv2, we don't need an smp_rmb() here. 379 * Unlike GICv2, we don't need an smp_rmb() here.
381 * The control dependency from gic_read_iar to 380 * The control dependency from gic_read_iar to
382 * the ISB in gic_write_eoir is enough to ensure 381 * the ISB in gic_write_eoir is enough to ensure
383 * that any shared data read by handle_IPI will 382 * that any shared data read by handle_IPI will
384 * be read after the ACK. 383 * be read after the ACK.
385 */ 384 */
386 handle_IPI(irqnr, regs); 385 handle_IPI(irqnr, regs);
387#else 386#else
388 WARN_ONCE(true, "Unexpected SGI received!\n"); 387 WARN_ONCE(true, "Unexpected SGI received!\n");
389#endif 388#endif
390 continue; 389 }
391 }
392 } while (irqnr != ICC_IAR1_EL1_SPURIOUS);
393} 390}
394 391
395static void __init gic_dist_init(void) 392static void __init gic_dist_init(void)
@@ -653,7 +650,9 @@ early_param("irqchip.gicv3_nolpi", gicv3_nolpi_cfg);
653 650
654static int gic_dist_supports_lpis(void) 651static int gic_dist_supports_lpis(void)
655{ 652{
656 return !!(readl_relaxed(gic_data.dist_base + GICD_TYPER) & GICD_TYPER_LPIS) && !gicv3_nolpi; 653 return (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) &&
654 !!(readl_relaxed(gic_data.dist_base + GICD_TYPER) & GICD_TYPER_LPIS) &&
655 !gicv3_nolpi);
657} 656}
658 657
659static void gic_cpu_init(void) 658static void gic_cpu_init(void)
@@ -673,10 +672,6 @@ static void gic_cpu_init(void)
673 672
674 gic_cpu_config(rbase, gic_redist_wait_for_rwp); 673 gic_cpu_config(rbase, gic_redist_wait_for_rwp);
675 674
676 /* Give LPIs a spin */
677 if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
678 its_cpu_init();
679
680 /* initialise system registers */ 675 /* initialise system registers */
681 gic_cpu_sys_reg_init(); 676 gic_cpu_sys_reg_init();
682} 677}
@@ -689,6 +684,10 @@ static void gic_cpu_init(void)
689static int gic_starting_cpu(unsigned int cpu) 684static int gic_starting_cpu(unsigned int cpu)
690{ 685{
691 gic_cpu_init(); 686 gic_cpu_init();
687
688 if (gic_dist_supports_lpis())
689 its_cpu_init();
690
692 return 0; 691 return 0;
693} 692}
694 693
@@ -1127,14 +1126,16 @@ static int __init gic_init_bases(void __iomem *dist_base,
1127 1126
1128 gic_update_vlpi_properties(); 1127 gic_update_vlpi_properties();
1129 1128
1130 if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
1131 its_init(handle, &gic_data.rdists, gic_data.domain);
1132
1133 gic_smp_init(); 1129 gic_smp_init();
1134 gic_dist_init(); 1130 gic_dist_init();
1135 gic_cpu_init(); 1131 gic_cpu_init();
1136 gic_cpu_pm_init(); 1132 gic_cpu_pm_init();
1137 1133
1134 if (gic_dist_supports_lpis()) {
1135 its_init(handle, &gic_data.rdists, gic_data.domain);
1136 its_cpu_init();
1137 }
1138
1138 return 0; 1139 return 0;
1139 1140
1140out_free: 1141out_free:
diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c
index 13063339b416..547045d89c4b 100644
--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -13,6 +13,7 @@
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/irqchip.h> 14#include <linux/irqchip.h>
15#include <linux/irqdomain.h> 15#include <linux/irqdomain.h>
16#include <linux/jump_label.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
17#include <linux/msi.h> 18#include <linux/msi.h>
18#include <linux/of_irq.h> 19#include <linux/of_irq.h>
@@ -26,6 +27,10 @@
26#define ICU_SETSPI_NSR_AH 0x14 27#define ICU_SETSPI_NSR_AH 0x14
27#define ICU_CLRSPI_NSR_AL 0x18 28#define ICU_CLRSPI_NSR_AL 0x18
28#define ICU_CLRSPI_NSR_AH 0x1c 29#define ICU_CLRSPI_NSR_AH 0x1c
30#define ICU_SET_SEI_AL 0x50
31#define ICU_SET_SEI_AH 0x54
32#define ICU_CLR_SEI_AL 0x58
33#define ICU_CLR_SEI_AH 0x5C
29#define ICU_INT_CFG(x) (0x100 + 4 * (x)) 34#define ICU_INT_CFG(x) (0x100 + 4 * (x))
30#define ICU_INT_ENABLE BIT(24) 35#define ICU_INT_ENABLE BIT(24)
31#define ICU_IS_EDGE BIT(28) 36#define ICU_IS_EDGE BIT(28)
@@ -36,12 +41,23 @@
36#define ICU_SATA0_ICU_ID 109 41#define ICU_SATA0_ICU_ID 109
37#define ICU_SATA1_ICU_ID 107 42#define ICU_SATA1_ICU_ID 107
38 43
44struct mvebu_icu_subset_data {
45 unsigned int icu_group;
46 unsigned int offset_set_ah;
47 unsigned int offset_set_al;
48 unsigned int offset_clr_ah;
49 unsigned int offset_clr_al;
50};
51
39struct mvebu_icu { 52struct mvebu_icu {
40 struct irq_chip irq_chip;
41 void __iomem *base; 53 void __iomem *base;
42 struct irq_domain *domain;
43 struct device *dev; 54 struct device *dev;
55};
56
57struct mvebu_icu_msi_data {
58 struct mvebu_icu *icu;
44 atomic_t initialized; 59 atomic_t initialized;
60 const struct mvebu_icu_subset_data *subset_data;
45}; 61};
46 62
47struct mvebu_icu_irq_data { 63struct mvebu_icu_irq_data {
@@ -50,28 +66,40 @@ struct mvebu_icu_irq_data {
50 unsigned int type; 66 unsigned int type;
51}; 67};
52 68
53static void mvebu_icu_init(struct mvebu_icu *icu, struct msi_msg *msg) 69DEFINE_STATIC_KEY_FALSE(legacy_bindings);
70
71static void mvebu_icu_init(struct mvebu_icu *icu,
72 struct mvebu_icu_msi_data *msi_data,
73 struct msi_msg *msg)
54{ 74{
55 if (atomic_cmpxchg(&icu->initialized, false, true)) 75 const struct mvebu_icu_subset_data *subset = msi_data->subset_data;
76
77 if (atomic_cmpxchg(&msi_data->initialized, false, true))
56 return; 78 return;
57 79
58 /* Set Clear/Set ICU SPI message address in AP */ 80 /* Set 'SET' ICU SPI message address in AP */
59 writel_relaxed(msg[0].address_hi, icu->base + ICU_SETSPI_NSR_AH); 81 writel_relaxed(msg[0].address_hi, icu->base + subset->offset_set_ah);
60 writel_relaxed(msg[0].address_lo, icu->base + ICU_SETSPI_NSR_AL); 82 writel_relaxed(msg[0].address_lo, icu->base + subset->offset_set_al);
61 writel_relaxed(msg[1].address_hi, icu->base + ICU_CLRSPI_NSR_AH); 83
62 writel_relaxed(msg[1].address_lo, icu->base + ICU_CLRSPI_NSR_AL); 84 if (subset->icu_group != ICU_GRP_NSR)
85 return;
86
87 /* Set 'CLEAR' ICU SPI message address in AP (level-MSI only) */
88 writel_relaxed(msg[1].address_hi, icu->base + subset->offset_clr_ah);
89 writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al);
63} 90}
64 91
65static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) 92static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
66{ 93{
67 struct irq_data *d = irq_get_irq_data(desc->irq); 94 struct irq_data *d = irq_get_irq_data(desc->irq);
95 struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d->domain);
68 struct mvebu_icu_irq_data *icu_irqd = d->chip_data; 96 struct mvebu_icu_irq_data *icu_irqd = d->chip_data;
69 struct mvebu_icu *icu = icu_irqd->icu; 97 struct mvebu_icu *icu = icu_irqd->icu;
70 unsigned int icu_int; 98 unsigned int icu_int;
71 99
72 if (msg->address_lo || msg->address_hi) { 100 if (msg->address_lo || msg->address_hi) {
73 /* One off initialization */ 101 /* One off initialization per domain */
74 mvebu_icu_init(icu, msg); 102 mvebu_icu_init(icu, msi_data, msg);
75 /* Configure the ICU with irq number & type */ 103 /* Configure the ICU with irq number & type */
76 icu_int = msg->data | ICU_INT_ENABLE; 104 icu_int = msg->data | ICU_INT_ENABLE;
77 if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) 105 if (icu_irqd->type & IRQ_TYPE_EDGE_RISING)
@@ -101,37 +129,66 @@ static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
101 } 129 }
102} 130}
103 131
132static struct irq_chip mvebu_icu_nsr_chip = {
133 .name = "ICU-NSR",
134 .irq_mask = irq_chip_mask_parent,
135 .irq_unmask = irq_chip_unmask_parent,
136 .irq_eoi = irq_chip_eoi_parent,
137 .irq_set_type = irq_chip_set_type_parent,
138 .irq_set_affinity = irq_chip_set_affinity_parent,
139};
140
141static struct irq_chip mvebu_icu_sei_chip = {
142 .name = "ICU-SEI",
143 .irq_ack = irq_chip_ack_parent,
144 .irq_mask = irq_chip_mask_parent,
145 .irq_unmask = irq_chip_unmask_parent,
146 .irq_set_type = irq_chip_set_type_parent,
147 .irq_set_affinity = irq_chip_set_affinity_parent,
148};
149
104static int 150static int
105mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, 151mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
106 unsigned long *hwirq, unsigned int *type) 152 unsigned long *hwirq, unsigned int *type)
107{ 153{
108 struct mvebu_icu *icu = d->host_data; 154 struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d);
109 unsigned int icu_group; 155 struct mvebu_icu *icu = platform_msi_get_host_data(d);
156 unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2;
110 157
111 /* Check the count of the parameters in dt */ 158 /* Check the count of the parameters in dt */
112 if (WARN_ON(fwspec->param_count < 3)) { 159 if (WARN_ON(fwspec->param_count != param_count)) {
113 dev_err(icu->dev, "wrong ICU parameter count %d\n", 160 dev_err(icu->dev, "wrong ICU parameter count %d\n",
114 fwspec->param_count); 161 fwspec->param_count);
115 return -EINVAL; 162 return -EINVAL;
116 } 163 }
117 164
118 /* Only ICU group type is handled */ 165 if (static_branch_unlikely(&legacy_bindings)) {
119 icu_group = fwspec->param[0]; 166 *hwirq = fwspec->param[1];
120 if (icu_group != ICU_GRP_NSR && icu_group != ICU_GRP_SR && 167 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
121 icu_group != ICU_GRP_SEI && icu_group != ICU_GRP_REI) { 168 if (fwspec->param[0] != ICU_GRP_NSR) {
122 dev_err(icu->dev, "wrong ICU group type %x\n", icu_group); 169 dev_err(icu->dev, "wrong ICU group type %x\n",
123 return -EINVAL; 170 fwspec->param[0]);
171 return -EINVAL;
172 }
173 } else {
174 *hwirq = fwspec->param[0];
175 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
176
177 /*
178 * The ICU receives level interrupts. While the NSR are also
179 * level interrupts, SEI are edge interrupts. Force the type
180 * here in this case. Please note that this makes the interrupt
181 * handling unreliable.
182 */
183 if (msi_data->subset_data->icu_group == ICU_GRP_SEI)
184 *type = IRQ_TYPE_EDGE_RISING;
124 } 185 }
125 186
126 *hwirq = fwspec->param[1];
127 if (*hwirq >= ICU_MAX_IRQS) { 187 if (*hwirq >= ICU_MAX_IRQS) {
128 dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq); 188 dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq);
129 return -EINVAL; 189 return -EINVAL;
130 } 190 }
131 191
132 /* Mask the type to prevent wrong DT configuration */
133 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
134
135 return 0; 192 return 0;
136} 193}
137 194
@@ -142,8 +199,10 @@ mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
142 int err; 199 int err;
143 unsigned long hwirq; 200 unsigned long hwirq;
144 struct irq_fwspec *fwspec = args; 201 struct irq_fwspec *fwspec = args;
145 struct mvebu_icu *icu = platform_msi_get_host_data(domain); 202 struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(domain);
203 struct mvebu_icu *icu = msi_data->icu;
146 struct mvebu_icu_irq_data *icu_irqd; 204 struct mvebu_icu_irq_data *icu_irqd;
205 struct irq_chip *chip = &mvebu_icu_nsr_chip;
147 206
148 icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL); 207 icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL);
149 if (!icu_irqd) 208 if (!icu_irqd)
@@ -156,7 +215,10 @@ mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
156 goto free_irqd; 215 goto free_irqd;
157 } 216 }
158 217
159 icu_irqd->icu_group = fwspec->param[0]; 218 if (static_branch_unlikely(&legacy_bindings))
219 icu_irqd->icu_group = fwspec->param[0];
220 else
221 icu_irqd->icu_group = msi_data->subset_data->icu_group;
160 icu_irqd->icu = icu; 222 icu_irqd->icu = icu;
161 223
162 err = platform_msi_domain_alloc(domain, virq, nr_irqs); 224 err = platform_msi_domain_alloc(domain, virq, nr_irqs);
@@ -170,8 +232,11 @@ mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
170 if (err) 232 if (err)
171 goto free_msi; 233 goto free_msi;
172 234
235 if (icu_irqd->icu_group == ICU_GRP_SEI)
236 chip = &mvebu_icu_sei_chip;
237
173 err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 238 err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
174 &icu->irq_chip, icu_irqd); 239 chip, icu_irqd);
175 if (err) { 240 if (err) {
176 dev_err(icu->dev, "failed to set the data to IRQ domain\n"); 241 dev_err(icu->dev, "failed to set the data to IRQ domain\n");
177 goto free_msi; 242 goto free_msi;
@@ -204,11 +269,84 @@ static const struct irq_domain_ops mvebu_icu_domain_ops = {
204 .free = mvebu_icu_irq_domain_free, 269 .free = mvebu_icu_irq_domain_free,
205}; 270};
206 271
272static const struct mvebu_icu_subset_data mvebu_icu_nsr_subset_data = {
273 .icu_group = ICU_GRP_NSR,
274 .offset_set_ah = ICU_SETSPI_NSR_AH,
275 .offset_set_al = ICU_SETSPI_NSR_AL,
276 .offset_clr_ah = ICU_CLRSPI_NSR_AH,
277 .offset_clr_al = ICU_CLRSPI_NSR_AL,
278};
279
280static const struct mvebu_icu_subset_data mvebu_icu_sei_subset_data = {
281 .icu_group = ICU_GRP_SEI,
282 .offset_set_ah = ICU_SET_SEI_AH,
283 .offset_set_al = ICU_SET_SEI_AL,
284};
285
286static const struct of_device_id mvebu_icu_subset_of_match[] = {
287 {
288 .compatible = "marvell,cp110-icu-nsr",
289 .data = &mvebu_icu_nsr_subset_data,
290 },
291 {
292 .compatible = "marvell,cp110-icu-sei",
293 .data = &mvebu_icu_sei_subset_data,
294 },
295 {},
296};
297
298static int mvebu_icu_subset_probe(struct platform_device *pdev)
299{
300 struct mvebu_icu_msi_data *msi_data;
301 struct device_node *msi_parent_dn;
302 struct device *dev = &pdev->dev;
303 struct irq_domain *irq_domain;
304
305 msi_data = devm_kzalloc(dev, sizeof(*msi_data), GFP_KERNEL);
306 if (!msi_data)
307 return -ENOMEM;
308
309 if (static_branch_unlikely(&legacy_bindings)) {
310 msi_data->icu = dev_get_drvdata(dev);
311 msi_data->subset_data = &mvebu_icu_nsr_subset_data;
312 } else {
313 msi_data->icu = dev_get_drvdata(dev->parent);
314 msi_data->subset_data = of_device_get_match_data(dev);
315 }
316
317 dev->msi_domain = of_msi_get_domain(dev, dev->of_node,
318 DOMAIN_BUS_PLATFORM_MSI);
319 if (!dev->msi_domain)
320 return -EPROBE_DEFER;
321
322 msi_parent_dn = irq_domain_get_of_node(dev->msi_domain);
323 if (!msi_parent_dn)
324 return -ENODEV;
325
326 irq_domain = platform_msi_create_device_tree_domain(dev, ICU_MAX_IRQS,
327 mvebu_icu_write_msg,
328 &mvebu_icu_domain_ops,
329 msi_data);
330 if (!irq_domain) {
331 dev_err(dev, "Failed to create ICU MSI domain\n");
332 return -ENOMEM;
333 }
334
335 return 0;
336}
337
338static struct platform_driver mvebu_icu_subset_driver = {
339 .probe = mvebu_icu_subset_probe,
340 .driver = {
341 .name = "mvebu-icu-subset",
342 .of_match_table = mvebu_icu_subset_of_match,
343 },
344};
345builtin_platform_driver(mvebu_icu_subset_driver);
346
207static int mvebu_icu_probe(struct platform_device *pdev) 347static int mvebu_icu_probe(struct platform_device *pdev)
208{ 348{
209 struct mvebu_icu *icu; 349 struct mvebu_icu *icu;
210 struct device_node *node = pdev->dev.of_node;
211 struct device_node *gicp_dn;
212 struct resource *res; 350 struct resource *res;
213 int i; 351 int i;
214 352
@@ -226,53 +364,38 @@ static int mvebu_icu_probe(struct platform_device *pdev)
226 return PTR_ERR(icu->base); 364 return PTR_ERR(icu->base);
227 } 365 }
228 366
229 icu->irq_chip.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
230 "ICU.%x",
231 (unsigned int)res->start);
232 if (!icu->irq_chip.name)
233 return -ENOMEM;
234
235 icu->irq_chip.irq_mask = irq_chip_mask_parent;
236 icu->irq_chip.irq_unmask = irq_chip_unmask_parent;
237 icu->irq_chip.irq_eoi = irq_chip_eoi_parent;
238 icu->irq_chip.irq_set_type = irq_chip_set_type_parent;
239#ifdef CONFIG_SMP
240 icu->irq_chip.irq_set_affinity = irq_chip_set_affinity_parent;
241#endif
242
243 /* 367 /*
244 * We're probed after MSI domains have been resolved, so force 368 * Legacy bindings: ICU is one node with one MSI parent: force manually
245 * resolution here. 369 * the probe of the NSR interrupts side.
370 * New bindings: ICU node has children, one per interrupt controller
371 * having its own MSI parent: call platform_populate().
372 * All ICU instances should use the same bindings.
246 */ 373 */
247 pdev->dev.msi_domain = of_msi_get_domain(&pdev->dev, node, 374 if (!of_get_child_count(pdev->dev.of_node))
248 DOMAIN_BUS_PLATFORM_MSI); 375 static_branch_enable(&legacy_bindings);
249 if (!pdev->dev.msi_domain)
250 return -EPROBE_DEFER;
251
252 gicp_dn = irq_domain_get_of_node(pdev->dev.msi_domain);
253 if (!gicp_dn)
254 return -ENODEV;
255 376
256 /* 377 /*
257 * Clean all ICU interrupts with type SPI_NSR, required to 378 * Clean all ICU interrupts of type NSR and SEI, required to
258 * avoid unpredictable SPI assignments done by firmware. 379 * avoid unpredictable SPI assignments done by firmware.
259 */ 380 */
260 for (i = 0 ; i < ICU_MAX_IRQS ; i++) { 381 for (i = 0 ; i < ICU_MAX_IRQS ; i++) {
261 u32 icu_int = readl_relaxed(icu->base + ICU_INT_CFG(i)); 382 u32 icu_int, icu_grp;
262 if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR) 383
384 icu_int = readl_relaxed(icu->base + ICU_INT_CFG(i));
385 icu_grp = icu_int >> ICU_GROUP_SHIFT;
386
387 if (icu_grp == ICU_GRP_NSR ||
388 (icu_grp == ICU_GRP_SEI &&
389 !static_branch_unlikely(&legacy_bindings)))
263 writel_relaxed(0x0, icu->base + ICU_INT_CFG(i)); 390 writel_relaxed(0x0, icu->base + ICU_INT_CFG(i));
264 } 391 }
265 392
266 icu->domain = 393 platform_set_drvdata(pdev, icu);
267 platform_msi_create_device_domain(&pdev->dev, ICU_MAX_IRQS,
268 mvebu_icu_write_msg,
269 &mvebu_icu_domain_ops, icu);
270 if (!icu->domain) {
271 dev_err(&pdev->dev, "Failed to create ICU domain\n");
272 return -ENOMEM;
273 }
274 394
275 return 0; 395 if (static_branch_unlikely(&legacy_bindings))
396 return mvebu_icu_subset_probe(pdev);
397 else
398 return devm_of_platform_populate(&pdev->dev);
276} 399}
277 400
278static const struct of_device_id mvebu_icu_of_match[] = { 401static const struct of_device_id mvebu_icu_of_match[] = {
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
new file mode 100644
index 000000000000..566d69a2edbc
--- /dev/null
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -0,0 +1,507 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#define pr_fmt(fmt) "mvebu-sei: " fmt
4
5#include <linux/interrupt.h>
6#include <linux/irq.h>
7#include <linux/irqchip.h>
8#include <linux/irqchip/chained_irq.h>
9#include <linux/irqdomain.h>
10#include <linux/kernel.h>
11#include <linux/msi.h>
12#include <linux/platform_device.h>
13#include <linux/of_address.h>
14#include <linux/of_irq.h>
15#include <linux/of_platform.h>
16
17/* Cause register */
18#define GICP_SECR(idx) (0x0 + ((idx) * 0x4))
19/* Mask register */
20#define GICP_SEMR(idx) (0x20 + ((idx) * 0x4))
21#define GICP_SET_SEI_OFFSET 0x30
22
23#define SEI_IRQ_COUNT_PER_REG 32
24#define SEI_IRQ_REG_COUNT 2
25#define SEI_IRQ_COUNT (SEI_IRQ_COUNT_PER_REG * SEI_IRQ_REG_COUNT)
26#define SEI_IRQ_REG_IDX(irq_id) ((irq_id) / SEI_IRQ_COUNT_PER_REG)
27#define SEI_IRQ_REG_BIT(irq_id) ((irq_id) % SEI_IRQ_COUNT_PER_REG)
28
29struct mvebu_sei_interrupt_range {
30 u32 first;
31 u32 size;
32};
33
34struct mvebu_sei_caps {
35 struct mvebu_sei_interrupt_range ap_range;
36 struct mvebu_sei_interrupt_range cp_range;
37};
38
39struct mvebu_sei {
40 struct device *dev;
41 void __iomem *base;
42 struct resource *res;
43 struct irq_domain *sei_domain;
44 struct irq_domain *ap_domain;
45 struct irq_domain *cp_domain;
46 const struct mvebu_sei_caps *caps;
47
48 /* Lock on MSI allocations/releases */
49 struct mutex cp_msi_lock;
50 DECLARE_BITMAP(cp_msi_bitmap, SEI_IRQ_COUNT);
51
52 /* Lock on IRQ masking register */
53 raw_spinlock_t mask_lock;
54};
55
56static void mvebu_sei_ack_irq(struct irq_data *d)
57{
58 struct mvebu_sei *sei = irq_data_get_irq_chip_data(d);
59 u32 reg_idx = SEI_IRQ_REG_IDX(d->hwirq);
60
61 writel_relaxed(BIT(SEI_IRQ_REG_BIT(d->hwirq)),
62 sei->base + GICP_SECR(reg_idx));
63}
64
65static void mvebu_sei_mask_irq(struct irq_data *d)
66{
67 struct mvebu_sei *sei = irq_data_get_irq_chip_data(d);
68 u32 reg, reg_idx = SEI_IRQ_REG_IDX(d->hwirq);
69 unsigned long flags;
70
71 /* 1 disables the interrupt */
72 raw_spin_lock_irqsave(&sei->mask_lock, flags);
73 reg = readl_relaxed(sei->base + GICP_SEMR(reg_idx));
74 reg |= BIT(SEI_IRQ_REG_BIT(d->hwirq));
75 writel_relaxed(reg, sei->base + GICP_SEMR(reg_idx));
76 raw_spin_unlock_irqrestore(&sei->mask_lock, flags);
77}
78
79static void mvebu_sei_unmask_irq(struct irq_data *d)
80{
81 struct mvebu_sei *sei = irq_data_get_irq_chip_data(d);
82 u32 reg, reg_idx = SEI_IRQ_REG_IDX(d->hwirq);
83 unsigned long flags;
84
85 /* 0 enables the interrupt */
86 raw_spin_lock_irqsave(&sei->mask_lock, flags);
87 reg = readl_relaxed(sei->base + GICP_SEMR(reg_idx));
88 reg &= ~BIT(SEI_IRQ_REG_BIT(d->hwirq));
89 writel_relaxed(reg, sei->base + GICP_SEMR(reg_idx));
90 raw_spin_unlock_irqrestore(&sei->mask_lock, flags);
91}
92
93static int mvebu_sei_set_affinity(struct irq_data *d,
94 const struct cpumask *mask_val,
95 bool force)
96{
97 return -EINVAL;
98}
99
100static int mvebu_sei_set_irqchip_state(struct irq_data *d,
101 enum irqchip_irq_state which,
102 bool state)
103{
104 /* We can only clear the pending state by acking the interrupt */
105 if (which != IRQCHIP_STATE_PENDING || state)
106 return -EINVAL;
107
108 mvebu_sei_ack_irq(d);
109 return 0;
110}
111
112static struct irq_chip mvebu_sei_irq_chip = {
113 .name = "SEI",
114 .irq_ack = mvebu_sei_ack_irq,
115 .irq_mask = mvebu_sei_mask_irq,
116 .irq_unmask = mvebu_sei_unmask_irq,
117 .irq_set_affinity = mvebu_sei_set_affinity,
118 .irq_set_irqchip_state = mvebu_sei_set_irqchip_state,
119};
120
121static int mvebu_sei_ap_set_type(struct irq_data *data, unsigned int type)
122{
123 if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_HIGH)
124 return -EINVAL;
125
126 return 0;
127}
128
129static struct irq_chip mvebu_sei_ap_irq_chip = {
130 .name = "AP SEI",
131 .irq_ack = irq_chip_ack_parent,
132 .irq_mask = irq_chip_mask_parent,
133 .irq_unmask = irq_chip_unmask_parent,
134 .irq_set_affinity = irq_chip_set_affinity_parent,
135 .irq_set_type = mvebu_sei_ap_set_type,
136};
137
138static void mvebu_sei_cp_compose_msi_msg(struct irq_data *data,
139 struct msi_msg *msg)
140{
141 struct mvebu_sei *sei = data->chip_data;
142 phys_addr_t set = sei->res->start + GICP_SET_SEI_OFFSET;
143
144 msg->data = data->hwirq + sei->caps->cp_range.first;
145 msg->address_lo = lower_32_bits(set);
146 msg->address_hi = upper_32_bits(set);
147}
148
149static int mvebu_sei_cp_set_type(struct irq_data *data, unsigned int type)
150{
151 if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_EDGE_RISING)
152 return -EINVAL;
153
154 return 0;
155}
156
157static struct irq_chip mvebu_sei_cp_irq_chip = {
158 .name = "CP SEI",
159 .irq_ack = irq_chip_ack_parent,
160 .irq_mask = irq_chip_mask_parent,
161 .irq_unmask = irq_chip_unmask_parent,
162 .irq_set_affinity = irq_chip_set_affinity_parent,
163 .irq_set_type = mvebu_sei_cp_set_type,
164 .irq_compose_msi_msg = mvebu_sei_cp_compose_msi_msg,
165};
166
167static int mvebu_sei_domain_alloc(struct irq_domain *domain, unsigned int virq,
168 unsigned int nr_irqs, void *arg)
169{
170 struct mvebu_sei *sei = domain->host_data;
171 struct irq_fwspec *fwspec = arg;
172
173 /* Not much to do, just setup the irqdata */
174 irq_domain_set_hwirq_and_chip(domain, virq, fwspec->param[0],
175 &mvebu_sei_irq_chip, sei);
176
177 return 0;
178}
179
180static void mvebu_sei_domain_free(struct irq_domain *domain, unsigned int virq,
181 unsigned int nr_irqs)
182{
183 int i;
184
185 for (i = 0; i < nr_irqs; i++) {
186 struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
187 irq_set_handler(virq + i, NULL);
188 irq_domain_reset_irq_data(d);
189 }
190}
191
192static const struct irq_domain_ops mvebu_sei_domain_ops = {
193 .alloc = mvebu_sei_domain_alloc,
194 .free = mvebu_sei_domain_free,
195};
196
197static int mvebu_sei_ap_translate(struct irq_domain *domain,
198 struct irq_fwspec *fwspec,
199 unsigned long *hwirq,
200 unsigned int *type)
201{
202 *hwirq = fwspec->param[0];
203 *type = IRQ_TYPE_LEVEL_HIGH;
204
205 return 0;
206}
207
208static int mvebu_sei_ap_alloc(struct irq_domain *domain, unsigned int virq,
209 unsigned int nr_irqs, void *arg)
210{
211 struct mvebu_sei *sei = domain->host_data;
212 struct irq_fwspec fwspec;
213 unsigned long hwirq;
214 unsigned int type;
215 int err;
216
217 mvebu_sei_ap_translate(domain, arg, &hwirq, &type);
218
219 fwspec.fwnode = domain->parent->fwnode;
220 fwspec.param_count = 1;
221 fwspec.param[0] = hwirq + sei->caps->ap_range.first;
222
223 err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
224 if (err)
225 return err;
226
227 irq_domain_set_info(domain, virq, hwirq,
228 &mvebu_sei_ap_irq_chip, sei,
229 handle_level_irq, NULL, NULL);
230 irq_set_probe(virq);
231
232 return 0;
233}
234
235static const struct irq_domain_ops mvebu_sei_ap_domain_ops = {
236 .translate = mvebu_sei_ap_translate,
237 .alloc = mvebu_sei_ap_alloc,
238 .free = irq_domain_free_irqs_parent,
239};
240
241static void mvebu_sei_cp_release_irq(struct mvebu_sei *sei, unsigned long hwirq)
242{
243 mutex_lock(&sei->cp_msi_lock);
244 clear_bit(hwirq, sei->cp_msi_bitmap);
245 mutex_unlock(&sei->cp_msi_lock);
246}
247
248static int mvebu_sei_cp_domain_alloc(struct irq_domain *domain,
249 unsigned int virq, unsigned int nr_irqs,
250 void *args)
251{
252 struct mvebu_sei *sei = domain->host_data;
253 struct irq_fwspec fwspec;
254 unsigned long hwirq;
255 int ret;
256
257 /* The software only supports single allocations for now */
258 if (nr_irqs != 1)
259 return -ENOTSUPP;
260
261 mutex_lock(&sei->cp_msi_lock);
262 hwirq = find_first_zero_bit(sei->cp_msi_bitmap,
263 sei->caps->cp_range.size);
264 if (hwirq < sei->caps->cp_range.size)
265 set_bit(hwirq, sei->cp_msi_bitmap);
266 mutex_unlock(&sei->cp_msi_lock);
267
268 if (hwirq == sei->caps->cp_range.size)
269 return -ENOSPC;
270
271 fwspec.fwnode = domain->parent->fwnode;
272 fwspec.param_count = 1;
273 fwspec.param[0] = hwirq + sei->caps->cp_range.first;
274
275 ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
276 if (ret)
277 goto free_irq;
278
279 irq_domain_set_info(domain, virq, hwirq,
280 &mvebu_sei_cp_irq_chip, sei,
281 handle_edge_irq, NULL, NULL);
282
283 return 0;
284
285free_irq:
286 mvebu_sei_cp_release_irq(sei, hwirq);
287 return ret;
288}
289
290static void mvebu_sei_cp_domain_free(struct irq_domain *domain,
291 unsigned int virq, unsigned int nr_irqs)
292{
293 struct mvebu_sei *sei = domain->host_data;
294 struct irq_data *d = irq_domain_get_irq_data(domain, virq);
295
296 if (nr_irqs != 1 || d->hwirq >= sei->caps->cp_range.size) {
297 dev_err(sei->dev, "Invalid hwirq %lu\n", d->hwirq);
298 return;
299 }
300
301 mvebu_sei_cp_release_irq(sei, d->hwirq);
302 irq_domain_free_irqs_parent(domain, virq, 1);
303}
304
305static const struct irq_domain_ops mvebu_sei_cp_domain_ops = {
306 .alloc = mvebu_sei_cp_domain_alloc,
307 .free = mvebu_sei_cp_domain_free,
308};
309
310static struct irq_chip mvebu_sei_msi_irq_chip = {
311 .name = "SEI pMSI",
312 .irq_ack = irq_chip_ack_parent,
313 .irq_set_type = irq_chip_set_type_parent,
314};
315
316static struct msi_domain_ops mvebu_sei_msi_ops = {
317};
318
319static struct msi_domain_info mvebu_sei_msi_domain_info = {
320 .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS,
321 .ops = &mvebu_sei_msi_ops,
322 .chip = &mvebu_sei_msi_irq_chip,
323};
324
325static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
326{
327 struct mvebu_sei *sei = irq_desc_get_handler_data(desc);
328 struct irq_chip *chip = irq_desc_get_chip(desc);
329 u32 idx;
330
331 chained_irq_enter(chip, desc);
332
333 for (idx = 0; idx < SEI_IRQ_REG_COUNT; idx++) {
334 unsigned long irqmap;
335 int bit;
336
337 irqmap = readl_relaxed(sei->base + GICP_SECR(idx));
338 for_each_set_bit(bit, &irqmap, SEI_IRQ_COUNT_PER_REG) {
339 unsigned long hwirq;
340 unsigned int virq;
341
342 hwirq = idx * SEI_IRQ_COUNT_PER_REG + bit;
343 virq = irq_find_mapping(sei->sei_domain, hwirq);
344 if (likely(virq)) {
345 generic_handle_irq(virq);
346 continue;
347 }
348
349 dev_warn(sei->dev,
350 "Spurious IRQ detected (hwirq %lu)\n", hwirq);
351 }
352 }
353
354 chained_irq_exit(chip, desc);
355}
356
357static void mvebu_sei_reset(struct mvebu_sei *sei)
358{
359 u32 reg_idx;
360
361 /* Clear IRQ cause registers, mask all interrupts */
362 for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) {
363 writel_relaxed(0xFFFFFFFF, sei->base + GICP_SECR(reg_idx));
364 writel_relaxed(0xFFFFFFFF, sei->base + GICP_SEMR(reg_idx));
365 }
366}
367
368static int mvebu_sei_probe(struct platform_device *pdev)
369{
370 struct device_node *node = pdev->dev.of_node;
371 struct irq_domain *plat_domain;
372 struct mvebu_sei *sei;
373 u32 parent_irq;
374 int ret;
375
376 sei = devm_kzalloc(&pdev->dev, sizeof(*sei), GFP_KERNEL);
377 if (!sei)
378 return -ENOMEM;
379
380 sei->dev = &pdev->dev;
381
382 mutex_init(&sei->cp_msi_lock);
383 raw_spin_lock_init(&sei->mask_lock);
384
385 sei->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386 sei->base = devm_ioremap_resource(sei->dev, sei->res);
387 if (!sei->base) {
388 dev_err(sei->dev, "Failed to remap SEI resource\n");
389 return -ENODEV;
390 }
391
392 /* Retrieve the SEI capabilities with the interrupt ranges */
393 sei->caps = of_device_get_match_data(&pdev->dev);
394 if (!sei->caps) {
395 dev_err(sei->dev,
396 "Could not retrieve controller capabilities\n");
397 return -EINVAL;
398 }
399
400 /*
401 * Reserve the single (top-level) parent SPI IRQ from which all the
402 * interrupts handled by this driver will be signaled.
403 */
404 parent_irq = irq_of_parse_and_map(node, 0);
405 if (parent_irq <= 0) {
406 dev_err(sei->dev, "Failed to retrieve top-level SPI IRQ\n");
407 return -ENODEV;
408 }
409
410 /* Create the root SEI domain */
411 sei->sei_domain = irq_domain_create_linear(of_node_to_fwnode(node),
412 (sei->caps->ap_range.size +
413 sei->caps->cp_range.size),
414 &mvebu_sei_domain_ops,
415 sei);
416 if (!sei->sei_domain) {
417 dev_err(sei->dev, "Failed to create SEI IRQ domain\n");
418 ret = -ENOMEM;
419 goto dispose_irq;
420 }
421
422 irq_domain_update_bus_token(sei->sei_domain, DOMAIN_BUS_NEXUS);
423
424 /* Create the 'wired' domain */
425 sei->ap_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
426 sei->caps->ap_range.size,
427 of_node_to_fwnode(node),
428 &mvebu_sei_ap_domain_ops,
429 sei);
430 if (!sei->ap_domain) {
431 dev_err(sei->dev, "Failed to create AP IRQ domain\n");
432 ret = -ENOMEM;
433 goto remove_sei_domain;
434 }
435
436 irq_domain_update_bus_token(sei->ap_domain, DOMAIN_BUS_WIRED);
437
438 /* Create the 'MSI' domain */
439 sei->cp_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
440 sei->caps->cp_range.size,
441 of_node_to_fwnode(node),
442 &mvebu_sei_cp_domain_ops,
443 sei);
444 if (!sei->cp_domain) {
445 pr_err("Failed to create CPs IRQ domain\n");
446 ret = -ENOMEM;
447 goto remove_ap_domain;
448 }
449
450 irq_domain_update_bus_token(sei->cp_domain, DOMAIN_BUS_GENERIC_MSI);
451
452 plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
453 &mvebu_sei_msi_domain_info,
454 sei->cp_domain);
455 if (!plat_domain) {
456 pr_err("Failed to create CPs MSI domain\n");
457 ret = -ENOMEM;
458 goto remove_cp_domain;
459 }
460
461 mvebu_sei_reset(sei);
462
463 irq_set_chained_handler_and_data(parent_irq,
464 mvebu_sei_handle_cascade_irq,
465 sei);
466
467 return 0;
468
469remove_cp_domain:
470 irq_domain_remove(sei->cp_domain);
471remove_ap_domain:
472 irq_domain_remove(sei->ap_domain);
473remove_sei_domain:
474 irq_domain_remove(sei->sei_domain);
475dispose_irq:
476 irq_dispose_mapping(parent_irq);
477
478 return ret;
479}
480
481struct mvebu_sei_caps mvebu_sei_ap806_caps = {
482 .ap_range = {
483 .first = 0,
484 .size = 21,
485 },
486 .cp_range = {
487 .first = 21,
488 .size = 43,
489 },
490};
491
492static const struct of_device_id mvebu_sei_of_match[] = {
493 {
494 .compatible = "marvell,ap806-sei",
495 .data = &mvebu_sei_ap806_caps,
496 },
497 {},
498};
499
500static struct platform_driver mvebu_sei_driver = {
501 .probe = mvebu_sei_probe,
502 .driver = {
503 .name = "mvebu-sei",
504 .of_match_table = mvebu_sei_of_match,
505 },
506};
507builtin_platform_driver(mvebu_sei_driver);
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index b1b47a40a278..faa7d61b9d6c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -124,6 +124,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
124 break; 124 break;
125 case IRQ_TYPE_EDGE_BOTH: 125 case IRQ_TYPE_EDGE_BOTH:
126 pdc_type = PDC_EDGE_DUAL; 126 pdc_type = PDC_EDGE_DUAL;
127 type = IRQ_TYPE_EDGE_RISING;
127 break; 128 break;
128 case IRQ_TYPE_LEVEL_HIGH: 129 case IRQ_TYPE_LEVEL_HIGH:
129 pdc_type = PDC_LEVEL_HIGH; 130 pdc_type = PDC_LEVEL_HIGH;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index eeceac3376fc..1d6711c28271 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -45,7 +45,7 @@
45 * IRQF_PERCPU - Interrupt is per cpu 45 * IRQF_PERCPU - Interrupt is per cpu
46 * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing 46 * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
47 * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is 47 * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
48 * registered first in an shared interrupt is considered for 48 * registered first in a shared interrupt is considered for
49 * performance reasons) 49 * performance reasons)
50 * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished. 50 * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
51 * Used by threaded interrupts which need to keep the 51 * Used by threaded interrupts which need to keep the
diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
index 0a83b4379f34..9a1a479a2bf4 100644
--- a/include/linux/irqchip/arm-gic-common.h
+++ b/include/linux/irqchip/arm-gic-common.h
@@ -13,6 +13,12 @@
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/ioport.h> 14#include <linux/ioport.h>
15 15
16#define GICD_INT_DEF_PRI 0xa0
17#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\
18 (GICD_INT_DEF_PRI << 16) |\
19 (GICD_INT_DEF_PRI << 8) |\
20 GICD_INT_DEF_PRI)
21
16enum gic_type { 22enum gic_type {
17 GIC_V2, 23 GIC_V2,
18 GIC_V3, 24 GIC_V3,
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 8bdbb5f29494..c2a7b863fc2e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -585,8 +585,10 @@ struct rdists {
585 void __iomem *rd_base; 585 void __iomem *rd_base;
586 struct page *pend_page; 586 struct page *pend_page;
587 phys_addr_t phys_base; 587 phys_addr_t phys_base;
588 bool lpi_enabled;
588 } __percpu *rdist; 589 } __percpu *rdist;
589 struct page *prop_page; 590 phys_addr_t prop_table_pa;
591 void *prop_table_va;
590 u64 flags; 592 u64 flags;
591 u32 gicd_typer; 593 u32 gicd_typer;
592 bool has_vlpis; 594 bool has_vlpis;
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 6c4aaf04046c..626179077bb0 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -65,11 +65,6 @@
65#define GICD_INT_EN_CLR_X32 0xffffffff 65#define GICD_INT_EN_CLR_X32 0xffffffff
66#define GICD_INT_EN_SET_SGI 0x0000ffff 66#define GICD_INT_EN_SET_SGI 0x0000ffff
67#define GICD_INT_EN_CLR_PPI 0xffff0000 67#define GICD_INT_EN_CLR_PPI 0xffff0000
68#define GICD_INT_DEF_PRI 0xa0
69#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\
70 (GICD_INT_DEF_PRI << 16) |\
71 (GICD_INT_DEF_PRI << 8) |\
72 GICD_INT_DEF_PRI)
73 68
74#define GICD_IIDR_IMPLEMENTER_SHIFT 0 69#define GICD_IIDR_IMPLEMENTER_SHIFT 0
75#define GICD_IIDR_IMPLEMENTER_MASK (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT) 70#define GICD_IIDR_IMPLEMENTER_MASK (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index dccfa65aee96..068aa46f0d55 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -75,6 +75,7 @@ struct irq_fwspec {
75enum irq_domain_bus_token { 75enum irq_domain_bus_token {
76 DOMAIN_BUS_ANY = 0, 76 DOMAIN_BUS_ANY = 0,
77 DOMAIN_BUS_WIRED, 77 DOMAIN_BUS_WIRED,
78 DOMAIN_BUS_GENERIC_MSI,
78 DOMAIN_BUS_PCI_MSI, 79 DOMAIN_BUS_PCI_MSI,
79 DOMAIN_BUS_PLATFORM_MSI, 80 DOMAIN_BUS_PLATFORM_MSI,
80 DOMAIN_BUS_NEXUS, 81 DOMAIN_BUS_NEXUS,
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 5839d8062dfc..0e9c50052ff3 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -317,11 +317,18 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
317int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, 317int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
318 int virq, int nvec, msi_alloc_info_t *args); 318 int virq, int nvec, msi_alloc_info_t *args);
319struct irq_domain * 319struct irq_domain *
320platform_msi_create_device_domain(struct device *dev, 320__platform_msi_create_device_domain(struct device *dev,
321 unsigned int nvec, 321 unsigned int nvec,
322 irq_write_msi_msg_t write_msi_msg, 322 bool is_tree,
323 const struct irq_domain_ops *ops, 323 irq_write_msi_msg_t write_msi_msg,
324 void *host_data); 324 const struct irq_domain_ops *ops,
325 void *host_data);
326
327#define platform_msi_create_device_domain(dev, nvec, write, ops, data) \
328 __platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
329#define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
330 __platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
331
325int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, 332int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
326 unsigned int nr_irqs); 333 unsigned int nr_irqs);
327void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq, 334void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 5d9fc01b60a6..3366d11c3e02 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -183,7 +183,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
183 * unhappy about. Replace them with ':', which does 183 * unhappy about. Replace them with ':', which does
184 * the trick and is not as offensive as '\'... 184 * the trick and is not as offensive as '\'...
185 */ 185 */
186 name = kstrdup(of_node_full_name(of_node), GFP_KERNEL); 186 name = kasprintf(GFP_KERNEL, "%pOF", of_node);
187 if (!name) { 187 if (!name) {
188 kfree(domain); 188 kfree(domain);
189 return NULL; 189 return NULL;
@@ -867,7 +867,7 @@ void irq_dispose_mapping(unsigned int virq)
867EXPORT_SYMBOL_GPL(irq_dispose_mapping); 867EXPORT_SYMBOL_GPL(irq_dispose_mapping);
868 868
869/** 869/**
870 * irq_find_mapping() - Find a linux irq from an hw irq number. 870 * irq_find_mapping() - Find a linux irq from a hw irq number.
871 * @domain: domain owning this hardware interrupt 871 * @domain: domain owning this hardware interrupt
872 * @hwirq: hardware irq number in that domain space 872 * @hwirq: hardware irq number in that domain space
873 */ 873 */
@@ -1741,6 +1741,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d)
1741static void debugfs_remove_domain_dir(struct irq_domain *d) 1741static void debugfs_remove_domain_dir(struct irq_domain *d)
1742{ 1742{
1743 debugfs_remove(d->debugfs_file); 1743 debugfs_remove(d->debugfs_file);
1744 d->debugfs_file = NULL;
1744} 1745}
1745 1746
1746void __init irq_domain_debugfs_init(struct dentry *root) 1747void __init irq_domain_debugfs_init(struct dentry *root)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index fb86146037a7..9dbdccab3b6a 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -927,6 +927,9 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
927 927
928 local_bh_disable(); 928 local_bh_disable();
929 ret = action->thread_fn(action->irq, action->dev_id); 929 ret = action->thread_fn(action->irq, action->dev_id);
930 if (ret == IRQ_HANDLED)
931 atomic_inc(&desc->threads_handled);
932
930 irq_finalize_oneshot(desc, action); 933 irq_finalize_oneshot(desc, action);
931 local_bh_enable(); 934 local_bh_enable();
932 return ret; 935 return ret;
@@ -943,6 +946,9 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
943 irqreturn_t ret; 946 irqreturn_t ret;
944 947
945 ret = action->thread_fn(action->irq, action->dev_id); 948 ret = action->thread_fn(action->irq, action->dev_id);
949 if (ret == IRQ_HANDLED)
950 atomic_inc(&desc->threads_handled);
951
946 irq_finalize_oneshot(desc, action); 952 irq_finalize_oneshot(desc, action);
947 return ret; 953 return ret;
948} 954}
@@ -1020,8 +1026,6 @@ static int irq_thread(void *data)
1020 irq_thread_check_affinity(desc, action); 1026 irq_thread_check_affinity(desc, action);
1021 1027
1022 action_ret = handler_fn(desc, action); 1028 action_ret = handler_fn(desc, action);
1023 if (action_ret == IRQ_HANDLED)
1024 atomic_inc(&desc->threads_handled);
1025 if (action_ret == IRQ_WAKE_THREAD) 1029 if (action_ret == IRQ_WAKE_THREAD)
1026 irq_wake_secondary(desc, action); 1030 irq_wake_secondary(desc, action);
1027 1031
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 7a0720a20003..d28813306b2c 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -257,9 +257,9 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
257 int softirq_bit; 257 int softirq_bit;
258 258
259 /* 259 /*
260 * Mask out PF_MEMALLOC s current task context is borrowed for the 260 * Mask out PF_MEMALLOC as the current task context is borrowed for the
261 * softirq. A softirq handled such as network RX might set PF_MEMALLOC 261 * softirq. A softirq handled, such as network RX, might set PF_MEMALLOC
262 * again if the socket is related to swap 262 * again if the socket is related to swapping.
263 */ 263 */
264 current->flags &= ~PF_MEMALLOC; 264 current->flags &= ~PF_MEMALLOC;
265 265