18c9fd4e15612f759c7f5f2c5dd53d7280d78d3b
[openwrt/staging/hauke.git] / target / linux / ath79 / patches-4.14 / 0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
1 From cb376159800b9b44be76949c3aee89eb06d29faa Mon Sep 17 00:00:00 2001
2 From: John Crispin <john@phrozen.org>
3 Date: Tue, 6 Mar 2018 09:55:13 +0100
4 Subject: [PATCH 07/27] irqchip/irq-ath79-intc: add irq cascade driver for
5 QCA9556 SoCs
6
7 Signed-off-by: John Crispin <john@phrozen.org>
8 ---
9 drivers/irqchip/Makefile | 1 +
10 drivers/irqchip/irq-ath79-intc.c | 104 +++++++++++++++++++++++++++++++++++++++
11 2 files changed, 105 insertions(+)
12 create mode 100644 drivers/irqchip/irq-ath79-intc.c
13
14 diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
15 index d27e3e3619e0..f63c94a92e25 100644
16 --- a/drivers/irqchip/Makefile
17 +++ b/drivers/irqchip/Makefile
18 @@ -3,6 +3,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o
19
20 obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o
21 obj-$(CONFIG_ATH79) += irq-ath79-cpu.o
22 +obj-$(CONFIG_ATH79) += irq-ath79-intc.o
23 obj-$(CONFIG_ATH79) += irq-ath79-misc.o
24 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
25 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
26 diff --git a/drivers/irqchip/irq-ath79-intc.c b/drivers/irqchip/irq-ath79-intc.c
27 new file mode 100644
28 index 000000000000..a26d3efe6e10
29 --- /dev/null
30 +++ b/drivers/irqchip/irq-ath79-intc.c
31 @@ -0,0 +1,104 @@
32 +/*
33 + * Atheros AR71xx/AR724x/AR913x specific interrupt handling
34 + *
35 + * Copyright (C) 2018 John Crispin <john@phrozen.org>
36 + *
37 + * This program is free software; you can redistribute it and/or modify it
38 + * under the terms of the GNU General Public License version 2 as published
39 + * by the Free Software Foundation.
40 + */
41 +
42 +#include <linux/interrupt.h>
43 +#include <linux/irqchip.h>
44 +#include <linux/of.h>
45 +#include <linux/of_irq.h>
46 +#include <linux/irqdomain.h>
47 +
48 +#include <asm/irq_cpu.h>
49 +#include <asm/mach-ath79/ath79.h>
50 +#include <asm/mach-ath79/ar71xx_regs.h>
51 +
52 +#define ATH79_MAX_INTC_CASCADE 3
53 +
54 +struct ath79_intc {
55 + struct irq_chip chip;
56 + u32 irq;
57 + u32 pending_mask;
58 + u32 irq_mask[ATH79_MAX_INTC_CASCADE];
59 +};
60 +
61 +static void ath79_intc_irq_handler(struct irq_desc *desc)
62 +{
63 + struct irq_domain *domain = irq_desc_get_handler_data(desc);
64 + struct ath79_intc *intc = domain->host_data;
65 + u32 pending;
66 +
67 + pending = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
68 + pending &= intc->pending_mask;
69 +
70 + if (pending) {
71 + int i;
72 +
73 + for (i = 0; i < domain->hwirq_max; i++)
74 + if (pending & intc->irq_mask[i])
75 + generic_handle_irq(irq_find_mapping(domain, i));
76 + } else {
77 + spurious_interrupt();
78 + }
79 +}
80 +
81 +static void ath79_intc_irq_unmask(struct irq_data *d)
82 +{
83 +}
84 +
85 +static void ath79_intc_irq_mask(struct irq_data *d)
86 +{
87 +}
88 +
89 +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
90 +{
91 + struct ath79_intc *intc = d->host_data;
92 +
93 + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq);
94 +
95 + return 0;
96 +}
97 +
98 +static const struct irq_domain_ops ath79_irq_domain_ops = {
99 + .xlate = irq_domain_xlate_onecell,
100 + .map = ath79_intc_map,
101 +};
102 +
103 +static int __init qca9556_intc_of_init(
104 + struct device_node *node, struct device_node *parent)
105 +{
106 + struct irq_domain *domain;
107 + struct ath79_intc *intc;
108 + int cnt, i;
109 +
110 + cnt = of_property_count_u32_elems(node, "qcom,pending-bits");
111 + if (cnt > ATH79_MAX_INTC_CASCADE)
112 + panic("Too many INTC pending bits\n");
113 +
114 + intc = kzalloc(sizeof(*intc), GFP_KERNEL);
115 + if (!intc)
116 + panic("Failed to allocate INTC memory\n");
117 + intc->chip.name = "INTC";
118 + intc->chip.irq_unmask = ath79_intc_irq_unmask,
119 + intc->chip.irq_mask = ath79_intc_irq_mask,
120 +
121 + of_property_read_u32_array(node, "qcom,pending-bits", intc->irq_mask, cnt);
122 + for (i = 0; i < cnt; i++)
123 + intc->pending_mask |= intc->irq_mask[i];
124 +
125 + intc->irq = irq_of_parse_and_map(node, 0);
126 + if (!intc->irq)
127 + panic("Failed to get INTC IRQ");
128 +
129 + domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc);
130 + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain);
131 +
132 + return 0;
133 +}
134 +IRQCHIP_DECLARE(qca9556_intc, "qcom,qca9556-intc",
135 + qca9556_intc_of_init);
136 --
137 2.11.0
138