]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/gic_v3.c
Merge OpenSSL 1.0.2h.
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / gic_v3.c
1 /*-
2  * Copyright (c) 2015 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Semihalf under
6  * the sponsorship of the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/ktr.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/rman.h>
41 #include <sys/pcpu.h>
42 #include <sys/proc.h>
43 #include <sys/cpuset.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/smp.h>
47
48 #include <vm/vm.h>
49 #include <vm/pmap.h>
50
51 #include <machine/bus.h>
52 #include <machine/cpu.h>
53 #include <machine/intr.h>
54
55 #include "pic_if.h"
56
57 #include "gic_v3_reg.h"
58 #include "gic_v3_var.h"
59
60 /* Device and PIC methods */
61 static int gic_v3_bind(device_t, u_int, u_int);
62 static void gic_v3_dispatch(device_t, struct trapframe *);
63 static void gic_v3_eoi(device_t, u_int);
64 static void gic_v3_mask_irq(device_t, u_int);
65 static void gic_v3_unmask_irq(device_t, u_int);
66 #ifdef SMP
67 static void gic_v3_init_secondary(device_t);
68 static void gic_v3_ipi_send(device_t, cpuset_t, u_int);
69 #endif
70
71 static device_method_t gic_v3_methods[] = {
72         /* Device interface */
73         DEVMETHOD(device_detach,        gic_v3_detach),
74
75         /* PIC interface */
76         DEVMETHOD(pic_bind,             gic_v3_bind),
77         DEVMETHOD(pic_dispatch,         gic_v3_dispatch),
78         DEVMETHOD(pic_eoi,              gic_v3_eoi),
79         DEVMETHOD(pic_mask,             gic_v3_mask_irq),
80         DEVMETHOD(pic_unmask,           gic_v3_unmask_irq),
81 #ifdef SMP
82         DEVMETHOD(pic_init_secondary,   gic_v3_init_secondary),
83         DEVMETHOD(pic_ipi_send,         gic_v3_ipi_send),
84 #endif
85         /* End */
86         DEVMETHOD_END
87 };
88
89 DEFINE_CLASS_0(gic, gic_v3_driver, gic_v3_methods,
90     sizeof(struct gic_v3_softc));
91
92 /*
93  * Driver-specific definitions.
94  */
95 MALLOC_DEFINE(M_GIC_V3, "GICv3", GIC_V3_DEVSTR);
96
97 /*
98  * Helper functions and definitions.
99  */
100 /* Destination registers, either Distributor or Re-Distributor */
101 enum gic_v3_xdist {
102         DIST = 0,
103         REDIST,
104 };
105
106 /* Helper routines starting with gic_v3_ */
107 static int gic_v3_dist_init(struct gic_v3_softc *);
108 static int gic_v3_redist_alloc(struct gic_v3_softc *);
109 static int gic_v3_redist_find(struct gic_v3_softc *);
110 static int gic_v3_redist_init(struct gic_v3_softc *);
111 static int gic_v3_cpu_init(struct gic_v3_softc *);
112 static void gic_v3_wait_for_rwp(struct gic_v3_softc *, enum gic_v3_xdist);
113
114 /* A sequence of init functions for primary (boot) CPU */
115 typedef int (*gic_v3_initseq_t) (struct gic_v3_softc *);
116 /* Primary CPU initialization sequence */
117 static gic_v3_initseq_t gic_v3_primary_init[] = {
118         gic_v3_dist_init,
119         gic_v3_redist_alloc,
120         gic_v3_redist_init,
121         gic_v3_cpu_init,
122         NULL
123 };
124
125 #ifdef SMP
126 /* Secondary CPU initialization sequence */
127 static gic_v3_initseq_t gic_v3_secondary_init[] = {
128         gic_v3_redist_init,
129         gic_v3_cpu_init,
130         NULL
131 };
132 #endif
133
134 /*
135  * Device interface.
136  */
137 int
138 gic_v3_attach(device_t dev)
139 {
140         struct gic_v3_softc *sc;
141         gic_v3_initseq_t *init_func;
142         uint32_t typer;
143         int rid;
144         int err;
145         size_t i;
146
147         sc = device_get_softc(dev);
148         sc->gic_registered = FALSE;
149         sc->dev = dev;
150         err = 0;
151
152         /* Initialize mutex */
153         mtx_init(&sc->gic_mtx, "GICv3 lock", NULL, MTX_SPIN);
154
155         /*
156          * Allocate array of struct resource.
157          * One entry for Distributor and all remaining for Re-Distributor.
158          */
159         sc->gic_res = malloc(
160             sizeof(*sc->gic_res) * (sc->gic_redists.nregions + 1),
161             M_GIC_V3, M_WAITOK);
162
163         /* Now allocate corresponding resources */
164         for (i = 0, rid = 0; i < (sc->gic_redists.nregions + 1); i++, rid++) {
165                 sc->gic_res[rid] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
166                     &rid, RF_ACTIVE);
167                 if (sc->gic_res[rid] == NULL)
168                         return (ENXIO);
169         }
170
171         /*
172          * Distributor interface
173          */
174         sc->gic_dist = sc->gic_res[0];
175
176         /*
177          * Re-Dristributor interface
178          */
179         /* Allocate space under region descriptions */
180         sc->gic_redists.regions = malloc(
181             sizeof(*sc->gic_redists.regions) * sc->gic_redists.nregions,
182             M_GIC_V3, M_WAITOK);
183
184         /* Fill-up bus_space information for each region. */
185         for (i = 0, rid = 1; i < sc->gic_redists.nregions; i++, rid++)
186                 sc->gic_redists.regions[i] = sc->gic_res[rid];
187
188         /* Get the number of supported SPI interrupts */
189         typer = gic_d_read(sc, 4, GICD_TYPER);
190         sc->gic_nirqs = GICD_TYPER_I_NUM(typer);
191         if (sc->gic_nirqs > GIC_I_NUM_MAX)
192                 sc->gic_nirqs = GIC_I_NUM_MAX;
193
194         /* Get the number of supported interrupt identifier bits */
195         sc->gic_idbits = GICD_TYPER_IDBITS(typer);
196
197         if (bootverbose) {
198                 device_printf(dev, "SPIs: %u, IDs: %u\n",
199                     sc->gic_nirqs, (1 << sc->gic_idbits) - 1);
200         }
201
202         /* Train init sequence for boot CPU */
203         for (init_func = gic_v3_primary_init; *init_func != NULL; init_func++) {
204                 err = (*init_func)(sc);
205                 if (err != 0)
206                         return (err);
207         }
208         /*
209          * Full success.
210          * Now register PIC to the interrupts handling layer.
211          */
212         arm_register_root_pic(dev, sc->gic_nirqs);
213         sc->gic_registered = TRUE;
214
215         return (0);
216 }
217
218 int
219 gic_v3_detach(device_t dev)
220 {
221         struct gic_v3_softc *sc;
222         size_t i;
223         int rid;
224
225         sc = device_get_softc(dev);
226
227         if (device_is_attached(dev)) {
228                 /*
229                  * XXX: We should probably deregister PIC
230                  */
231                 if (sc->gic_registered)
232                         panic("Trying to detach registered PIC");
233         }
234         for (rid = 0; rid < (sc->gic_redists.nregions + 1); rid++)
235                 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->gic_res[rid]);
236
237         for (i = 0; i < mp_ncpus; i++)
238                 free(sc->gic_redists.pcpu[i], M_GIC_V3);
239
240         free(sc->gic_res, M_GIC_V3);
241         free(sc->gic_redists.regions, M_GIC_V3);
242
243         return (0);
244 }
245
246 /*
247  * PIC interface.
248  */
249
250 static int
251 gic_v3_bind(device_t dev, u_int irq, u_int cpuid)
252 {
253         uint64_t aff;
254         struct gic_v3_softc *sc;
255
256         sc = device_get_softc(dev);
257
258         if (irq <= GIC_LAST_PPI) {
259                 /* Can't bind PPI to another CPU but it's not an error */
260                 return (0);
261         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) {
262                 aff = CPU_AFFINITY(cpuid);
263                 gic_d_write(sc, 4, GICD_IROUTER(irq), aff);
264                 return (0);
265         } else if (irq >= GIC_FIRST_LPI)
266                 return (lpi_migrate(dev, irq, cpuid));
267
268         return (EINVAL);
269 }
270
271 static void
272 gic_v3_dispatch(device_t dev, struct trapframe *frame)
273 {
274         uint64_t active_irq;
275
276         while (1) {
277                 if (CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1) {
278                         /*
279                          * Hardware:            Cavium ThunderX
280                          * Chip revision:       Pass 1.0 (early version)
281                          *                      Pass 1.1 (production)
282                          * ERRATUM:             22978, 23154
283                          */
284                         __asm __volatile(
285                             "nop;nop;nop;nop;nop;nop;nop;nop;   \n"
286                             "mrs %0, ICC_IAR1_EL1               \n"
287                             "nop;nop;nop;nop;                   \n"
288                             "dsb sy                             \n"
289                             : "=&r" (active_irq));
290                 } else {
291                         active_irq = gic_icc_read(IAR1);
292                 }
293
294                 if (__predict_false(active_irq == ICC_IAR1_EL1_SPUR))
295                         break;
296
297                 if (__predict_true((active_irq >= GIC_FIRST_PPI &&
298                     active_irq <= GIC_LAST_SPI) || active_irq >= GIC_FIRST_LPI)) {
299                         arm_dispatch_intr(active_irq, frame);
300                         continue;
301                 }
302
303                 if (active_irq <= GIC_LAST_SGI) {
304                         gic_icc_write(EOIR1, (uint64_t)active_irq);
305                         arm_dispatch_intr(active_irq, frame);
306                         continue;
307                 }
308         }
309 }
310
311 static void
312 gic_v3_eoi(device_t dev, u_int irq)
313 {
314
315         gic_icc_write(EOIR1, (uint64_t)irq);
316 }
317
318 static void
319 gic_v3_mask_irq(device_t dev, u_int irq)
320 {
321         struct gic_v3_softc *sc;
322
323         sc = device_get_softc(dev);
324
325         if (irq <= GIC_LAST_PPI) { /* SGIs and PPIs in corresponding Re-Distributor */
326                 gic_r_write(sc, 4,
327                     GICR_SGI_BASE_SIZE + GICD_ICENABLER(irq), GICD_I_MASK(irq));
328                 gic_v3_wait_for_rwp(sc, REDIST);
329         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
330                 gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
331                 gic_v3_wait_for_rwp(sc, DIST);
332         } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
333                 lpi_mask_irq(dev, irq);
334         } else
335                 panic("%s: Unsupported IRQ number %u", __func__, irq);
336 }
337
338 static void
339 gic_v3_unmask_irq(device_t dev, u_int irq)
340 {
341         struct gic_v3_softc *sc;
342
343         sc = device_get_softc(dev);
344
345         if (irq <= GIC_LAST_PPI) { /* SGIs and PPIs in corresponding Re-Distributor */
346                 gic_r_write(sc, 4,
347                     GICR_SGI_BASE_SIZE + GICD_ISENABLER(irq), GICD_I_MASK(irq));
348                 gic_v3_wait_for_rwp(sc, REDIST);
349         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
350                 gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
351                 gic_v3_wait_for_rwp(sc, DIST);
352         } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
353                 lpi_unmask_irq(dev, irq);
354         } else
355                 panic("%s: Unsupported IRQ number %u", __func__, irq);
356 }
357
358 #ifdef SMP
359 static void
360 gic_v3_init_secondary(device_t dev)
361 {
362         struct gic_v3_softc *sc;
363         gic_v3_initseq_t *init_func;
364         int err;
365
366         sc = device_get_softc(dev);
367
368         /* Train init sequence for boot CPU */
369         for (init_func = gic_v3_secondary_init; *init_func != NULL; init_func++) {
370                 err = (*init_func)(sc);
371                 if (err != 0) {
372                         device_printf(dev,
373                             "Could not initialize GIC for CPU%u\n",
374                             PCPU_GET(cpuid));
375                         return;
376                 }
377         }
378
379         /*
380          * Try to initialize ITS.
381          * If there is no driver attached this routine will fail but that
382          * does not mean failure here as only LPIs will not be functional
383          * on the current CPU.
384          */
385         if (its_init_cpu(NULL) != 0) {
386                 device_printf(dev,
387                     "Could not initialize ITS for CPU%u. "
388                     "No LPIs will arrive on this CPU\n",
389                     PCPU_GET(cpuid));
390         }
391
392         /*
393          * ARM64TODO:   Unmask timer PPIs. To be removed when appropriate
394          *              mechanism is implemented.
395          *              Activate the timer interrupts: virtual (27), secure (29),
396          *              and non-secure (30). Use hardcoded values here as there
397          *              should be no defines for them.
398          */
399         gic_v3_unmask_irq(dev, 27);
400         gic_v3_unmask_irq(dev, 29);
401         gic_v3_unmask_irq(dev, 30);
402 }
403
404 static void
405 gic_v3_ipi_send(device_t dev, cpuset_t cpuset, u_int ipi)
406 {
407         u_int cpu;
408         uint64_t aff, tlist;
409         uint64_t val;
410         uint64_t aff_mask;
411
412         /* Set affinity mask to match level 3, 2 and 1 */
413         aff_mask = CPU_AFF1_MASK | CPU_AFF2_MASK | CPU_AFF3_MASK;
414
415         /* Iterate through all CPUs in set */
416         while (!CPU_EMPTY(&cpuset)) {
417                 aff = tlist = 0;
418                 for (cpu = 0; cpu < mp_ncpus; cpu++) {
419                         /* Compose target list for single AFF3:AFF2:AFF1 set */
420                         if (CPU_ISSET(cpu, &cpuset)) {
421                                 if (!tlist) {
422                                         /*
423                                          * Save affinity of the first CPU to
424                                          * send IPI to for later comparison.
425                                          */
426                                         aff = CPU_AFFINITY(cpu);
427                                         tlist |= (1UL << CPU_AFF0(aff));
428                                         CPU_CLR(cpu, &cpuset);
429                                 }
430                                 /* Check for same Affinity level 3, 2 and 1 */
431                                 if ((aff & aff_mask) == (CPU_AFFINITY(cpu) & aff_mask)) {
432                                         tlist |= (1UL << CPU_AFF0(CPU_AFFINITY(cpu)));
433                                         /* Clear CPU in cpuset from target list */
434                                         CPU_CLR(cpu, &cpuset);
435                                 }
436                         }
437                 }
438                 if (tlist) {
439                         KASSERT((tlist & ~ICC_SGI1R_EL1_TL_MASK) == 0,
440                             ("Target list too long for GICv3 IPI"));
441                         /* Send SGI to CPUs in target list */
442                         val = tlist;
443                         val |= (uint64_t)CPU_AFF3(aff) << ICC_SGI1R_EL1_AFF3_SHIFT;
444                         val |= (uint64_t)CPU_AFF2(aff) << ICC_SGI1R_EL1_AFF2_SHIFT;
445                         val |= (uint64_t)CPU_AFF1(aff) << ICC_SGI1R_EL1_AFF1_SHIFT;
446                         val |= (uint64_t)(ipi & ICC_SGI1R_EL1_SGIID_MASK) <<
447                             ICC_SGI1R_EL1_SGIID_SHIFT;
448                         gic_icc_write(SGI1R, val);
449                 }
450         }
451 }
452 #endif
453
454 /*
455  * Helper routines
456  */
457 static void
458 gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum gic_v3_xdist xdist)
459 {
460         struct resource *res;
461         u_int cpuid;
462         size_t us_left = 1000000;
463
464         cpuid = PCPU_GET(cpuid);
465
466         switch (xdist) {
467         case DIST:
468                 res = sc->gic_dist;
469                 break;
470         case REDIST:
471                 res = sc->gic_redists.pcpu[cpuid];
472                 break;
473         default:
474                 KASSERT(0, ("%s: Attempt to wait for unknown RWP", __func__));
475                 return;
476         }
477
478         while ((bus_read_4(res, GICD_CTLR) & GICD_CTLR_RWP) != 0) {
479                 DELAY(1);
480                 if (us_left-- == 0)
481                         panic("GICD Register write pending for too long");
482         }
483 }
484
485 /* CPU interface. */
486 static __inline void
487 gic_v3_cpu_priority(uint64_t mask)
488 {
489
490         /* Set prority mask */
491         gic_icc_write(PMR, mask & ICC_PMR_EL1_PRIO_MASK);
492 }
493
494 static int
495 gic_v3_cpu_enable_sre(struct gic_v3_softc *sc)
496 {
497         uint64_t sre;
498         u_int cpuid;
499
500         cpuid = PCPU_GET(cpuid);
501         /*
502          * Set the SRE bit to enable access to GIC CPU interface
503          * via system registers.
504          */
505         sre = READ_SPECIALREG(icc_sre_el1);
506         sre |= ICC_SRE_EL1_SRE;
507         WRITE_SPECIALREG(icc_sre_el1, sre);
508         isb();
509         /*
510          * Now ensure that the bit is set.
511          */
512         sre = READ_SPECIALREG(icc_sre_el1);
513         if ((sre & ICC_SRE_EL1_SRE) == 0) {
514                 /* We are done. This was disabled in EL2 */
515                 device_printf(sc->dev, "ERROR: CPU%u cannot enable CPU interface "
516                     "via system registers\n", cpuid);
517                 return (ENXIO);
518         } else if (bootverbose) {
519                 device_printf(sc->dev,
520                     "CPU%u enabled CPU interface via system registers\n",
521                     cpuid);
522         }
523
524         return (0);
525 }
526
527 static int
528 gic_v3_cpu_init(struct gic_v3_softc *sc)
529 {
530         int err;
531
532         /* Enable access to CPU interface via system registers */
533         err = gic_v3_cpu_enable_sre(sc);
534         if (err != 0)
535                 return (err);
536         /* Priority mask to minimum - accept all interrupts */
537         gic_v3_cpu_priority(GIC_PRIORITY_MIN);
538         /* Disable EOI mode */
539         gic_icc_clear(CTLR, ICC_CTLR_EL1_EOIMODE);
540         /* Enable group 1 (insecure) interrups */
541         gic_icc_set(IGRPEN1, ICC_IGRPEN0_EL1_EN);
542
543         return (0);
544 }
545
546 /* Distributor */
547 static int
548 gic_v3_dist_init(struct gic_v3_softc *sc)
549 {
550         uint64_t aff;
551         u_int i;
552
553         /*
554          * 1. Disable the Distributor
555          */
556         gic_d_write(sc, 4, GICD_CTLR, 0);
557         gic_v3_wait_for_rwp(sc, DIST);
558
559         /*
560          * 2. Configure the Distributor
561          */
562         /* Set all global interrupts to be level triggered, active low. */
563         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ICFGRn)
564                 gic_d_write(sc, 4, GICD_ICFGR(i), 0x00000000);
565
566         /* Set priority to all shared interrupts */
567         for (i = GIC_FIRST_SPI;
568             i < sc->gic_nirqs; i += GICD_I_PER_IPRIORITYn) {
569                 /* Set highest priority */
570                 gic_d_write(sc, 4, GICD_IPRIORITYR(i), GIC_PRIORITY_MAX);
571         }
572
573         /*
574          * Disable all interrupts. Leave PPI and SGIs as they are enabled in
575          * Re-Distributor registers.
576          */
577         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ISENABLERn)
578                 gic_d_write(sc, 4, GICD_ICENABLER(i), 0xFFFFFFFF);
579
580         gic_v3_wait_for_rwp(sc, DIST);
581
582         /*
583          * 3. Enable Distributor
584          */
585         /* Enable Distributor with ARE, Group 1 */
586         gic_d_write(sc, 4, GICD_CTLR, GICD_CTLR_ARE_NS | GICD_CTLR_G1A |
587             GICD_CTLR_G1);
588
589         /*
590          * 4. Route all interrupts to boot CPU.
591          */
592         aff = CPU_AFFINITY(0);
593         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i++)
594                 gic_d_write(sc, 4, GICD_IROUTER(i), aff);
595
596         return (0);
597 }
598
599 /* Re-Distributor */
600 static int
601 gic_v3_redist_alloc(struct gic_v3_softc *sc)
602 {
603         u_int cpuid;
604
605         /* Allocate struct resource for all CPU's Re-Distributor registers */
606         for (cpuid = 0; cpuid < mp_ncpus; cpuid++)
607                 if (CPU_ISSET(cpuid, &all_cpus) != 0)
608                         sc->gic_redists.pcpu[cpuid] =
609                                 malloc(sizeof(*sc->gic_redists.pcpu[0]),
610                                     M_GIC_V3, M_WAITOK);
611                 else
612                         sc->gic_redists.pcpu[cpuid] = NULL;
613         return (0);
614 }
615
616 static int
617 gic_v3_redist_find(struct gic_v3_softc *sc)
618 {
619         struct resource r_res;
620         bus_space_handle_t r_bsh;
621         uint64_t aff;
622         uint64_t typer;
623         uint32_t pidr2;
624         u_int cpuid;
625         size_t i;
626
627         cpuid = PCPU_GET(cpuid);
628
629         aff = CPU_AFFINITY(cpuid);
630         /* Affinity in format for comparison with typer */
631         aff = (CPU_AFF3(aff) << 24) | (CPU_AFF2(aff) << 16) |
632             (CPU_AFF1(aff) << 8) | CPU_AFF0(aff);
633
634         if (bootverbose) {
635                 device_printf(sc->dev,
636                     "Start searching for Re-Distributor\n");
637         }
638         /* Iterate through Re-Distributor regions */
639         for (i = 0; i < sc->gic_redists.nregions; i++) {
640                 /* Take a copy of the region's resource */
641                 r_res = *sc->gic_redists.regions[i];
642                 r_bsh = rman_get_bushandle(&r_res);
643
644                 pidr2 = bus_read_4(&r_res, GICR_PIDR2);
645                 switch (pidr2 & GICR_PIDR2_ARCH_MASK) {
646                 case GICR_PIDR2_ARCH_GICv3: /* fall through */
647                 case GICR_PIDR2_ARCH_GICv4:
648                         break;
649                 default:
650                         device_printf(sc->dev,
651                             "No Re-Distributor found for CPU%u\n", cpuid);
652                         return (ENODEV);
653                 }
654
655                 do {
656                         typer = bus_read_8(&r_res, GICR_TYPER);
657                         if ((typer >> GICR_TYPER_AFF_SHIFT) == aff) {
658                                 KASSERT(sc->gic_redists.pcpu[cpuid] != NULL,
659                                     ("Invalid pointer to per-CPU redistributor"));
660                                 /* Copy res contents to its final destination */
661                                 *sc->gic_redists.pcpu[cpuid] = r_res;
662                                 if (bootverbose) {
663                                         device_printf(sc->dev,
664                                             "CPU%u Re-Distributor has been found\n",
665                                             cpuid);
666                                 }
667                                 return (0);
668                         }
669
670                         r_bsh += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
671                         if ((typer & GICR_TYPER_VLPIS) != 0) {
672                                 r_bsh +=
673                                     (GICR_VLPI_BASE_SIZE + GICR_RESERVED_SIZE);
674                         }
675
676                         rman_set_bushandle(&r_res, r_bsh);
677                 } while ((typer & GICR_TYPER_LAST) == 0);
678         }
679
680         device_printf(sc->dev, "No Re-Distributor found for CPU%u\n", cpuid);
681         return (ENXIO);
682 }
683
684 static int
685 gic_v3_redist_wake(struct gic_v3_softc *sc)
686 {
687         uint32_t waker;
688         size_t us_left = 1000000;
689
690         waker = gic_r_read(sc, 4, GICR_WAKER);
691         /* Wake up Re-Distributor for this CPU */
692         waker &= ~GICR_WAKER_PS;
693         gic_r_write(sc, 4, GICR_WAKER, waker);
694         /*
695          * When clearing ProcessorSleep bit it is required to wait for
696          * ChildrenAsleep to become zero following the processor power-on.
697          */
698         while ((gic_r_read(sc, 4, GICR_WAKER) & GICR_WAKER_CA) != 0) {
699                 DELAY(1);
700                 if (us_left-- == 0) {
701                         panic("Could not wake Re-Distributor for CPU%u",
702                             PCPU_GET(cpuid));
703                 }
704         }
705
706         if (bootverbose) {
707                 device_printf(sc->dev, "CPU%u Re-Distributor woke up\n",
708                     PCPU_GET(cpuid));
709         }
710
711         return (0);
712 }
713
714 static int
715 gic_v3_redist_init(struct gic_v3_softc *sc)
716 {
717         int err;
718         size_t i;
719
720         err = gic_v3_redist_find(sc);
721         if (err != 0)
722                 return (err);
723
724         err = gic_v3_redist_wake(sc);
725         if (err != 0)
726                 return (err);
727
728         /* Disable SPIs */
729         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ICENABLER0,
730             GICR_I_ENABLER_PPI_MASK);
731         /* Enable SGIs */
732         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ISENABLER0,
733             GICR_I_ENABLER_SGI_MASK);
734
735         /* Set priority for SGIs and PPIs */
736         for (i = 0; i <= GIC_LAST_PPI; i += GICR_I_PER_IPRIORITYn) {
737                 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICD_IPRIORITYR(i),
738                     GIC_PRIORITY_MAX);
739         }
740
741         gic_v3_wait_for_rwp(sc, REDIST);
742
743         return (0);
744 }