mpic.c (296893) | mpic.c (297539) |
---|---|
1/*- 2 * Copyright (c) 2006 Benno Rice. 3 * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD. 4 * Copyright (c) 2012 Semihalf. 5 * All rights reserved. 6 * 7 * Developed by Semihalf. 8 * --- 17 unchanged lines hidden (view full) --- 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_icu.c, rev 1 30 * from: FreeBSD: src/sys/arm/mv/ic.c,v 1.5 2011/02/08 01:49:30 31 */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2006 Benno Rice. 3 * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD. 4 * Copyright (c) 2012 Semihalf. 5 * All rights reserved. 6 * 7 * Developed by Semihalf. 8 * --- 17 unchanged lines hidden (view full) --- 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_icu.c, rev 1 30 * from: FreeBSD: src/sys/arm/mv/ic.c,v 1.5 2011/02/08 01:49:30 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/arm/mv/mpic.c 296893 2016-03-15 06:06:09Z wma $"); | 34__FBSDID("$FreeBSD: head/sys/arm/mv/mpic.c 297539 2016-04-04 09:15:25Z skra $"); |
35 36#include "opt_platform.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/bus.h> 41#include <sys/kernel.h> 42#include <sys/cpuset.h> --- 50 unchanged lines hidden (view full) --- 93#define MPIC_CTP 0x40 94#define MPIC_IIACK 0x44 95#define MPIC_ISM 0x48 96#define MPIC_ICM 0x4c 97#define MPIC_ERR_MASK 0xe50 98 99#define MPIC_PPI 32 100 | 35 36#include "opt_platform.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/bus.h> 41#include <sys/kernel.h> 42#include <sys/cpuset.h> --- 50 unchanged lines hidden (view full) --- 93#define MPIC_CTP 0x40 94#define MPIC_IIACK 0x44 95#define MPIC_ISM 0x48 96#define MPIC_ICM 0x4c 97#define MPIC_ERR_MASK 0xe50 98 99#define MPIC_PPI 32 100 |
101#ifdef ARM_INTRNG 102struct mv_mpic_irqsrc { 103 struct intr_irqsrc mmi_isrc; 104 u_int mmi_irq; 105}; 106#endif 107 |
|
101struct mv_mpic_softc { 102 device_t sc_dev; 103 struct resource * mpic_res[4]; 104 bus_space_tag_t mpic_bst; 105 bus_space_handle_t mpic_bsh; 106 bus_space_tag_t cpu_bst; 107 bus_space_handle_t cpu_bsh; 108 bus_space_tag_t drbl_bst; 109 bus_space_handle_t drbl_bsh; 110 struct mtx mtx; | 108struct mv_mpic_softc { 109 device_t sc_dev; 110 struct resource * mpic_res[4]; 111 bus_space_tag_t mpic_bst; 112 bus_space_handle_t mpic_bsh; 113 bus_space_tag_t cpu_bst; 114 bus_space_handle_t cpu_bsh; 115 bus_space_tag_t drbl_bst; 116 bus_space_handle_t drbl_bsh; 117 struct mtx mtx; |
111 112 struct intr_irqsrc ** mpic_isrcs; | 118#ifdef ARM_INTRNG 119 struct mv_mpic_irqsrc * mpic_isrcs; 120#endif |
113 int nirqs; 114 void * intr_hand; 115}; 116 117static struct resource_spec mv_mpic_spec[] = { 118 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 119 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 120 { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL }, --- 51 unchanged lines hidden (view full) --- 172 173 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 174 return (ENXIO); 175 176 device_set_desc(dev, "Marvell Integrated Interrupt Controller"); 177 return (0); 178} 179 | 121 int nirqs; 122 void * intr_hand; 123}; 124 125static struct resource_spec mv_mpic_spec[] = { 126 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 127 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 128 { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL }, --- 51 unchanged lines hidden (view full) --- 180 181 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 182 return (ENXIO); 183 184 device_set_desc(dev, "Marvell Integrated Interrupt Controller"); 185 return (0); 186} 187 |
188#ifdef ARM_INTRNG |
|
180static int | 189static int |
190mv_mpic_register_isrcs(struct mv_mpic_softc *sc) 191{ 192 int error; 193 uint32_t irq; 194 struct intr_irqsrc *isrc; 195 const char *name; 196 197 sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF, 198 M_WAITOK | M_ZERO); 199 200 name = device_get_nameunit(sc->sc_dev); 201 for (irq = 0; irq < sc->nirqs; irq++) { 202 sc->mpic_isrcs[irq].mmi_irq = irq; 203 204 isrc = &sc->mpic_isrcs[irq].mmi_isrc; 205 if (irq < MPIC_PPI) { 206 error = intr_isrc_register(isrc, sc->sc_dev, 207 INTR_ISRCF_PPI, "%s", name); 208 } else { 209 error = intr_isrc_register(isrc, sc->sc_dev, 0, "%s", 210 name); 211 } 212 if (error != 0) { 213 /* XXX call intr_isrc_deregister() */ 214 device_printf(sc->sc_dev, "%s failed", __func__); 215 return (error); 216 } 217 } 218 return (0); 219} 220#endif 221 222static int |
|
181mv_mpic_attach(device_t dev) 182{ 183 struct mv_mpic_softc *sc; 184 int error; 185 uint32_t val; 186 187 sc = (struct mv_mpic_softc *)device_get_softc(dev); 188 --- 33 unchanged lines hidden (view full) --- 222 bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, 223 MPIC_CTRL, 1); 224 MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0); 225 226 val = MPIC_READ(mv_mpic_sc, MPIC_CTRL); 227 sc->nirqs = MPIC_CTRL_NIRQS(val); 228 229#ifdef ARM_INTRNG | 223mv_mpic_attach(device_t dev) 224{ 225 struct mv_mpic_softc *sc; 226 int error; 227 uint32_t val; 228 229 sc = (struct mv_mpic_softc *)device_get_softc(dev); 230 --- 33 unchanged lines hidden (view full) --- 264 bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh, 265 MPIC_CTRL, 1); 266 MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0); 267 268 val = MPIC_READ(mv_mpic_sc, MPIC_CTRL); 269 sc->nirqs = MPIC_CTRL_NIRQS(val); 270 271#ifdef ARM_INTRNG |
230 sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF, 231 M_WAITOK | M_ZERO); 232 | 272 if (mv_mpic_register_isrcs(sc) != 0) { 273 device_printf(dev, "could not register PIC ISRCs\n"); 274 bus_release_resources(dev, mv_mpic_spec, sc->mpic_res); 275 return (ENXIO); 276 } |
233 if (intr_pic_register(dev, OF_xref_from_device(dev)) != 0) { 234 device_printf(dev, "could not register PIC\n"); 235 bus_release_resources(dev, mv_mpic_spec, sc->mpic_res); 236 return (ENXIO); 237 } 238#endif 239 240 mpic_unmask_msi(); 241 242 return (0); 243} 244 245#ifdef ARM_INTRNG 246static int 247mpic_intr(void *arg) 248{ 249 struct mv_mpic_softc *sc; | 277 if (intr_pic_register(dev, OF_xref_from_device(dev)) != 0) { 278 device_printf(dev, "could not register PIC\n"); 279 bus_release_resources(dev, mv_mpic_spec, sc->mpic_res); 280 return (ENXIO); 281 } 282#endif 283 284 mpic_unmask_msi(); 285 286 return (0); 287} 288 289#ifdef ARM_INTRNG 290static int 291mpic_intr(void *arg) 292{ 293 struct mv_mpic_softc *sc; |
250 struct trapframe *tf; 251 struct intr_irqsrc *isrc; | |
252 uint32_t cause, irqsrc; 253 unsigned int irq; 254 u_int cpuid; 255 256 sc = arg; | 294 uint32_t cause, irqsrc; 295 unsigned int irq; 296 u_int cpuid; 297 298 sc = arg; |
257 tf = curthread->td_intr_frame; | |
258 cpuid = PCPU_GET(cpuid); 259 irq = 0; 260 261 for (cause = MPIC_CPU_READ(sc, MPIC_PPI_CAUSE); cause > 0; 262 cause >>= 1, irq++) { 263 if (cause & 1) { 264 irqsrc = MPIC_READ(sc, MPIC_INT_CTL(irq)); 265 if ((irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid)) == 0) 266 continue; | 299 cpuid = PCPU_GET(cpuid); 300 irq = 0; 301 302 for (cause = MPIC_CPU_READ(sc, MPIC_PPI_CAUSE); cause > 0; 303 cause >>= 1, irq++) { 304 if (cause & 1) { 305 irqsrc = MPIC_READ(sc, MPIC_INT_CTL(irq)); 306 if ((irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid)) == 0) 307 continue; |
267 isrc = sc->mpic_isrcs[irq]; 268 if (isrc == NULL) { 269 device_printf(sc->sc_dev, "Stray interrupt %u detected\n", irq); | 308 if (intr_isrc_dispatch(&sc->mpic_isrcs[irq].mmi_isrc, 309 curthread->td_intr_frame) != 0) { |
270 mpic_mask_irq(irq); | 310 mpic_mask_irq(irq); |
271 continue; | 311 device_printf(sc->sc_dev, "Stray irq %u " 312 "disabled\n", irq); |
272 } | 313 } |
273 intr_irq_dispatch(isrc, tf); | |
274 } 275 } 276 277 return (FILTER_HANDLED); 278} 279 | 314 } 315 } 316 317 return (FILTER_HANDLED); 318} 319 |
280static int 281mpic_attach_isrc(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int irq) | 320static void 321mpic_disable_intr(device_t dev, struct intr_irqsrc *isrc) |
282{ | 322{ |
283 const char *name; | 323 u_int irq; |
284 | 324 |
285 mtx_lock_spin(&sc->mtx); 286 if (sc->mpic_isrcs[irq] != NULL) { 287 mtx_unlock_spin(&sc->mtx); 288 return (sc->mpic_isrcs[irq] == isrc ? 0 : EEXIST); 289 } 290 sc->mpic_isrcs[irq] = isrc; 291 isrc->isrc_data = irq; 292 mtx_unlock_spin(&sc->mtx); 293 294 name = device_get_nameunit(sc->sc_dev); 295 intr_irq_set_name(isrc, "%s", name); 296 297 return (0); | 325 irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq; 326 mpic_mask_irq(irq); |
298} 299 | 327} 328 |
300#ifdef FDT 301static int 302mpic_map_fdt(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp) | 329static void 330mpic_enable_intr(device_t dev, struct intr_irqsrc *isrc) |
303{ 304 u_int irq; | 331{ 332 u_int irq; |
305 int error; | |
306 | 333 |
307 if (isrc->isrc_ncells != 1) 308 return (EINVAL); 309 310 irq = isrc->isrc_cells[0]; 311 312 error = mpic_attach_isrc(sc, isrc, irq); 313 if (error != 0) 314 return (error); 315 316 isrc->isrc_nspc_num = irq; 317 isrc->isrc_trig = INTR_TRIGGER_CONFORM; 318 isrc->isrc_pol = INTR_POLARITY_CONFORM; 319 isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN; 320 321 *irqp = irq; 322 323 return (0); | 334 irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq; 335 mpic_unmask_irq(irq); |
324} | 336} |
325#endif | |
326 327static int | 337 338static int |
328mpic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu) | 339mpic_map_intr(device_t dev, struct intr_map_data *data, 340 struct intr_irqsrc **isrcp) |
329{ 330 struct mv_mpic_softc *sc; | 341{ 342 struct mv_mpic_softc *sc; |
331 int error; 332 u_int irq = 0; | |
333 334 sc = device_get_softc(dev); 335 | 343 344 sc = device_get_softc(dev); 345 |
336#ifdef FDT 337 if (isrc->isrc_type == INTR_ISRCT_FDT) 338 error = mpic_map_fdt(sc, isrc, &irq); 339 else 340#endif 341 error = EINVAL; | 346 if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells !=1 || 347 data->fdt.cells[0] >= sc->nirqs) 348 return (EINVAL); |
342 | 349 |
343 if (error == 0) 344 *is_percpu = irq < MPIC_PPI; 345 346 return (error); | 350 *isrcp = &sc->mpic_isrcs[data->fdt.cells[0]].mmi_isrc; 351 return (0); |
347} 348 349static void | 352} 353 354static void |
350mpic_disable_source(device_t dev, struct intr_irqsrc *isrc) 351{ 352 u_int irq; 353 354 irq = isrc->isrc_data; 355 mpic_mask_irq(irq); 356} 357 358static void 359mpic_enable_source(device_t dev, struct intr_irqsrc *isrc) 360{ 361 u_int irq; 362 363 irq = isrc->isrc_data; 364 mpic_unmask_irq(irq); 365} 366static void | |
367mpic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) 368{ 369 | 355mpic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) 356{ 357 |
370 mpic_disable_source(dev, isrc); | 358 mpic_disable_intr(dev, isrc); |
371} 372 373static void 374mpic_post_ithread(device_t dev, struct intr_irqsrc *isrc) 375{ 376 | 359} 360 361static void 362mpic_post_ithread(device_t dev, struct intr_irqsrc *isrc) 363{ 364 |
377 mpic_enable_source(dev, isrc); | 365 mpic_enable_intr(dev, isrc); |
378} 379#endif 380 381static device_method_t mv_mpic_methods[] = { 382 DEVMETHOD(device_probe, mv_mpic_probe), 383 DEVMETHOD(device_attach, mv_mpic_attach), 384 385#ifdef ARM_INTRNG | 366} 367#endif 368 369static device_method_t mv_mpic_methods[] = { 370 DEVMETHOD(device_probe, mv_mpic_probe), 371 DEVMETHOD(device_attach, mv_mpic_attach), 372 373#ifdef ARM_INTRNG |
386 DEVMETHOD(pic_register, mpic_register), 387 DEVMETHOD(pic_disable_source, mpic_disable_source), 388 DEVMETHOD(pic_enable_source, mpic_enable_source), | 374 DEVMETHOD(pic_disable_intr, mpic_disable_intr), 375 DEVMETHOD(pic_enable_intr, mpic_enable_intr), 376 DEVMETHOD(pic_map_intr, mpic_map_intr), |
389 DEVMETHOD(pic_post_ithread, mpic_post_ithread), 390 DEVMETHOD(pic_pre_ithread, mpic_pre_ithread), 391#endif 392 { 0, 0 } 393}; 394 395static driver_t mv_mpic_driver = { 396 "mpic", --- 247 unchanged lines hidden --- | 377 DEVMETHOD(pic_post_ithread, mpic_post_ithread), 378 DEVMETHOD(pic_pre_ithread, mpic_pre_ithread), 379#endif 380 { 0, 0 } 381}; 382 383static driver_t mv_mpic_driver = { 384 "mpic", --- 247 unchanged lines hidden --- |