summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/irqchip/irq-mvebu-gicp.c38
-rw-r--r--drivers/irqchip/irq-mvebu-gicp.h12
-rw-r--r--drivers/irqchip/irq-mvebu-icu.c33
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
58int 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
78static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 56static 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
88static struct irq_chip gicp_irq_chip = { 70static struct irq_chip gicp_irq_chip = {
@@ -170,13 +152,15 @@ static const struct irq_domain_ops gicp_domain_ops = {
170static struct irq_chip gicp_msi_irq_chip = { 152static 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
175static struct msi_domain_ops gicp_msi_ops = { 158static struct msi_domain_ops gicp_msi_ops = {
176}; 159};
177 160
178static struct msi_domain_info gicp_msi_domain_info = { 161static 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
7struct device_node;
8
9int 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
48struct mvebu_icu_irq_data { 47struct 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
53static 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
54static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) 65static 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 }