diff options
-rw-r--r-- | drivers/irqchip/irq-mvebu-gicp.c | 38 | ||||
-rw-r--r-- | drivers/irqchip/irq-mvebu-gicp.h | 12 | ||||
-rw-r--r-- | drivers/irqchip/irq-mvebu-icu.c | 33 |
3 files changed, 28 insertions, 55 deletions
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c index 17a4a7b6cdbb..4e17f7081efc 100644 --- a/drivers/irqchip/irq-mvebu-gicp.c +++ b/drivers/irqchip/irq-mvebu-gicp.c | |||
@@ -19,8 +19,6 @@ | |||
19 | 19 | ||
20 | #include <dt-bindings/interrupt-controller/arm-gic.h> | 20 | #include <dt-bindings/interrupt-controller/arm-gic.h> |
21 | 21 | ||
22 | #include "irq-mvebu-gicp.h" | ||
23 | |||
24 | #define GICP_SETSPI_NSR_OFFSET 0x0 | 22 | #define GICP_SETSPI_NSR_OFFSET 0x0 |
25 | #define GICP_CLRSPI_NSR_OFFSET 0x8 | 23 | #define GICP_CLRSPI_NSR_OFFSET 0x8 |
26 | 24 | ||
@@ -55,34 +53,18 @@ static int gicp_idx_to_spi(struct mvebu_gicp *gicp, int idx) | |||
55 | return -EINVAL; | 53 | return -EINVAL; |
56 | } | 54 | } |
57 | 55 | ||
58 | int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, | ||
59 | phys_addr_t *clrspi) | ||
60 | { | ||
61 | struct platform_device *pdev; | ||
62 | struct mvebu_gicp *gicp; | ||
63 | |||
64 | pdev = of_find_device_by_node(dn); | ||
65 | if (!pdev) | ||
66 | return -ENODEV; | ||
67 | |||
68 | gicp = platform_get_drvdata(pdev); | ||
69 | if (!gicp) | ||
70 | return -ENODEV; | ||
71 | |||
72 | *setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; | ||
73 | *clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | 56 | static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) |
79 | { | 57 | { |
80 | struct mvebu_gicp *gicp = data->chip_data; | 58 | struct mvebu_gicp *gicp = data->chip_data; |
81 | phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; | 59 | phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; |
82 | 60 | phys_addr_t clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; | |
83 | msg->data = data->hwirq; | 61 | |
84 | msg->address_lo = lower_32_bits(setspi); | 62 | msg[0].data = data->hwirq; |
85 | msg->address_hi = upper_32_bits(setspi); | 63 | msg[0].address_lo = lower_32_bits(setspi); |
64 | msg[0].address_hi = upper_32_bits(setspi); | ||
65 | msg[1].data = data->hwirq; | ||
66 | msg[1].address_lo = lower_32_bits(clrspi); | ||
67 | msg[1].address_hi = upper_32_bits(clrspi); | ||
86 | } | 68 | } |
87 | 69 | ||
88 | static struct irq_chip gicp_irq_chip = { | 70 | static struct irq_chip gicp_irq_chip = { |
@@ -170,13 +152,15 @@ static const struct irq_domain_ops gicp_domain_ops = { | |||
170 | static struct irq_chip gicp_msi_irq_chip = { | 152 | static struct irq_chip gicp_msi_irq_chip = { |
171 | .name = "GICP", | 153 | .name = "GICP", |
172 | .irq_set_type = irq_chip_set_type_parent, | 154 | .irq_set_type = irq_chip_set_type_parent, |
155 | .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, | ||
173 | }; | 156 | }; |
174 | 157 | ||
175 | static struct msi_domain_ops gicp_msi_ops = { | 158 | static struct msi_domain_ops gicp_msi_ops = { |
176 | }; | 159 | }; |
177 | 160 | ||
178 | static struct msi_domain_info gicp_msi_domain_info = { | 161 | static struct msi_domain_info gicp_msi_domain_info = { |
179 | .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), | 162 | .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | |
163 | MSI_FLAG_LEVEL_CAPABLE), | ||
180 | .ops = &gicp_msi_ops, | 164 | .ops = &gicp_msi_ops, |
181 | .chip = &gicp_msi_irq_chip, | 165 | .chip = &gicp_msi_irq_chip, |
182 | }; | 166 | }; |
diff --git a/drivers/irqchip/irq-mvebu-gicp.h b/drivers/irqchip/irq-mvebu-gicp.h deleted file mode 100644 index eaa12fb72102..000000000000 --- a/drivers/irqchip/irq-mvebu-gicp.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef __MVEBU_GICP_H__ | ||
3 | #define __MVEBU_GICP_H__ | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | |||
7 | struct device_node; | ||
8 | |||
9 | int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, | ||
10 | phys_addr_t *clrspi); | ||
11 | |||
12 | #endif /* __MVEBU_GICP_H__ */ | ||
diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c index e18c48d3a92e..13063339b416 100644 --- a/drivers/irqchip/irq-mvebu-icu.c +++ b/drivers/irqchip/irq-mvebu-icu.c | |||
@@ -21,8 +21,6 @@ | |||
21 | 21 | ||
22 | #include <dt-bindings/interrupt-controller/mvebu-icu.h> | 22 | #include <dt-bindings/interrupt-controller/mvebu-icu.h> |
23 | 23 | ||
24 | #include "irq-mvebu-gicp.h" | ||
25 | |||
26 | /* ICU registers */ | 24 | /* ICU registers */ |
27 | #define ICU_SETSPI_NSR_AL 0x10 | 25 | #define ICU_SETSPI_NSR_AL 0x10 |
28 | #define ICU_SETSPI_NSR_AH 0x14 | 26 | #define ICU_SETSPI_NSR_AH 0x14 |
@@ -43,6 +41,7 @@ struct mvebu_icu { | |||
43 | void __iomem *base; | 41 | void __iomem *base; |
44 | struct irq_domain *domain; | 42 | struct irq_domain *domain; |
45 | struct device *dev; | 43 | struct device *dev; |
44 | atomic_t initialized; | ||
46 | }; | 45 | }; |
47 | 46 | ||
48 | struct mvebu_icu_irq_data { | 47 | struct mvebu_icu_irq_data { |
@@ -51,6 +50,18 @@ struct mvebu_icu_irq_data { | |||
51 | unsigned int type; | 50 | unsigned int type; |
52 | }; | 51 | }; |
53 | 52 | ||
53 | static void mvebu_icu_init(struct mvebu_icu *icu, struct msi_msg *msg) | ||
54 | { | ||
55 | if (atomic_cmpxchg(&icu->initialized, false, true)) | ||
56 | return; | ||
57 | |||
58 | /* Set Clear/Set ICU SPI message address in AP */ | ||
59 | writel_relaxed(msg[0].address_hi, icu->base + ICU_SETSPI_NSR_AH); | ||
60 | writel_relaxed(msg[0].address_lo, icu->base + ICU_SETSPI_NSR_AL); | ||
61 | writel_relaxed(msg[1].address_hi, icu->base + ICU_CLRSPI_NSR_AH); | ||
62 | writel_relaxed(msg[1].address_lo, icu->base + ICU_CLRSPI_NSR_AL); | ||
63 | } | ||
64 | |||
54 | static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) | 65 | static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) |
55 | { | 66 | { |
56 | struct irq_data *d = irq_get_irq_data(desc->irq); | 67 | struct irq_data *d = irq_get_irq_data(desc->irq); |
@@ -59,6 +70,8 @@ static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) | |||
59 | unsigned int icu_int; | 70 | unsigned int icu_int; |
60 | 71 | ||
61 | if (msg->address_lo || msg->address_hi) { | 72 | if (msg->address_lo || msg->address_hi) { |
73 | /* One off initialization */ | ||
74 | mvebu_icu_init(icu, msg); | ||
62 | /* Configure the ICU with irq number & type */ | 75 | /* Configure the ICU with irq number & type */ |
63 | icu_int = msg->data | ICU_INT_ENABLE; | 76 | icu_int = msg->data | ICU_INT_ENABLE; |
64 | if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) | 77 | if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) |
@@ -197,9 +210,7 @@ static int mvebu_icu_probe(struct platform_device *pdev) | |||
197 | struct device_node *node = pdev->dev.of_node; | 210 | struct device_node *node = pdev->dev.of_node; |
198 | struct device_node *gicp_dn; | 211 | struct device_node *gicp_dn; |
199 | struct resource *res; | 212 | struct resource *res; |
200 | phys_addr_t setspi, clrspi; | 213 | int i; |
201 | u32 i, icu_int; | ||
202 | int ret; | ||
203 | 214 | ||
204 | icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu), | 215 | icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu), |
205 | GFP_KERNEL); | 216 | GFP_KERNEL); |
@@ -242,22 +253,12 @@ static int mvebu_icu_probe(struct platform_device *pdev) | |||
242 | if (!gicp_dn) | 253 | if (!gicp_dn) |
243 | return -ENODEV; | 254 | return -ENODEV; |
244 | 255 | ||
245 | ret = mvebu_gicp_get_doorbells(gicp_dn, &setspi, &clrspi); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | /* Set Clear/Set ICU SPI message address in AP */ | ||
250 | writel_relaxed(upper_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AH); | ||
251 | writel_relaxed(lower_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AL); | ||
252 | writel_relaxed(upper_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AH); | ||
253 | writel_relaxed(lower_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AL); | ||
254 | |||
255 | /* | 256 | /* |
256 | * Clean all ICU interrupts with type SPI_NSR, required to | 257 | * Clean all ICU interrupts with type SPI_NSR, required to |
257 | * avoid unpredictable SPI assignments done by firmware. | 258 | * avoid unpredictable SPI assignments done by firmware. |
258 | */ | 259 | */ |
259 | for (i = 0 ; i < ICU_MAX_IRQS ; i++) { | 260 | for (i = 0 ; i < ICU_MAX_IRQS ; i++) { |
260 | icu_int = readl(icu->base + ICU_INT_CFG(i)); | 261 | u32 icu_int = readl_relaxed(icu->base + ICU_INT_CFG(i)); |
261 | if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR) | 262 | if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR) |
262 | writel_relaxed(0x0, icu->base + ICU_INT_CFG(i)); | 263 | writel_relaxed(0x0, icu->base + ICU_INT_CFG(i)); |
263 | } | 264 | } |