]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/gic.c
Move arm's devmap to some generic place, so it can be used
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / gic.c
1 /*-
2  * Copyright (c) 2011 The FreeBSD Foundation
3  * Copyright (c) 2014 Andrew Turner
4  * All rights reserved.
5  *
6  * Developed by Damjan Marion <damjan.marion@gmail.com>
7  *
8  * Based on OMAP4 GIC code by Ben Gray
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the company nor the name of the author may be used to
19  *    endorse or promote products derived from this software without specific
20  *    prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/bus.h>
41 #include <sys/kernel.h>
42 #include <sys/ktr.h>
43 #include <sys/module.h>
44 #include <sys/rman.h>
45 #include <sys/pcpu.h>
46 #include <sys/proc.h>
47 #include <sys/cpuset.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50
51 #include <machine/bus.h>
52 #include <machine/intr.h>
53 #include <machine/smp.h>
54
55 #include <vm/vm.h>
56 #include <vm/pmap.h>
57
58 #include <arm64/arm64/gic.h>
59
60 #include "pic_if.h"
61
62 /* We are using GICv2 register naming */
63
64 /* Distributor Registers */
65 #define GICD_CTLR               0x000                   /* v1 ICDDCR */
66 #define GICD_TYPER              0x004                   /* v1 ICDICTR */
67 #define GICD_IIDR               0x008                   /* v1 ICDIIDR */
68 #define GICD_IGROUPR(n)         (0x0080 + ((n) * 4))    /* v1 ICDISER */
69 #define GICD_ISENABLER(n)       (0x0100 + ((n) * 4))    /* v1 ICDISER */
70 #define GICD_ICENABLER(n)       (0x0180 + ((n) * 4))    /* v1 ICDICER */
71 #define GICD_ISPENDR(n)         (0x0200 + ((n) * 4))    /* v1 ICDISPR */
72 #define GICD_ICPENDR(n)         (0x0280 + ((n) * 4))    /* v1 ICDICPR */
73 #define GICD_ICACTIVER(n)       (0x0380 + ((n) * 4))    /* v1 ICDABR */
74 #define GICD_IPRIORITYR(n)      (0x0400 + ((n) * 4))    /* v1 ICDIPR */
75 #define GICD_ITARGETSR(n)       (0x0800 + ((n) * 4))    /* v1 ICDIPTR */
76 #define GICD_ICFGR(n)           (0x0C00 + ((n) * 4))    /* v1 ICDICFR */
77 #define GICD_SGIR(n)            (0x0F00 + ((n) * 4))    /* v1 ICDSGIR */
78 #define  GICD_SGI_TARGET_SHIFT  16
79
80 /* CPU Registers */
81 #define GICC_CTLR               0x0000                  /* v1 ICCICR */
82 #define GICC_PMR                0x0004                  /* v1 ICCPMR */
83 #define GICC_BPR                0x0008                  /* v1 ICCBPR */
84 #define GICC_IAR                0x000C                  /* v1 ICCIAR */
85 #define GICC_EOIR               0x0010                  /* v1 ICCEOIR */
86 #define GICC_RPR                0x0014                  /* v1 ICCRPR */
87 #define GICC_HPPIR              0x0018                  /* v1 ICCHPIR */
88 #define GICC_ABPR               0x001C                  /* v1 ICCABPR */
89 #define GICC_IIDR               0x00FC                  /* v1 ICCIIDR*/
90
91 #define GIC_FIRST_IPI            0      /* Irqs 0-15 are SGIs/IPIs. */
92 #define GIC_LAST_IPI            15
93 #define GIC_FIRST_PPI           16      /* Irqs 16-31 are private (per */
94 #define GIC_LAST_PPI            31      /* core) peripheral interrupts. */
95 #define GIC_FIRST_SPI           32      /* Irqs 32+ are shared peripherals. */
96
97 /* First bit is a polarity bit (0 - low, 1 - high) */
98 #define GICD_ICFGR_POL_LOW      (0 << 0)
99 #define GICD_ICFGR_POL_HIGH     (1 << 0)
100 #define GICD_ICFGR_POL_MASK     0x1
101 /* Second bit is a trigger bit (0 - level, 1 - edge) */
102 #define GICD_ICFGR_TRIG_LVL     (0 << 1)
103 #define GICD_ICFGR_TRIG_EDGE    (1 << 1)
104 #define GICD_ICFGR_TRIG_MASK    0x2
105
106 static struct resource_spec arm_gic_spec[] = {
107         { SYS_RES_MEMORY,       0,      RF_ACTIVE },    /* Distributor registers */
108         { SYS_RES_MEMORY,       1,      RF_ACTIVE },    /* CPU Interrupt Intf. registers */
109         { -1, 0 }
110 };
111
112 static u_int arm_gic_map[MAXCPU];
113
114 static struct arm_gic_softc *arm_gic_sc = NULL;
115
116 #define gic_c_read_4(_sc, _reg)         \
117     bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg))
118 #define gic_c_write_4(_sc, _reg, _val)          \
119     bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val))
120 #define gic_d_read_4(_sc, _reg)         \
121     bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg))
122 #define gic_d_write_4(_sc, _reg, _val)          \
123     bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
124
125 static pic_dispatch_t gic_dispatch;
126 static pic_eoi_t gic_eoi;
127 static pic_mask_t gic_mask_irq;
128 static pic_unmask_t gic_unmask_irq;
129
130 static uint8_t
131 gic_cpu_mask(struct arm_gic_softc *sc)
132 {
133         uint32_t mask;
134         int i;
135
136         /* Read the current cpuid mask by reading ITARGETSR{0..7} */
137         for (i = 0; i < 8; i++) {
138                 mask = gic_d_read_4(sc, GICD_ITARGETSR(i));
139                 if (mask != 0)
140                         break;
141         }
142         /* No mask found, assume we are on CPU interface 0 */
143         if (mask == 0)
144                 return (1);
145
146         /* Collect the mask in the lower byte */
147         mask |= mask >> 16;
148         mask |= mask >> 8;
149
150         return (mask);
151 }
152
153 #ifdef SMP
154 static void
155 gic_init_secondary(device_t dev)
156 {
157         struct arm_gic_softc *sc = device_get_softc(dev);
158         int i;
159
160         /* Set the mask so we can find this CPU to send it IPIs */
161         arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
162
163         for (i = 0; i < sc->nirqs; i += 4)
164                 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
165
166         /* Set all the interrupts to be in Group 0 (secure) */
167         for (i = 0; i < sc->nirqs; i += 32) {
168                 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
169         }
170
171         /* Enable CPU interface */
172         gic_c_write_4(sc, GICC_CTLR, 1);
173
174         /* Set priority mask register. */
175         gic_c_write_4(sc, GICC_PMR, 0xff);
176
177         /* Enable interrupt distribution */
178         gic_d_write_4(sc, GICD_CTLR, 0x01);
179
180         /*
181          * Activate the timer interrupts: virtual, secure, and non-secure.
182          */
183         gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
184         gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
185         gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
186 }
187 #endif
188
189 int
190 arm_gic_attach(device_t dev)
191 {
192         struct          arm_gic_softc *sc;
193         int             i;
194         uint32_t        icciidr, mask;
195
196         if (arm_gic_sc)
197                 return (ENXIO);
198
199         sc = device_get_softc(dev);
200
201         if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) {
202                 device_printf(dev, "could not allocate resources\n");
203                 return (ENXIO);
204         }
205
206         sc->gic_dev = dev;
207         arm_gic_sc = sc;
208
209         /* Initialize mutex */
210         mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN);
211
212         /* Distributor Interface */
213         sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]);
214         sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]);
215
216         /* CPU Interface */
217         sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
218         sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
219
220         /* Disable interrupt forwarding to the CPU interface */
221         gic_d_write_4(sc, GICD_CTLR, 0x00);
222
223         /* Get the number of interrupts */
224         sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
225         sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
226
227         arm_register_root_pic(dev, sc->nirqs);
228
229         icciidr = gic_c_read_4(sc, GICC_IIDR);
230         device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
231                         icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
232                         (icciidr & 0xfff), sc->nirqs);
233
234         /* Set all global interrupts to be level triggered, active low. */
235         for (i = 32; i < sc->nirqs; i += 16) {
236                 gic_d_write_4(sc, GICD_ICFGR(i >> 4), 0x00000000);
237         }
238
239         /* Disable all interrupts. */
240         for (i = 32; i < sc->nirqs; i += 32) {
241                 gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
242         }
243
244         /* Find the current cpu mask */
245         mask = gic_cpu_mask(sc);
246         /* Set the mask so we can find this CPU to send it IPIs */
247         arm_gic_map[PCPU_GET(cpuid)] = mask;
248         /* Set all four targets to this cpu */
249         mask |= mask << 8;
250         mask |= mask << 16;
251
252         for (i = 0; i < sc->nirqs; i += 4) {
253                 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
254                 if (i > 32) {
255                         gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
256                 }
257         }
258
259         /* Set all the interrupts to be in Group 0 (secure) */
260         for (i = 0; i < sc->nirqs; i += 32) {
261                 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
262         }
263
264         /* Enable CPU interface */
265         gic_c_write_4(sc, GICC_CTLR, 1);
266
267         /* Set priority mask register. */
268         gic_c_write_4(sc, GICC_PMR, 0xff);
269
270         /* Enable interrupt distribution */
271         gic_d_write_4(sc, GICD_CTLR, 0x01);
272
273         return (0);
274 }
275
276 static void gic_dispatch(device_t dev, struct trapframe *frame)
277 {
278         struct arm_gic_softc *sc = device_get_softc(dev);
279         uint32_t active_irq;
280         int first = 1;
281
282         while (1) {
283                 active_irq = gic_c_read_4(sc, GICC_IAR);
284
285                 /*
286                  * Immediatly EOIR the SGIs, because doing so requires the other
287                  * bits (ie CPU number), not just the IRQ number, and we do not
288                  * have this information later.
289                  */
290
291                 if ((active_irq & 0x3ff) <= GIC_LAST_IPI)
292                         gic_c_write_4(sc, GICC_EOIR, active_irq);
293                 active_irq &= 0x3FF;
294
295                 if (active_irq == 0x3FF) {
296                         if (first)
297                                 printf("Spurious interrupt detected\n");
298                         return;
299                 }
300
301                 arm_dispatch_intr(active_irq, frame);
302                 first = 0;
303         }
304 }
305
306 static void
307 gic_eoi(device_t dev, u_int irq)
308 {
309         struct arm_gic_softc *sc = device_get_softc(dev);
310
311         gic_c_write_4(sc, GICC_EOIR, irq);
312 }
313
314 void
315 gic_mask_irq(device_t dev, u_int irq)
316 {
317         struct arm_gic_softc *sc = device_get_softc(dev);
318
319         gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
320         gic_c_write_4(sc, GICC_EOIR, irq);
321 }
322
323 void
324 gic_unmask_irq(device_t dev, u_int irq)
325 {
326         struct arm_gic_softc *sc = device_get_softc(dev);
327
328         gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
329 }
330
331 #ifdef SMP
332 static void
333 gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
334 {
335         struct arm_gic_softc *sc = device_get_softc(dev);
336         uint32_t val = 0, i;
337
338         for (i = 0; i < MAXCPU; i++)
339                 if (CPU_ISSET(i, &cpus))
340                         val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
341
342         gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
343 }
344 #endif
345
346 static device_method_t arm_gic_methods[] = {
347         /* Device interface */
348         DEVMETHOD(device_attach,        arm_gic_attach),
349
350         /* pic_if */
351         DEVMETHOD(pic_dispatch,         gic_dispatch),
352         DEVMETHOD(pic_eoi,              gic_eoi),
353         DEVMETHOD(pic_mask,             gic_mask_irq),
354         DEVMETHOD(pic_unmask,           gic_unmask_irq),
355
356 #ifdef SMP
357         DEVMETHOD(pic_init_secondary,   gic_init_secondary),
358         DEVMETHOD(pic_ipi_send,         gic_ipi_send),
359 #endif
360
361         { 0, 0 }
362 };
363
364 DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods,
365     sizeof(struct arm_gic_softc));
366
367 #define GICV2M_MSI_TYPER        0x008
368 #define  MSI_TYPER_SPI_BASE(x)  (((x) >> 16) & 0x3ff)
369 #define  MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff)
370 #define GICv2M_MSI_SETSPI_NS    0x040
371 #define GICV2M_MSI_IIDR         0xFCC
372
373 static int
374 gicv2m_attach(device_t dev)
375 {
376         struct gicv2m_softc *sc;
377         uint32_t typer;
378         int rid;
379
380         sc = device_get_softc(dev);
381
382         rid = 0;
383         sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
384         if (sc->sc_mem == NULL) {
385                 device_printf(dev, "Unable to allocate resources\n");
386                 return (ENXIO);
387         }
388
389         typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER);
390         sc->sc_spi_start = MSI_TYPER_SPI_BASE(typer);
391         sc->sc_spi_count = MSI_TYPER_SPI_COUNT(typer);
392
393         device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start,
394             sc->sc_spi_start + sc->sc_spi_count - 1);
395
396         mtx_init(&sc->sc_mutex, "GICv2m lock", "", MTX_DEF);
397
398         arm_register_msi_pic(dev);
399
400         return (0);
401 }
402
403 static int
404 gicv2m_alloc_msix(device_t dev, device_t pci_dev, int *pirq)
405 {
406         struct arm_gic_softc *psc;
407         struct gicv2m_softc *sc;
408         uint32_t reg;
409         int irq;
410
411         psc = device_get_softc(device_get_parent(dev));
412         sc = device_get_softc(dev);
413
414         mtx_lock(&sc->sc_mutex);
415         /* Find an unused interrupt */
416         KASSERT(sc->sc_spi_offset < sc->sc_spi_count, ("No free SPIs"));
417
418         irq = sc->sc_spi_start + sc->sc_spi_offset;
419         sc->sc_spi_offset++;
420
421         /* Interrupts need to be edge triggered, set this */
422         reg = gic_d_read_4(psc, GICD_ICFGR(irq >> 4));
423         reg |= (GICD_ICFGR_TRIG_EDGE | GICD_ICFGR_POL_HIGH) <<
424             ((irq & 0xf) * 2);
425         gic_d_write_4(psc, GICD_ICFGR(irq >> 4), reg);
426
427         *pirq = irq;
428         mtx_unlock(&sc->sc_mutex);
429
430         return (0);
431 }
432
433 static int
434 gicv2m_alloc_msi(device_t dev, device_t pci_dev, int count, int *irqs)
435 {
436         struct arm_gic_softc *psc;
437         struct gicv2m_softc *sc;
438         uint32_t reg;
439         int i, irq;
440
441         psc = device_get_softc(device_get_parent(dev));
442         sc = device_get_softc(dev);
443
444         mtx_lock(&sc->sc_mutex);
445         KASSERT(sc->sc_spi_offset + count <= sc->sc_spi_count,
446             ("No free SPIs for %d MSI interrupts", count));
447
448         /* Find an unused interrupt */
449         for (i = 0; i < count; i++) {
450                 irq = sc->sc_spi_start + sc->sc_spi_offset;
451                 sc->sc_spi_offset++;
452
453                 /* Interrupts need to be edge triggered, set this */
454                 reg = gic_d_read_4(psc, GICD_ICFGR(irq >> 4));
455                 reg |= (GICD_ICFGR_TRIG_EDGE | GICD_ICFGR_POL_HIGH) <<
456                     ((irq & 0xf) * 2);
457                 gic_d_write_4(psc, GICD_ICFGR(irq >> 4), reg);
458
459                 irqs[i] = irq;
460         }
461         mtx_unlock(&sc->sc_mutex);
462
463         return (0);
464 }
465
466 static int
467 gicv2m_map_msi(device_t dev, device_t pci_dev, int irq, uint64_t *addr,
468     uint32_t *data)
469 {
470         struct gicv2m_softc *sc = device_get_softc(dev);
471
472         *addr = vtophys(rman_get_virtual(sc->sc_mem)) + 0x40;
473         *data = irq;
474
475         return (0);
476 }
477
478 static device_method_t arm_gicv2m_methods[] = {
479         /* Device interface */
480         DEVMETHOD(device_attach,        gicv2m_attach),
481
482         /* MSI/MSI-X */
483         DEVMETHOD(pic_alloc_msix,       gicv2m_alloc_msix),
484         DEVMETHOD(pic_alloc_msi,        gicv2m_alloc_msi),
485         DEVMETHOD(pic_map_msi,          gicv2m_map_msi),
486
487         { 0, 0 }
488 };
489
490 DEFINE_CLASS_0(gicv2m, arm_gicv2m_driver, arm_gicv2m_methods,
491     sizeof(struct gicv2m_softc));