Index: sys/conf/options.mips =================================================================== --- sys/conf/options.mips +++ sys/conf/options.mips @@ -136,3 +136,7 @@ # Options that affect the pmap. # PV_STATS opt_pmap.h +# +# Options to use ARM_INTRNG code +# +MIPS_INTRNG opt_global.h Index: sys/mips/include/intr.h =================================================================== --- /dev/null +++ sys/mips/include/intr.h @@ -0,0 +1,149 @@ +/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#ifdef FDT +#include +#endif + +#ifndef NIRQ +#define NIRQ 128 /* XXX - It should be an option and match size used in exception.S */ +#endif + +#ifdef notyet +#define INTR_SOLO INTR_MD1 +typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); +#else +typedef int intr_irq_filter_t(void *arg); +#endif + +#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1) + +typedef void intr_ipi_filter_t(void *arg); + +enum intr_isrc_type { + INTR_ISRCT_NAMESPACE, + INTR_ISRCT_FDT +}; + +#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */ +#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */ +#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */ + +/* Interrupt source definition. */ +struct intr_irqsrc { + device_t isrc_dev; /* where isrc is mapped */ + intptr_t isrc_xref; /* device reference key */ + uintptr_t isrc_data; /* device data for isrc */ + u_int isrc_irq; /* unique identificator */ + enum intr_isrc_type isrc_type; /* how is isrc decribed */ + u_int isrc_flags; + char isrc_name[INTR_ISRC_NAMELEN]; + uint16_t isrc_nspc_type; + uint16_t isrc_nspc_num; + enum intr_trigger isrc_trig; + enum intr_polarity isrc_pol; + cpuset_t isrc_cpu; /* on which CPUs is enabled */ + u_int isrc_index; + u_long * isrc_count; + u_int isrc_handlers; + struct intr_event * isrc_event; + intr_irq_filter_t * isrc_filter; + intr_ipi_filter_t * isrc_ipifilter; + void * isrc_arg; +#ifdef FDT + u_int isrc_ncells; + pcell_t isrc_cells[]; /* leave it last */ +#endif +}; + +void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...) + __printflike(2, 3); + +void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); + +#define INTR_IRQ_NSPC_NONE 0 +#define INTR_IRQ_NSPC_PLAIN 1 +#define INTR_IRQ_NSPC_IRQ 2 +#define INTR_IRQ_NSPC_IPI 3 +#define INTR_IRQ_NSPC_SWI 4 + +u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num); +#ifdef FDT +u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int); +#endif + +int intr_pic_register(device_t dev, intptr_t xref); +int intr_pic_unregister(device_t dev, intptr_t xref); +int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, + void *arg, u_int ipicount); + +int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *, + u_int, int, void **); +int intr_irq_remove_handler(device_t dev, u_int, void *); +int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity); +int intr_irq_describe(u_int, void *, const char *); + +u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); + +#ifdef SMP +int intr_irq_bind(u_int, int); + +void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); + +#define AISHF_NOALLOC 0x0001 + +int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, + void *arg, u_int flags); + +void intr_pic_init_secondary(void); +#endif + +/* MIPS compatibility for legacy mips code */ +void cpu_init_interrupts(void); +void cpu_establish_hardintr(const char *, driver_filter_t *, driver_intr_t *, + void *, int, int, void **); +void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*), + void *, int, int, void **); +/* MIPS interrupt C entry point */ +void cpu_intr(struct trapframe *); + + +#endif /* _MACHINE_INTR_H */ Index: sys/mips/include/smp.h =================================================================== --- sys/mips/include/smp.h +++ sys/mips/include/smp.h @@ -21,6 +21,11 @@ #include +#ifdef MIPS_INTRNG +# define MIPS_IPI_COUNT 1 +# define INTR_IPI_COUNT MIPS_IPI_COUNT +#endif + /* * Interprocessor interrupts for SMP. */ Index: sys/mips/mips/exception.S =================================================================== --- sys/mips/mips/exception.S +++ sys/mips/mips/exception.S @@ -640,7 +640,11 @@ * Call the interrupt handler. a0 points at the saved frame. */ PTR_LA gp, _C_LABEL(_gp) +#ifdef MIPS_INTRNG + PTR_LA k0, _C_LABEL(intr_irq_handler) +#else PTR_LA k0, _C_LABEL(cpu_intr) +#endif jalr k0 REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging @@ -752,7 +756,11 @@ /* * Call the interrupt handler. */ +#ifdef MIPS_INTRNG + PTR_LA k0, _C_LABEL(intr_irq_handler) +#else PTR_LA k0, _C_LABEL(cpu_intr) +#endif jalr k0 REG_S a3, CALLFRAME_RA(sp) # for debugging @@ -1184,6 +1192,7 @@ PTR_ADDU sp, sp, CALLFRAME_SIZ END(MipsFPTrap) +#ifndef MIPS_INTRNG /* * Interrupt counters for vmstat. */ @@ -1210,6 +1219,7 @@ #else .int INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2 #endif +#endif /* MIPS_INTRNG */ /* Index: sys/mips/mips/nexus.c =================================================================== --- sys/mips/mips/nexus.c +++ sys/mips/mips/nexus.c @@ -36,6 +36,7 @@ * this code implements the core resource managers for interrupt * requests and memory address space. */ +#include "opt_platform.h" #include __FBSDID("$FreeBSD$"); @@ -53,13 +54,22 @@ #include #include -#include #include #include #include +#ifdef MIPS_INTRNG +#include +#else +#include +#endif #include "opt_platform.h" +#ifdef FDT +#include +#include "ofw_bus_if.h" +#endif + #undef NEXUS_DEBUG #ifdef NEXUS_DEBUG #define dprintf printf @@ -107,6 +117,19 @@ driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); +#ifdef MIPS_INTRNG +#ifdef SMP +static int nexus_bind_intr(device_t, device_t, struct resource *, int); +#endif +#ifdef FDT +static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, + int icells, pcell_t *intr); +#endif +static int nexus_describe_intr(device_t dev, device_t child, + struct resource *irq, void *cookie, const char *descr); +static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol); +#endif static device_method_t nexus_methods[] = { /* Device interface */ @@ -127,7 +150,16 @@ DEVMETHOD(bus_activate_resource,nexus_activate_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_hinted_child, nexus_hinted_child), - +#ifdef MIPS_INTRNG + DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_describe_intr, nexus_describe_intr), +#ifdef SMP + DEVMETHOD(bus_bind_intr, nexus_bind_intr), +#endif +#ifdef FDT + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), +#endif +#endif { 0, 0 } }; @@ -381,6 +413,7 @@ void *vaddr; vm_paddr_t paddr; vm_size_t psize; + int err; /* * If this is a memory resource, use pmap_mapdev to map it. @@ -388,10 +421,25 @@ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { paddr = rman_get_start(r); psize = rman_get_size(r); - vaddr = pmap_mapdev(paddr, psize); +#ifdef FDT + err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0, + (bus_space_handle_t *)&vaddr); + if (err != 0) { + rman_deactivate_resource(r); + return (err); + } + rman_set_bustag(r, fdtbus_bs_tag); +#else + vaddr = (bus_space_handle_t)pmap_mapdev(paddr, + (vm_size_t)psize); + if (vaddr == 0) { + rman_deactivate_resource(r); + return (ENOMEM); + } + rman_set_bustag(r, mips_bus_space_generic); +#endif rman_set_virtual(r, vaddr); - rman_set_bustag(r, mips_bus_space_generic); rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr); } @@ -402,11 +450,20 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - vm_offset_t va; - - if (type == SYS_RES_MEMORY) { - va = (vm_offset_t)rman_get_virtual(r); - pmap_unmapdev(va, rman_get_size(r)); + bus_space_handle_t vaddr; + bus_size_t psize; + + vaddr = rman_get_bushandle(r); + + if (type == SYS_RES_MEMORY && vaddr != 0) { + psize = (bus_size_t)rman_get_size(r); +#ifdef FDT + bus_space_unmap(fdtbus_bs_tag, vaddr, psize); +#else + pmap_unmapdev((vm_offset_t)vaddr, psize); +#endif + rman_set_virtual(r, NULL); + rman_set_bushandle(r, 0); } return (rman_deactivate_resource(r)); @@ -416,9 +473,16 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { - register_t s; int irq; +#ifdef MIPS_INTRNG + for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { + intr_irq_add_handler(child, filt, intr, arg, irq, flags, + cookiep); + } +#else + register_t s; + s = intr_disable(); irq = rman_get_start(res); if (irq >= NUM_MIPS_IRQS) { @@ -429,6 +493,7 @@ cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg, irq, flags, cookiep); intr_restore(s); +#endif return (0); } @@ -436,9 +501,53 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { +#ifdef MIPS_INTRNG + return (intr_irq_remove_handler(child, rman_get_start(r), ih)); +#else printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__); return (0); +#endif +} + +#ifdef MIPS_INTRNG +static int +nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol) +{ + int ret = ENODEV; + +#ifdef MIPS_INTRNG + ret = intr_irq_config(irq, trig, pol); +#endif + return (ret); +} + +static int +nexus_describe_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *descr) +{ + + return (intr_irq_describe(rman_get_start(irq), cookie, descr)); +} + +#ifdef SMP +static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + + return (intr_irq_bind(rman_get_start(irq), cpu)); +} +#endif + +#ifdef FDT +static int +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *intr) +{ + return (intr_fdt_map_irq(iparent, intr, icells)); } +#endif +#endif /* MIPS_INTRNG */ static void nexus_hinted_child(device_t bus, const char *dname, int dunit) @@ -493,4 +602,5 @@ } } -DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); +EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0, + BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);