arm: dts: bcm2711-rpi-4-b: Adds respeaker 4mic nodes
[platform/kernel/linux-rpi.git] / drivers / irqchip / irq-bcm2836.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Root interrupt controller for the BCM2836 (Raspberry Pi 2).
4  *
5  * Copyright 2015 Broadcom
6  */
7
8 #include <linux/cpu.h>
9 #include <linux/of_address.h>
10 #include <linux/of_irq.h>
11 #include <linux/irqchip.h>
12 #include <linux/irqdomain.h>
13 #include <linux/irqchip/chained_irq.h>
14 #include <linux/irqchip/irq-bcm2836.h>
15
16 #include <asm/exception.h>
17
18 struct bcm2836_arm_irqchip_intc {
19         struct irq_domain *domain;
20         void __iomem *base;
21 };
22
23 static struct bcm2836_arm_irqchip_intc intc  __read_mostly;
24
25 void __iomem *arm_local_intc;
26 EXPORT_SYMBOL_GPL(arm_local_intc);
27
28 static void bcm2836_arm_irqchip_mask_per_cpu_irq(unsigned int reg_offset,
29                                                  unsigned int bit,
30                                                  int cpu)
31 {
32         void __iomem *reg = intc.base + reg_offset + 4 * cpu;
33
34         writel(readl(reg) & ~BIT(bit), reg);
35 }
36
37 static void bcm2836_arm_irqchip_unmask_per_cpu_irq(unsigned int reg_offset,
38                                                    unsigned int bit,
39                                                  int cpu)
40 {
41         void __iomem *reg = intc.base + reg_offset + 4 * cpu;
42
43         writel(readl(reg) | BIT(bit), reg);
44 }
45
46 static void bcm2836_arm_irqchip_mask_timer_irq(struct irq_data *d)
47 {
48         bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
49                                              d->hwirq - LOCAL_IRQ_CNTPSIRQ,
50                                              smp_processor_id());
51 }
52
53 static void bcm2836_arm_irqchip_unmask_timer_irq(struct irq_data *d)
54 {
55         bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
56                                                d->hwirq - LOCAL_IRQ_CNTPSIRQ,
57                                                smp_processor_id());
58 }
59
60 static struct irq_chip bcm2836_arm_irqchip_timer = {
61         .name           = "bcm2836-timer",
62         .irq_mask       = bcm2836_arm_irqchip_mask_timer_irq,
63         .irq_unmask     = bcm2836_arm_irqchip_unmask_timer_irq,
64 };
65
66 static void bcm2836_arm_irqchip_mask_pmu_irq(struct irq_data *d)
67 {
68         writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_CLR);
69 }
70
71 static void bcm2836_arm_irqchip_unmask_pmu_irq(struct irq_data *d)
72 {
73         writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_SET);
74 }
75
76 static struct irq_chip bcm2836_arm_irqchip_pmu = {
77         .name           = "bcm2836-pmu",
78         .irq_mask       = bcm2836_arm_irqchip_mask_pmu_irq,
79         .irq_unmask     = bcm2836_arm_irqchip_unmask_pmu_irq,
80 };
81
82 static void bcm2836_arm_irqchip_mask_gpu_irq(struct irq_data *d)
83 {
84 }
85
86 static void bcm2836_arm_irqchip_unmask_gpu_irq(struct irq_data *d)
87 {
88 }
89
90 #ifdef CONFIG_ARM64
91
92 void bcm2836_arm_irqchip_spin_gpu_irq(void)
93 {
94         u32 i;
95         void __iomem *gpurouting = (intc.base + LOCAL_GPU_ROUTING);
96         u32 routing_val = readl(gpurouting);
97
98         for (i = 1; i <= 3; i++) {
99                 u32 new_routing_val = (routing_val + i) & 3;
100
101                 if (cpu_active(new_routing_val)) {
102                         writel(new_routing_val, gpurouting);
103                         return;
104                 }
105         }
106 }
107 EXPORT_SYMBOL(bcm2836_arm_irqchip_spin_gpu_irq);
108
109 #endif
110
111 static struct irq_chip bcm2836_arm_irqchip_gpu = {
112         .name           = "bcm2836-gpu",
113         .irq_mask       = bcm2836_arm_irqchip_mask_gpu_irq,
114         .irq_unmask     = bcm2836_arm_irqchip_unmask_gpu_irq,
115 };
116
117 static void bcm2836_arm_irqchip_dummy_op(struct irq_data *d)
118 {
119 }
120
121 static struct irq_chip bcm2836_arm_irqchip_dummy = {
122         .name           = "bcm2836-dummy",
123         .irq_eoi        = bcm2836_arm_irqchip_dummy_op,
124 };
125
126 static int bcm2836_map(struct irq_domain *d, unsigned int irq,
127                        irq_hw_number_t hw)
128 {
129         struct irq_chip *chip;
130
131         switch (hw) {
132         case LOCAL_IRQ_MAILBOX0:
133                 chip = &bcm2836_arm_irqchip_dummy;
134                 break;
135         case LOCAL_IRQ_CNTPSIRQ:
136         case LOCAL_IRQ_CNTPNSIRQ:
137         case LOCAL_IRQ_CNTHPIRQ:
138         case LOCAL_IRQ_CNTVIRQ:
139                 chip = &bcm2836_arm_irqchip_timer;
140                 break;
141         case LOCAL_IRQ_GPU_FAST:
142                 chip = &bcm2836_arm_irqchip_gpu;
143                 break;
144         case LOCAL_IRQ_PMU_FAST:
145                 chip = &bcm2836_arm_irqchip_pmu;
146                 break;
147         default:
148                 pr_warn_once("Unexpected hw irq: %lu\n", hw);
149                 return -EINVAL;
150         }
151
152         irq_set_percpu_devid(irq);
153         irq_domain_set_info(d, irq, hw, chip, d->host_data,
154                             handle_percpu_devid_irq, NULL, NULL);
155         irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW);
156
157         return 0;
158 }
159
160 static void
161 __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
162 {
163         int cpu = smp_processor_id();
164         u32 stat;
165
166         stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
167         if (stat) {
168                 u32 hwirq = ffs(stat) - 1;
169
170                 handle_domain_irq(intc.domain, hwirq, regs);
171         }
172 }
173
174 #ifdef CONFIG_SMP
175 static struct irq_domain *ipi_domain;
176
177 static void bcm2836_arm_irqchip_handle_ipi(struct irq_desc *desc)
178 {
179         struct irq_chip *chip = irq_desc_get_chip(desc);
180         int cpu = smp_processor_id();
181         u32 mbox_val;
182
183         chained_irq_enter(chip, desc);
184
185         mbox_val = readl_relaxed(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
186         if (mbox_val) {
187                 int hwirq = ffs(mbox_val) - 1;
188                 generic_handle_domain_irq(ipi_domain, hwirq);
189         }
190
191         chained_irq_exit(chip, desc);
192 }
193
194 static void bcm2836_arm_irqchip_ipi_ack(struct irq_data *d)
195 {
196         int cpu = smp_processor_id();
197
198         writel_relaxed(BIT(d->hwirq),
199                        intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
200 }
201
202 static void bcm2836_arm_irqchip_ipi_send_mask(struct irq_data *d,
203                                               const struct cpumask *mask)
204 {
205         int cpu;
206         void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
207
208         /*
209          * Ensure that stores to normal memory are visible to the
210          * other CPUs before issuing the IPI.
211          */
212         smp_wmb();
213
214         for_each_cpu(cpu, mask)
215                 writel_relaxed(BIT(d->hwirq), mailbox0_base + 16 * cpu);
216 }
217
218 static struct irq_chip bcm2836_arm_irqchip_ipi = {
219         .name           = "IPI",
220         .irq_mask       = bcm2836_arm_irqchip_dummy_op,
221         .irq_unmask     = bcm2836_arm_irqchip_dummy_op,
222         .irq_ack        = bcm2836_arm_irqchip_ipi_ack,
223         .ipi_send_mask  = bcm2836_arm_irqchip_ipi_send_mask,
224 };
225
226 static int bcm2836_arm_irqchip_ipi_alloc(struct irq_domain *d,
227                                          unsigned int virq,
228                                          unsigned int nr_irqs, void *args)
229 {
230         int i;
231
232         for (i = 0; i < nr_irqs; i++) {
233                 irq_set_percpu_devid(virq + i);
234                 irq_domain_set_info(d, virq + i, i, &bcm2836_arm_irqchip_ipi,
235                                     d->host_data,
236                                     handle_percpu_devid_irq,
237                                     NULL, NULL);
238         }
239
240         return 0;
241 }
242
243 static void bcm2836_arm_irqchip_ipi_free(struct irq_domain *d,
244                                          unsigned int virq,
245                                          unsigned int nr_irqs)
246 {
247         /* Not freeing IPIs */
248 }
249
250 static const struct irq_domain_ops ipi_domain_ops = {
251         .alloc  = bcm2836_arm_irqchip_ipi_alloc,
252         .free   = bcm2836_arm_irqchip_ipi_free,
253 };
254
255 static int bcm2836_cpu_starting(unsigned int cpu)
256 {
257         bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
258                                                cpu);
259         return 0;
260 }
261
262 static int bcm2836_cpu_dying(unsigned int cpu)
263 {
264         bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
265                                              cpu);
266         return 0;
267 }
268
269 #define BITS_PER_MBOX   32
270
271 static void __init bcm2836_arm_irqchip_smp_init(void)
272 {
273         struct irq_fwspec ipi_fwspec = {
274                 .fwnode         = intc.domain->fwnode,
275                 .param_count    = 1,
276                 .param          = {
277                         [0]     = LOCAL_IRQ_MAILBOX0,
278                 },
279         };
280         int base_ipi, mux_irq;
281
282         mux_irq = irq_create_fwspec_mapping(&ipi_fwspec);
283         if (WARN_ON(mux_irq <= 0))
284                 return;
285
286         ipi_domain = irq_domain_create_linear(intc.domain->fwnode,
287                                               BITS_PER_MBOX, &ipi_domain_ops,
288                                               NULL);
289         if (WARN_ON(!ipi_domain))
290                 return;
291
292         ipi_domain->flags |= IRQ_DOMAIN_FLAG_IPI_SINGLE;
293         irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
294
295         base_ipi = __irq_domain_alloc_irqs(ipi_domain, -1, BITS_PER_MBOX,
296                                            NUMA_NO_NODE, NULL,
297                                            false, NULL);
298
299         if (WARN_ON(!base_ipi))
300                 return;
301
302         set_smp_ipi_range(base_ipi, BITS_PER_MBOX);
303
304         irq_set_chained_handler_and_data(mux_irq,
305                                          bcm2836_arm_irqchip_handle_ipi, NULL);
306
307         /* Unmask IPIs to the boot CPU. */
308         cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,
309                           "irqchip/bcm2836:starting", bcm2836_cpu_starting,
310                           bcm2836_cpu_dying);
311 }
312 #else
313 #define bcm2836_arm_irqchip_smp_init()  do { } while(0)
314 #endif
315
316 static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
317         .xlate = irq_domain_xlate_onetwocell,
318         .map = bcm2836_map,
319 };
320
321 /*
322  * The LOCAL_IRQ_CNT* timer firings are based off of the external
323  * oscillator with some scaling.  The firmware sets up CNTFRQ to
324  * report 19.2Mhz, but doesn't set up the scaling registers.
325  */
326 static void bcm2835_init_local_timer_frequency(void)
327 {
328         /*
329          * Set the timer to source from the 19.2Mhz crystal clock (bit
330          * 8 unset), and only increment by 1 instead of 2 (bit 9
331          * unset).
332          */
333         writel(0, intc.base + LOCAL_CONTROL);
334
335         /*
336          * Set the timer prescaler to 1:1 (timer freq = input freq *
337          * 2**31 / prescaler)
338          */
339         writel(0x80000000, intc.base + LOCAL_PRESCALER);
340 }
341
342 static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
343                                                       struct device_node *parent)
344 {
345         intc.base = of_iomap(node, 0);
346         if (!intc.base) {
347                 panic("%pOF: unable to map local interrupt registers\n", node);
348         }
349
350         arm_local_intc = intc.base;
351
352         bcm2835_init_local_timer_frequency();
353
354         intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
355                                             &bcm2836_arm_irqchip_intc_ops,
356                                             NULL);
357         if (!intc.domain)
358                 panic("%pOF: unable to create IRQ domain\n", node);
359
360         irq_domain_update_bus_token(intc.domain, DOMAIN_BUS_WIRED);
361
362         bcm2836_arm_irqchip_smp_init();
363
364         set_handle_irq(bcm2836_arm_irqchip_handle_irq);
365         return 0;
366 }
367
368 IRQCHIP_DECLARE(bcm2836_arm_irqchip_l1_intc, "brcm,bcm2836-l1-intc",
369                 bcm2836_arm_irqchip_l1_intc_of_init);