Mon May 2 04:39:29 2022 UTC ()
fix non-MULTIPROCESSOR build


(ryo)
diff -r1.7 -r1.8 src/sys/arch/arm/apple/apple_intc.c

cvs diff -r1.7 -r1.8 src/sys/arch/arm/apple/apple_intc.c (switch to unified diff)

--- src/sys/arch/arm/apple/apple_intc.c 2022/03/28 19:59:26 1.7
+++ src/sys/arch/arm/apple/apple_intc.c 2022/05/02 04:39:29 1.8
@@ -1,522 +1,526 @@ @@ -1,522 +1,526 @@
1/* $NetBSD: apple_intc.c,v 1.7 2022/03/28 19:59:26 riastradh Exp $ */ 1/* $NetBSD: apple_intc.c,v 1.8 2022/05/02 04:39:29 ryo Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_ddb.h" 29#include "opt_ddb.h"
30#include "opt_multiprocessor.h" 30#include "opt_multiprocessor.h"
31 31
32#define _INTR_PRIVATE 32#define _INTR_PRIVATE
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: apple_intc.c,v 1.7 2022/03/28 19:59:26 riastradh Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: apple_intc.c,v 1.8 2022/05/02 04:39:29 ryo Exp $");
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/bus.h> 38#include <sys/bus.h>
39#include <sys/device.h> 39#include <sys/device.h>
40#include <sys/intr.h> 40#include <sys/intr.h>
41#include <sys/kernel.h> 41#include <sys/kernel.h>
42#include <sys/lwp.h> 42#include <sys/lwp.h>
43#include <sys/systm.h> 43#include <sys/systm.h>
44#include <sys/cpu.h> 44#include <sys/cpu.h>
45#include <sys/kmem.h> 45#include <sys/kmem.h>
46#include <sys/atomic.h> 46#include <sys/atomic.h>
47 47
48#include <dev/fdt/fdtvar.h> 48#include <dev/fdt/fdtvar.h>
49 49
50#include <dev/pci/pcireg.h> 50#include <dev/pci/pcireg.h>
51#include <dev/pci/pcivar.h> 51#include <dev/pci/pcivar.h>
52 52
53#include <arm/cpu.h> 53#include <arm/cpu.h>
54#include <arm/cpufunc.h> 54#include <arm/cpufunc.h>
55#include <arm/armreg.h> 55#include <arm/armreg.h>
56#include <arm/locore.h> 56#include <arm/locore.h>
57#include <arm/pic/picvar.h> 57#include <arm/pic/picvar.h>
58#include <arm/fdt/arm_fdtvar.h> 58#include <arm/fdt/arm_fdtvar.h>
59 59
60/* 60/*
61 * AIC registers 61 * AIC registers
62 */ 62 */
63#define AIC_INFO 0x0004 63#define AIC_INFO 0x0004
64#define AIC_INFO_NIRQ __BITS(15,0) 64#define AIC_INFO_NIRQ __BITS(15,0)
65#define AIC_WHOAMI 0x2000 65#define AIC_WHOAMI 0x2000
66#define AIC_EVENT 0x2004 66#define AIC_EVENT 0x2004
67#define AIC_EVENT_TYPE __BITS(31,16) 67#define AIC_EVENT_TYPE __BITS(31,16)
68#define AIC_EVENT_TYPE_NONE 0 68#define AIC_EVENT_TYPE_NONE 0
69#define AIC_EVENT_TYPE_IRQ 1 69#define AIC_EVENT_TYPE_IRQ 1
70#define AIC_EVENT_TYPE_IPI 4 70#define AIC_EVENT_TYPE_IPI 4
71#define AIC_EVENT_DATA __BITS(15,0) 71#define AIC_EVENT_DATA __BITS(15,0)
72#define AIC_EVENT_IPI_OTHER 1 72#define AIC_EVENT_IPI_OTHER 1
73#define AIC_IPI_SEND 0x2008 73#define AIC_IPI_SEND 0x2008
74#define AIC_IPI_ACK 0x200c 74#define AIC_IPI_ACK 0x200c
75#define AIC_IPI_MASK_CLR 0x2028 75#define AIC_IPI_MASK_CLR 0x2028
76#define AIC_IPI_OTHER __BIT(0) 76#define AIC_IPI_OTHER __BIT(0)
77#define AIC_AFFINITY(irqno) (0x3000 + (irqno) * 4) 77#define AIC_AFFINITY(irqno) (0x3000 + (irqno) * 4)
78#define AIC_SW_SET(irqno) (0x4000 + (irqno) / 32 * 4) 78#define AIC_SW_SET(irqno) (0x4000 + (irqno) / 32 * 4)
79#define AIC_SW_CLR(irqno) (0x4080 + (irqno) / 32 * 4) 79#define AIC_SW_CLR(irqno) (0x4080 + (irqno) / 32 * 4)
80#define AIC_MASK_SET(irqno) (0x4100 + (irqno) / 32 * 4) 80#define AIC_MASK_SET(irqno) (0x4100 + (irqno) / 32 * 4)
81#define AIC_MASK_CLR(irqno) (0x4180 + (irqno) / 32 * 4) 81#define AIC_MASK_CLR(irqno) (0x4180 + (irqno) / 32 * 4)
82#define AIC_MASK_BIT(irqno) __BIT((irqno) & 0x1f) 82#define AIC_MASK_BIT(irqno) __BIT((irqno) & 0x1f)
83 83
84static const struct device_compatible_entry compat_data[] = { 84static const struct device_compatible_entry compat_data[] = {
85 { .compat = "apple,aic" }, 85 { .compat = "apple,aic" },
86 DEVICE_COMPAT_EOL 86 DEVICE_COMPAT_EOL
87}; 87};
88 88
89struct apple_intc_softc; 89struct apple_intc_softc;
90 90
91struct apple_intc_percpu { 91struct apple_intc_percpu {
92 struct apple_intc_softc *pc_sc; 92 struct apple_intc_softc *pc_sc;
93 u_int pc_cpuid; 93 u_int pc_cpuid;
94 u_int pc_ipimask; 94 u_int pc_ipimask;
95 95
96 struct pic_softc pc_pic; 96 struct pic_softc pc_pic;
97}; 97};
98 98
99#define LOCALPIC_SOURCE_TIMER 0 99#define LOCALPIC_SOURCE_TIMER 0
100#define LOCALPIC_SOURCE_IPI 1 100#define LOCALPIC_SOURCE_IPI 1
101 101
102struct apple_intc_softc { 102struct apple_intc_softc {
103 device_t sc_dev; /* device handle */ 103 device_t sc_dev; /* device handle */
104 bus_space_tag_t sc_bst; /* mmio tag */ 104 bus_space_tag_t sc_bst; /* mmio tag */
105 bus_space_handle_t sc_bsh; /* mmio handle */ 105 bus_space_handle_t sc_bsh; /* mmio handle */
106 u_int sc_nirq; /* number of supported IRQs */ 106 u_int sc_nirq; /* number of supported IRQs */
107 u_int *sc_cpuid; /* map of cpu index to AIC CPU ID */ 107 u_int *sc_cpuid; /* map of cpu index to AIC CPU ID */
108 struct apple_intc_percpu *sc_pc; /* per-CPU data for timer and IPIs */ 108 struct apple_intc_percpu *sc_pc; /* per-CPU data for timer and IPIs */
109 109
110 struct pic_softc sc_pic; 110 struct pic_softc sc_pic;
111}; 111};
112 112
113static struct apple_intc_softc *intc_softc; 113static struct apple_intc_softc *intc_softc;
114 114
115#define PICTOSOFTC(pic) container_of(pic, struct apple_intc_softc, sc_pic) 115#define PICTOSOFTC(pic) container_of(pic, struct apple_intc_softc, sc_pic)
116#define PICTOPERCPU(pic) container_of(pic, struct apple_intc_percpu, pc_pic) 116#define PICTOPERCPU(pic) container_of(pic, struct apple_intc_percpu, pc_pic)
117 117
118#define AIC_READ(sc, reg) \ 118#define AIC_READ(sc, reg) \
119 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 119 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
120#define AIC_WRITE(sc, reg, val) \ 120#define AIC_WRITE(sc, reg, val) \
121 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 121 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
122 122
123static void 123static void
124apple_intc_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask) 124apple_intc_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask)
125{ 125{
126 struct apple_intc_softc * const sc = PICTOSOFTC(pic); 126 struct apple_intc_softc * const sc = PICTOSOFTC(pic);
127 127
128 AIC_WRITE(sc, AIC_SW_SET(irqbase), mask); 128 AIC_WRITE(sc, AIC_SW_SET(irqbase), mask);
129 AIC_WRITE(sc, AIC_MASK_CLR(irqbase), mask); 129 AIC_WRITE(sc, AIC_MASK_CLR(irqbase), mask);
130} 130}
131 131
132static void 132static void
133apple_intc_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask) 133apple_intc_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask)
134{ 134{
135} 135}
136 136
137static void 137static void
138apple_intc_establish_irq(struct pic_softc *pic, struct intrsource *is) 138apple_intc_establish_irq(struct pic_softc *pic, struct intrsource *is)
139{ 139{
140 struct apple_intc_softc * const sc = PICTOSOFTC(pic); 140 struct apple_intc_softc * const sc = PICTOSOFTC(pic);
141 141
142 KASSERT(is->is_type == IST_LEVEL); 142 KASSERT(is->is_type == IST_LEVEL);
143 143
144 /* Route to primary PE by default */ 144 /* Route to primary PE by default */
145 AIC_WRITE(sc, AIC_AFFINITY(is->is_irq), __BIT(0)); 145 AIC_WRITE(sc, AIC_AFFINITY(is->is_irq), __BIT(0));
146 AIC_WRITE(sc, AIC_MASK_CLR(is->is_irq), 146 AIC_WRITE(sc, AIC_MASK_CLR(is->is_irq),
147 AIC_MASK_BIT(is->is_irq)); 147 AIC_MASK_BIT(is->is_irq));
148} 148}
149 149
150static void 150static void
151apple_intc_set_priority(struct pic_softc *pic, int ipl) 151apple_intc_set_priority(struct pic_softc *pic, int ipl)
152{ 152{
153} 153}
154 154
155static void 155static void
156apple_intc_cpu_init(struct pic_softc *pic, struct cpu_info *ci) 156apple_intc_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
157{ 157{
158 struct apple_intc_softc * const sc = PICTOSOFTC(pic); 158 struct apple_intc_softc * const sc = PICTOSOFTC(pic);
159 const u_int cpuno = cpu_index(ci); 159 const u_int cpuno = cpu_index(ci);
160 160
161 sc->sc_cpuid[cpuno] = AIC_READ(sc, AIC_WHOAMI); 161 sc->sc_cpuid[cpuno] = AIC_READ(sc, AIC_WHOAMI);
162} 162}
163 163
164static const struct pic_ops apple_intc_picops = { 164static const struct pic_ops apple_intc_picops = {
165 .pic_unblock_irqs = apple_intc_unblock_irqs, 165 .pic_unblock_irqs = apple_intc_unblock_irqs,
166 .pic_block_irqs = apple_intc_block_irqs, 166 .pic_block_irqs = apple_intc_block_irqs,
167 .pic_establish_irq = apple_intc_establish_irq, 167 .pic_establish_irq = apple_intc_establish_irq,
168 .pic_set_priority = apple_intc_set_priority, 168 .pic_set_priority = apple_intc_set_priority,
169#ifdef MULTIPROCESSOR 169#ifdef MULTIPROCESSOR
170 .pic_cpu_init = apple_intc_cpu_init, 170 .pic_cpu_init = apple_intc_cpu_init,
171#endif 171#endif
172}; 172};
173 173
174static void 174static void
175apple_intc_local_unblock_irqs(struct pic_softc *pic, size_t irqbase, 175apple_intc_local_unblock_irqs(struct pic_softc *pic, size_t irqbase,
176 uint32_t mask) 176 uint32_t mask)
177{ 177{
178 KASSERT(irqbase == 0); 178 KASSERT(irqbase == 0);
179 179
180 if ((mask & __BIT(LOCALPIC_SOURCE_TIMER)) != 0) { 180 if ((mask & __BIT(LOCALPIC_SOURCE_TIMER)) != 0) {
181 gtmr_cntv_ctl_write(gtmr_cntv_ctl_read() & ~CNTCTL_IMASK); 181 gtmr_cntv_ctl_write(gtmr_cntv_ctl_read() & ~CNTCTL_IMASK);
182 isb(); 182 isb();
183 } 183 }
184} 184}
185 185
186static void 186static void
187apple_intc_local_block_irqs(struct pic_softc *pic, size_t irqbase, 187apple_intc_local_block_irqs(struct pic_softc *pic, size_t irqbase,
188 uint32_t mask) 188 uint32_t mask)
189{ 189{
190 KASSERT(irqbase == 0); 190 KASSERT(irqbase == 0);
191 191
192 if ((mask & __BIT(LOCALPIC_SOURCE_TIMER)) != 0) { 192 if ((mask & __BIT(LOCALPIC_SOURCE_TIMER)) != 0) {
193 gtmr_cntv_ctl_write(gtmr_cntv_ctl_read() | CNTCTL_IMASK); 193 gtmr_cntv_ctl_write(gtmr_cntv_ctl_read() | CNTCTL_IMASK);
194 isb(); 194 isb();
195 } 195 }
196} 196}
197 197
198static void 198static void
199apple_intc_local_establish_irq(struct pic_softc *pic, struct intrsource *is) 199apple_intc_local_establish_irq(struct pic_softc *pic, struct intrsource *is)
200{ 200{
201} 201}
202 202
203#ifdef MULTIPROCESSOR 203#ifdef MULTIPROCESSOR
204static void 204static void
205apple_intc_local_ipi_send(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi) 205apple_intc_local_ipi_send(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
206{ 206{
207 struct apple_intc_percpu * const pc = PICTOPERCPU(pic); 207 struct apple_intc_percpu * const pc = PICTOPERCPU(pic);
208 struct apple_intc_softc * const sc = pc->pc_sc; 208 struct apple_intc_softc * const sc = pc->pc_sc;
209 const u_int target = sc->sc_cpuid[pc->pc_cpuid]; 209 const u_int target = sc->sc_cpuid[pc->pc_cpuid];
210 210
211 atomic_or_32(&pc->pc_ipimask, __BIT(ipi)); 211 atomic_or_32(&pc->pc_ipimask, __BIT(ipi));
212 AIC_WRITE(sc, AIC_IPI_SEND, __BIT(target)); 212 AIC_WRITE(sc, AIC_IPI_SEND, __BIT(target));
213} 213}
214#endif /* MULTIPROCESSOR */ 214#endif /* MULTIPROCESSOR */
215 215
216static const struct pic_ops apple_intc_localpicops = { 216static const struct pic_ops apple_intc_localpicops = {
217 .pic_unblock_irqs = apple_intc_local_unblock_irqs, 217 .pic_unblock_irqs = apple_intc_local_unblock_irqs,
218 .pic_block_irqs = apple_intc_local_block_irqs, 218 .pic_block_irqs = apple_intc_local_block_irqs,
219 .pic_establish_irq = apple_intc_local_establish_irq, 219 .pic_establish_irq = apple_intc_local_establish_irq,
220#ifdef MULTIPROCESSOR 220#ifdef MULTIPROCESSOR
221 .pic_ipi_send = apple_intc_local_ipi_send, 221 .pic_ipi_send = apple_intc_local_ipi_send,
222#endif 222#endif
223}; 223};
224 224
225static void * 225static void *
226apple_intc_fdt_establish(device_t dev, u_int *specifier, int ipl, int flags, 226apple_intc_fdt_establish(device_t dev, u_int *specifier, int ipl, int flags,
227 int (*func)(void *), void *arg, const char *xname) 227 int (*func)(void *), void *arg, const char *xname)
228{ 228{
229 struct apple_intc_softc * const sc = device_private(dev); 229 struct apple_intc_softc * const sc = device_private(dev);
230 230
231 /* 1st cell is the interrupt type (0=IRQ, 1=FIQ) */ 231 /* 1st cell is the interrupt type (0=IRQ, 1=FIQ) */
232 const u_int type = be32toh(specifier[0]); 232 const u_int type = be32toh(specifier[0]);
233 /* 2nd cell is the interrupt number */ 233 /* 2nd cell is the interrupt number */
234 const u_int intno = be32toh(specifier[1]); 234 const u_int intno = be32toh(specifier[1]);
235 /* 3rd cell is the interrupt flags */ 235 /* 3rd cell is the interrupt flags */
236 236
237 const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0; 237 const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
238 238
239 if (type == 0) 239 if (type == 0)
240 return intr_establish_xname(intno, ipl, IST_LEVEL | mpsafe, 240 return intr_establish_xname(intno, ipl, IST_LEVEL | mpsafe,
241 func, arg, xname); 241 func, arg, xname);
242 242
243 /* interate over CPUs for LOCALPIC_SOURCE_TIMER */ 243 /* interate over CPUs for LOCALPIC_SOURCE_TIMER */
244 CPU_INFO_ITERATOR cii; 244 CPU_INFO_ITERATOR cii;
245 struct cpu_info *ci; 245 struct cpu_info *ci;
246 void *ih = NULL; 246 void *ih = NULL;
247 for (CPU_INFO_FOREACH(cii, ci)) { 247 for (CPU_INFO_FOREACH(cii, ci)) {
248 const cpuid_t cpuno = cpu_index(ci); 248 const cpuid_t cpuno = cpu_index(ci);
249 struct apple_intc_percpu * const pc = &sc->sc_pc[cpuno]; 249 struct apple_intc_percpu * const pc = &sc->sc_pc[cpuno];
250 struct pic_softc * const pic = &pc->pc_pic; 250 struct pic_softc * const pic = &pc->pc_pic;
251 const int irq = pic->pic_irqbase + LOCALPIC_SOURCE_TIMER; 251 const int irq = pic->pic_irqbase + LOCALPIC_SOURCE_TIMER;
252 252
253 void *ihn = intr_establish_xname(irq, ipl, IST_LEVEL | mpsafe, 253 void *ihn = intr_establish_xname(irq, ipl, IST_LEVEL | mpsafe,
254 func, arg, xname); 254 func, arg, xname);
255 if (cpuno == 0) 255 if (cpuno == 0)
256 ih = ihn; 256 ih = ihn;
257 } 257 }
258 return ih; 258 return ih;
259} 259}
260 260
261static void 261static void
262apple_intc_fdt_disestablish(device_t dev, void *ih) 262apple_intc_fdt_disestablish(device_t dev, void *ih)
263{ 263{
264 intr_disestablish(ih); 264 intr_disestablish(ih);
265} 265}
266 266
267static bool 267static bool
268apple_intc_fdt_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen) 268apple_intc_fdt_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
269{ 269{
270 if (!specifier) 270 if (!specifier)
271 return false; 271 return false;
272 272
273 /* 1st cell is the interrupt type (0=IRQ, 1=FIQ) */ 273 /* 1st cell is the interrupt type (0=IRQ, 1=FIQ) */
274 const u_int type = be32toh(specifier[0]); 274 const u_int type = be32toh(specifier[0]);
275 /* 2nd cell is the interrupt number */ 275 /* 2nd cell is the interrupt number */
276 const u_int intno = be32toh(specifier[1]); 276 const u_int intno = be32toh(specifier[1]);
277 277
278 snprintf(buf, buflen, "%s %u", type == 0 ? "irq" : "fiq", intno); 278 snprintf(buf, buflen, "%s %u", type == 0 ? "irq" : "fiq", intno);
279 279
280 return true; 280 return true;
281} 281}
282 282
283static const struct fdtbus_interrupt_controller_func apple_intc_fdt_funcs = { 283static const struct fdtbus_interrupt_controller_func apple_intc_fdt_funcs = {
284 .establish = apple_intc_fdt_establish, 284 .establish = apple_intc_fdt_establish,
285 .disestablish = apple_intc_fdt_disestablish, 285 .disestablish = apple_intc_fdt_disestablish,
286 .intrstr = apple_intc_fdt_intrstr, 286 .intrstr = apple_intc_fdt_intrstr,
287}; 287};
288 288
289static void 289static void
290apple_intc_mark_pending(struct pic_softc *pic, u_int intno) 290apple_intc_mark_pending(struct pic_softc *pic, u_int intno)
291{ 291{
292 const int base = intno & ~0x1f; 292 const int base = intno & ~0x1f;
293 const uint32_t pending = __BIT(intno & 0x1f); 293 const uint32_t pending = __BIT(intno & 0x1f);
294 pic_mark_pending_sources(pic, base, pending); 294 pic_mark_pending_sources(pic, base, pending);
295} 295}
296 296
297static void 297static void
298apple_intc_irq_handler(void *frame) 298apple_intc_irq_handler(void *frame)
299{ 299{
300 struct cpu_info * const ci = curcpu(); 300 struct cpu_info * const ci = curcpu();
301 struct apple_intc_softc * const sc = intc_softc; 301 struct apple_intc_softc * const sc = intc_softc;
302 struct pic_softc *pic; 302 struct pic_softc *pic;
303 struct intrsource *is; 303 struct intrsource *is;
304 const int oldipl = ci->ci_cpl; 304 const int oldipl = ci->ci_cpl;
305 uint16_t evtype, evdata; 305 uint16_t evtype, evdata;
306 bus_size_t clr_reg; 306 bus_size_t clr_reg;
307 uint32_t clr_val; 307 uint32_t clr_val;
308 308
309 ci->ci_data.cpu_nintr++; 309 ci->ci_data.cpu_nintr++;
310 310
311 for (;;) { 311 for (;;) {
312 const uint32_t ev = AIC_READ(sc, AIC_EVENT); 312 const uint32_t ev = AIC_READ(sc, AIC_EVENT);
313 evtype = __SHIFTOUT(ev, AIC_EVENT_TYPE); 313 evtype = __SHIFTOUT(ev, AIC_EVENT_TYPE);
314 evdata = __SHIFTOUT(ev, AIC_EVENT_DATA); 314 evdata = __SHIFTOUT(ev, AIC_EVENT_DATA);
315 315
316 dsb(sy); 316 dsb(sy);
317 isb(); 317 isb();
318 318
319 if (evtype == AIC_EVENT_TYPE_IRQ) { 319 if (evtype == AIC_EVENT_TYPE_IRQ) {
320 KASSERT(evdata < sc->sc_nirq); 320 KASSERT(evdata < sc->sc_nirq);
321 pic = &sc->sc_pic; 321 pic = &sc->sc_pic;
322 is = pic->pic_sources[evdata]; 322 is = pic->pic_sources[evdata];
323 KASSERT(is != NULL); 323 KASSERT(is != NULL);
324 324
325 AIC_WRITE(sc, AIC_SW_CLR(evdata), 325 AIC_WRITE(sc, AIC_SW_CLR(evdata),
326 __BIT(evdata & 0x1f)); 326 __BIT(evdata & 0x1f));
327 327
328 clr_reg = AIC_MASK_CLR(evdata); 328 clr_reg = AIC_MASK_CLR(evdata);
329 clr_val = AIC_MASK_BIT(evdata); 329 clr_val = AIC_MASK_BIT(evdata);
330 } else if (evtype == AIC_EVENT_TYPE_IPI) { 330 } else if (evtype == AIC_EVENT_TYPE_IPI) {
331 KASSERT(evdata == AIC_EVENT_IPI_OTHER); 331 KASSERT(evdata == AIC_EVENT_IPI_OTHER);
332 pic = &sc->sc_pc[cpu_index(ci)].pc_pic; 332 pic = &sc->sc_pc[cpu_index(ci)].pc_pic;
333 is = pic->pic_sources[LOCALPIC_SOURCE_IPI]; 333 is = pic->pic_sources[LOCALPIC_SOURCE_IPI];
334 KASSERT(is != NULL); 334 KASSERT(is != NULL);
335 335
336 AIC_WRITE(sc, AIC_IPI_ACK, AIC_IPI_OTHER); 336 AIC_WRITE(sc, AIC_IPI_ACK, AIC_IPI_OTHER);
337 337
338 clr_reg = 0; 338 clr_reg = 0;
339 clr_val = 0; 339 clr_val = 0;
340 } else { 340 } else {
341 break; 341 break;
342 } 342 }
343 343
344 if (ci->ci_cpl >= is->is_ipl) { 344 if (ci->ci_cpl >= is->is_ipl) {
345 apple_intc_mark_pending(pic, is->is_irq); 345 apple_intc_mark_pending(pic, is->is_irq);
346 } else { 346 } else {
347 pic_set_priority(ci, is->is_ipl); 347 pic_set_priority(ci, is->is_ipl);
348 ENABLE_INTERRUPT(); 348 ENABLE_INTERRUPT();
349 pic_dispatch(is, frame); 349 pic_dispatch(is, frame);
350 DISABLE_INTERRUPT(); 350 DISABLE_INTERRUPT();
351 351
352 if (clr_val != 0) { 352 if (clr_val != 0) {
353 AIC_WRITE(sc, clr_reg, clr_val); 353 AIC_WRITE(sc, clr_reg, clr_val);
354 } 354 }
355 } 355 }
356 } 356 }
357 357
358 if (oldipl != IPL_HIGH) { 358 if (oldipl != IPL_HIGH) {
359 pic_do_pending_ints(DAIF_I|DAIF_F, oldipl, frame); 359 pic_do_pending_ints(DAIF_I|DAIF_F, oldipl, frame);
360 } 360 }
361} 361}
362 362
363static void 363static void
364apple_intc_fiq_handler(void *frame) 364apple_intc_fiq_handler(void *frame)
365{ 365{
366 struct cpu_info * const ci = curcpu(); 366 struct cpu_info * const ci = curcpu();
367 struct apple_intc_softc * const sc = intc_softc; 367 struct apple_intc_softc * const sc = intc_softc;
368 struct pic_softc * const pic = &sc->sc_pc[cpu_index(ci)].pc_pic; 368 struct pic_softc * const pic = &sc->sc_pc[cpu_index(ci)].pc_pic;
369 const int oldipl = ci->ci_cpl; 369 const int oldipl = ci->ci_cpl;
370 370
371 ci->ci_data.cpu_nintr++; 371 ci->ci_data.cpu_nintr++;
372 372
373 struct intrsource * const is = pic->pic_sources[LOCALPIC_SOURCE_TIMER]; 373 struct intrsource * const is = pic->pic_sources[LOCALPIC_SOURCE_TIMER];
374 374
375 dsb(sy); 375 dsb(sy);
376 isb(); 376 isb();
377 377
378 if (oldipl >= is->is_ipl) { 378 if (oldipl >= is->is_ipl) {
379 apple_intc_mark_pending(pic, LOCALPIC_SOURCE_TIMER); 379 apple_intc_mark_pending(pic, LOCALPIC_SOURCE_TIMER);
380 } else { 380 } else {
381 pic_set_priority(ci, is->is_ipl); 381 pic_set_priority(ci, is->is_ipl);
382 pic_dispatch(is, frame); 382 pic_dispatch(is, frame);
383 } 383 }
384 384
385 if (oldipl != IPL_HIGH) { 385 if (oldipl != IPL_HIGH) {
386 pic_do_pending_ints(DAIF_I|DAIF_F, oldipl, frame); 386 pic_do_pending_ints(DAIF_I|DAIF_F, oldipl, frame);
387 } 387 }
388} 388}
389 389
390#ifdef MULTIPROCESSOR 390#ifdef MULTIPROCESSOR
391static int 391static int
392apple_intc_ipi_handler(void *priv) 392apple_intc_ipi_handler(void *priv)
393{ 393{
394 struct apple_intc_percpu * const pc = priv; 394 struct apple_intc_percpu * const pc = priv;
395 struct apple_intc_softc * const sc = pc->pc_sc; 395 struct apple_intc_softc * const sc = pc->pc_sc;
396 uint32_t ipimask, bit; 396 uint32_t ipimask, bit;
397 397
398 AIC_WRITE(sc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); 398 AIC_WRITE(sc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER);
399 ipimask = atomic_swap_32(&pc->pc_ipimask, 0); 399 ipimask = atomic_swap_32(&pc->pc_ipimask, 0);
400 400
401 while ((bit = ffs(ipimask)) > 0) { 401 while ((bit = ffs(ipimask)) > 0) {
402 const u_int ipi = bit - 1; 402 const u_int ipi = bit - 1;
403 403
404 switch (ipi) { 404 switch (ipi) {
405 case IPI_AST: 405 case IPI_AST:
406 pic_ipi_ast(priv); 406 pic_ipi_ast(priv);
407 break; 407 break;
408 case IPI_NOP: 408 case IPI_NOP:
409 pic_ipi_nop(priv); 409 pic_ipi_nop(priv);
410 break; 410 break;
411#ifdef __HAVE_PREEMPTION 411#ifdef __HAVE_PREEMPTION
412 case IPI_KPREEMPT: 412 case IPI_KPREEMPT:
413 pic_ipi_kpreempt(priv); 413 pic_ipi_kpreempt(priv);
414 break; 414 break;
415#endif 415#endif
416 case IPI_XCALL: 416 case IPI_XCALL:
417 pic_ipi_xcall(priv); 417 pic_ipi_xcall(priv);
418 break; 418 break;
419 case IPI_GENERIC: 419 case IPI_GENERIC:
420 pic_ipi_generic(priv); 420 pic_ipi_generic(priv);
421 break; 421 break;
422 case IPI_SHOOTDOWN: 422 case IPI_SHOOTDOWN:
423 pic_ipi_shootdown(priv); 423 pic_ipi_shootdown(priv);
424 break; 424 break;
425#ifdef DDB 425#ifdef DDB
426 case IPI_DDB: 426 case IPI_DDB:
427 pic_ipi_ddb(priv); 427 pic_ipi_ddb(priv);
428 break; 428 break;
429#endif 429#endif
430 } 430 }
431 ipimask &= ~__BIT(ipi); 431 ipimask &= ~__BIT(ipi);
432 } 432 }
433 433
434 return 1; 434 return 1;
435} 435}
436#endif /* MULTIPROCESSOR */ 436#endif /* MULTIPROCESSOR */
437 437
438static int 438static int
439apple_intc_match(device_t parent, cfdata_t cf, void *aux) 439apple_intc_match(device_t parent, cfdata_t cf, void *aux)
440{ 440{
441 struct fdt_attach_args * const faa = aux; 441 struct fdt_attach_args * const faa = aux;
442 442
443 return of_compatible_match(faa->faa_phandle, compat_data); 443 return of_compatible_match(faa->faa_phandle, compat_data);
444} 444}
445 445
446static void 446static void
447apple_intc_attach(device_t parent, device_t self, void *aux) 447apple_intc_attach(device_t parent, device_t self, void *aux)
448{ 448{
449 struct apple_intc_softc * const sc = device_private(self); 449 struct apple_intc_softc * const sc = device_private(self);
450 struct fdt_attach_args * const faa = aux; 450 struct fdt_attach_args * const faa = aux;
451 const int phandle = faa->faa_phandle; 451 const int phandle = faa->faa_phandle;
452 bus_addr_t addr; 452 bus_addr_t addr;
453 bus_size_t size; 453 bus_size_t size;
454 int error; 454 int error;
455 455
456 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 456 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
457 aprint_error(": couldn't get registers\n"); 457 aprint_error(": couldn't get registers\n");
458 return; 458 return;
459 } 459 }
460 460
461 sc->sc_dev = self; 461 sc->sc_dev = self;
462 sc->sc_bst = faa->faa_bst; 462 sc->sc_bst = faa->faa_bst;
463 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 463 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
464 aprint_error(": couldn't map registers\n"); 464 aprint_error(": couldn't map registers\n");
465 return; 465 return;
466 } 466 }
467 467
468 sc->sc_nirq = AIC_READ(sc, AIC_INFO) & AIC_INFO_NIRQ; 468 sc->sc_nirq = AIC_READ(sc, AIC_INFO) & AIC_INFO_NIRQ;
469 469
470 aprint_naive("\n"); 470 aprint_naive("\n");
471 aprint_normal(": Apple AIC (%u IRQs, 1 FIQ)\n", sc->sc_nirq); 471 aprint_normal(": Apple AIC (%u IRQs, 1 FIQ)\n", sc->sc_nirq);
472 KASSERT(sc->sc_nirq % 32 == 0); 472 KASSERT(sc->sc_nirq % 32 == 0);
473 473
474 sc->sc_pic.pic_ops = &apple_intc_picops; 474 sc->sc_pic.pic_ops = &apple_intc_picops;
475 sc->sc_pic.pic_maxsources = sc->sc_nirq; 475 sc->sc_pic.pic_maxsources = sc->sc_nirq;
476 snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "AIC"); 476 snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "AIC");
477 pic_add(&sc->sc_pic, 0); 477 pic_add(&sc->sc_pic, 0);
478 478
479 error = fdtbus_register_interrupt_controller(self, phandle, 479 error = fdtbus_register_interrupt_controller(self, phandle,
480 &apple_intc_fdt_funcs); 480 &apple_intc_fdt_funcs);
481 if (error) { 481 if (error) {
482 aprint_error_dev(self, "couldn't register with fdtbus: %d\n", 482 aprint_error_dev(self, "couldn't register with fdtbus: %d\n",
483 error); 483 error);
484 return; 484 return;
485 } 485 }
486 486
487 KASSERT(intc_softc == NULL); 487 KASSERT(intc_softc == NULL);
488 intc_softc = sc; 488 intc_softc = sc;
489 arm_fdt_irq_set_handler(apple_intc_irq_handler); 489 arm_fdt_irq_set_handler(apple_intc_irq_handler);
490 arm_fdt_fiq_set_handler(apple_intc_fiq_handler); 490 arm_fdt_fiq_set_handler(apple_intc_fiq_handler);
491 491
492 KASSERT(ncpu != 0); 492 KASSERT(ncpu != 0);
493 sc->sc_cpuid = kmem_zalloc(sizeof(*sc->sc_cpuid) * ncpu, KM_SLEEP); 493 sc->sc_cpuid = kmem_zalloc(sizeof(*sc->sc_cpuid) * ncpu, KM_SLEEP);
494 sc->sc_pc = kmem_zalloc(sizeof(*sc->sc_pc) * ncpu, KM_SLEEP); 494 sc->sc_pc = kmem_zalloc(sizeof(*sc->sc_pc) * ncpu, KM_SLEEP);
495 495
496 CPU_INFO_ITERATOR cii; 496 CPU_INFO_ITERATOR cii;
497 struct cpu_info *ci; 497 struct cpu_info *ci;
498 for (CPU_INFO_FOREACH(cii, ci)) { 498 for (CPU_INFO_FOREACH(cii, ci)) {
499 const cpuid_t cpuno = cpu_index(ci); 499 const cpuid_t cpuno = cpu_index(ci);
500 struct apple_intc_percpu * const pc = &sc->sc_pc[cpuno]; 500 struct apple_intc_percpu * const pc = &sc->sc_pc[cpuno];
501 struct pic_softc * const pic = &pc->pc_pic; 501 struct pic_softc * const pic = &pc->pc_pic;
502 502
503 pc->pc_sc = sc; 503 pc->pc_sc = sc;
504 pc->pc_cpuid = cpuno; 504 pc->pc_cpuid = cpuno;
505 505
 506#ifdef MULTIPROCESSOR
506 pic->pic_cpus = ci->ci_kcpuset; 507 pic->pic_cpus = ci->ci_kcpuset;
 508#endif
507 pic->pic_ops = &apple_intc_localpicops; 509 pic->pic_ops = &apple_intc_localpicops;
508 pic->pic_maxsources = 2; 510 pic->pic_maxsources = 2;
509 snprintf(pic->pic_name, sizeof(pic->pic_name), "AIC/%lu", cpuno); 511 snprintf(pic->pic_name, sizeof(pic->pic_name), "AIC/%lu", cpuno);
510 512
511 pic_add(pic, PIC_IRQBASE_ALLOC); 513 pic_add(pic, PIC_IRQBASE_ALLOC);
512 514
 515#ifdef MULTIPROCESSOR
513 intr_establish_xname(pic->pic_irqbase + LOCALPIC_SOURCE_IPI, 516 intr_establish_xname(pic->pic_irqbase + LOCALPIC_SOURCE_IPI,
514 IPL_HIGH, IST_LEVEL | IST_MPSAFE, apple_intc_ipi_handler, 517 IPL_HIGH, IST_LEVEL | IST_MPSAFE, apple_intc_ipi_handler,
515 pc, "ipi"); 518 pc, "ipi");
 519#endif
516 } 520 }
517 521
518 apple_intc_cpu_init(&sc->sc_pic, curcpu()); 522 apple_intc_cpu_init(&sc->sc_pic, curcpu());
519} 523}
520 524
521CFATTACH_DECL_NEW(apple_intc, sizeof(struct apple_intc_softc), 525CFATTACH_DECL_NEW(apple_intc, sizeof(struct apple_intc_softc),
522 apple_intc_match, apple_intc_attach, NULL, NULL); 526 apple_intc_match, apple_intc_attach, NULL, NULL);