From: kettenis Date: Fri, 5 Aug 2016 20:38:17 +0000 (+0000) Subject: We don't want drivers with numbers in their names. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2b7dae4aff7e4510fa1933a6ae10738f040d62fd;p=openbsd We don't want drivers with numbers in their names. Requested by deraadt@ --- diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC index 28042e808f0..dd03c1911ab 100644 --- a/sys/arch/armv7/conf/GENERIC +++ b/sys/arch/armv7/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.33 2016/08/05 19:00:25 kettenis Exp $ +# $OpenBSD: GENERIC,v 1.34 2016/08/05 20:38:17 kettenis Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -85,7 +85,7 @@ usb* at ehci? sunxi0 at mainbus? # Sunxi on-chip devices -a1xintc* at fdt? # A1x interrupt controller +sxiintc* at fdt? # A1x interrupt controller sxipio* at sunxi? # GPIO pins for leds & PHYs gpio* at sxipio? sxiccmu* at sunxi? # Clock Control Module/Unit diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK index 06b66e1725a..f88d65bc7f9 100644 --- a/sys/arch/armv7/conf/RAMDISK +++ b/sys/arch/armv7/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.30 2016/08/05 19:00:25 kettenis Exp $ +# $OpenBSD: RAMDISK,v 1.31 2016/08/05 20:38:17 kettenis Exp $ machine armv7 arm @@ -84,7 +84,7 @@ usb* at ehci? sunxi0 at mainbus? # Sunxi on-chip devices -a1xintc* at fdt? # A1x interrupt controller +sxiintc* at fdt? # A1x interrupt controller sxipio* at sunxi? # GPIO pins for leds & PHYs gpio* at sxipio? sxiccmu* at sunxi? # Clock Control Module/Unit diff --git a/sys/arch/armv7/sunxi/a1xintc.c b/sys/arch/armv7/sunxi/a1xintc.c deleted file mode 100644 index 3eed1f43924..00000000000 --- a/sys/arch/armv7/sunxi/a1xintc.c +++ /dev/null @@ -1,458 +0,0 @@ -/* $OpenBSD: a1xintc.c,v 1.8 2016/08/05 19:00:25 kettenis Exp $ */ -/* - * Copyright (c) 2007,2009 Dale Rahn - * Copyright (c) 2013 Artturi Alm - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#ifdef DEBUG_INTC -#define DPRINTF(x) do { if (a1xintcdebug) printf x; } while (0) -#define DPRINTFN(n,x) do { if (a1xintcdebug>(n)) printf x; } while (0) -int a1xintcdebug = 10; -char *ipl_strtbl[NIPL] = { - "IPL_NONE", - "IPL_SOFT", - "IPL_SOFTCLOCK", - "IPL_SOFTNET", - "IPL_SOFTTTY", - "IPL_BIO|IPL_USB", - "IPL_NET", - "IPL_TTY", - "IPL_VM", - "IPL_AUDIO", - "IPL_CLOCK", - "IPL_STATCLOCK", - "IPL_SCHED|IPL_HIGH" -}; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define NIRQ 96 -#define NBANKS 3 -#define NIRQPRIOREGS 5 - -/* registers */ -#define INTC_VECTOR_REG 0x00 -#define INTC_BASE_ADR_REG 0x04 -#define INTC_PROTECTION_REG 0x08 -#define INTC_NMI_CTRL_REG 0x0c - -#define INTC_IRQ_PENDING_REG0 0x10 -#define INTC_IRQ_PENDING_REG1 0x14 -#define INTC_IRQ_PENDING_REG2 0x18 - -#define INTC_SELECT_REG0 0x30 -#define INTC_SELECT_REG1 0x34 -#define INTC_SELECT_REG2 0x38 - -#define INTC_ENABLE_REG0 0x40 -#define INTC_ENABLE_REG1 0x44 -#define INTC_ENABLE_REG2 0x48 - -#define INTC_MASK_REG0 0x50 -#define INTC_MASK_REG1 0x54 -#define INTC_MASK_REG2 0x58 - -#define INTC_RESP_REG0 0x60 -#define INTC_RESP_REG1 0x64 -#define INTC_RESP_REG2 0x68 - -#define INTC_PRIO_REG0 0x80 -#define INTC_PRIO_REG1 0x84 -#define INTC_PRIO_REG2 0x88 -#define INTC_PRIO_REG3 0x8c -#define INTC_PRIO_REG4 0x90 - -#define INTC_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4)) -#define INTC_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4)) -#define INTC_SELECT_REG(_b) (0x30 + ((_b) * 4)) -#define INTC_ENABLE_REG(_b) (0x40 + ((_b) * 4)) -#define INTC_MASK_REG(_b) (0x50 + ((_b) * 4)) -#define INTC_RESP_REG(_b) (0x60 + ((_b) * 4)) -#define INTC_PRIO_REG(_b) (0x80 + ((_b) * 4)) - -#define IRQ2REG32(i) (((i) >> 5) & 0x3) -#define IRQ2BIT32(i) ((i) & 0x1f) - -#define IRQ2REG16(i) (((i) >> 4) & 0x5) -#define IRQ2BIT16(i) (((i) & 0x0f) * 2) - -#define INTC_IRQ_HIPRIO 0x3 -#define INTC_IRQ_ENABLED 0x2 -#define INTC_IRQ_DISABLED 0x1 -#define INTC_IRQ_LOWPRIO 0x0 -#define INTC_PRIOCLEAR(i) (~(INTC_IRQ_HIPRIO << IRQ2BIT16((i)))) -#define INTC_PRIOENABLE(i) (INTC_IRQ_ENABLED << IRQ2BIT16((i))) -#define INTC_PRIOHI(i) (INTC_IRQ_HIPRIO << IRQ2BIT16((i))) - - -struct intrhand { - TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */ - int (*ih_func)(void *); /* handler */ - void *ih_arg; /* arg for handler */ - int ih_ipl; /* IPL_* */ - int ih_irq; /* IRQ number */ - struct evcount ih_count; - char *ih_name; -}; - -struct intrq { - TAILQ_HEAD(, intrhand) iq_list; /* handler list */ - int iq_irq; /* IRQ to mask while handling */ - int iq_levels; /* IPL_*'s this IRQ has */ - int iq_ist; /* share type */ -}; - -volatile int a1xsoftint_pending; - -struct intrq a1xintc_handler[NIRQ]; -u_int32_t a1xintc_smask[NIPL]; -u_int32_t a1xintc_imask[NBANKS][NIPL]; -struct interrupt_controller a1xintc_ic; - -bus_space_tag_t a1xintc_iot; -bus_space_handle_t a1xintc_ioh; -int a1xintc_nirq; - -int a1xintc_match(struct device *, void *, void *); -void a1xintc_attach(struct device *, struct device *, void *); -int a1xintc_spllower(int); -int a1xintc_splraise(int); -void a1xintc_setipl(int); -void a1xintc_calc_masks(void); -void *a1xintc_intr_establish_fdt(void *, int *, int, int (*)(void *), - void *, char *); - -struct cfattach a1xintc_ca = { - sizeof (struct device), a1xintc_match, a1xintc_attach -}; - -struct cfdriver a1xintc_cd = { - NULL, "a1xintc", DV_DULL -}; - -int a1xintc_attached = 0; - -int -a1xintc_match(struct device *parent, void *match, void *aux) -{ - struct fdt_attach_args *faa = aux; - - return OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-ic"); -} - -void -a1xintc_attach(struct device *parent, struct device *self, void *aux) -{ - struct fdt_attach_args *faa = aux; - int i, j; - - a1xintc_iot = faa->fa_iot; - if (bus_space_map(a1xintc_iot, faa->fa_reg[0].addr, - faa->fa_reg[0].size, 0, &a1xintc_ioh)) - panic("a1xintc_attach: bus_space_map failed!"); - - /* disable/mask/clear all interrupts */ - for (i = 0; i < NBANKS; i++) { - bus_space_write_4(a1xintc_iot, a1xintc_ioh, INTC_ENABLE_REG(i), 0); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, INTC_MASK_REG(i), 0); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, INTC_IRQ_PENDING_REG(i), - 0xffffffff); - for (j = 0; j < NIPL; j++) - a1xintc_imask[i][j] = 0; - } - - /* XXX */ - bus_space_write_4(a1xintc_iot, a1xintc_ioh, INTC_PROTECTION_REG, 1); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, INTC_NMI_CTRL_REG, 0); - - for (i = 0; i < NIRQ; i++) - TAILQ_INIT(&a1xintc_handler[i].iq_list); - - a1xintc_calc_masks(); - - arm_init_smask(); - a1xintc_attached = 1; - - /* insert self as interrupt handler */ - arm_set_intr_handler(a1xintc_splraise, a1xintc_spllower, a1xintc_splx, - a1xintc_setipl, - a1xintc_intr_establish, a1xintc_intr_disestablish, a1xintc_intr_string, - a1xintc_irq_handler); - a1xintc_setipl(IPL_HIGH); /* XXX ??? */ - enable_interrupts(PSR_I); - printf("\n"); - - a1xintc_ic.ic_node = faa->fa_node; - a1xintc_ic.ic_establish = a1xintc_intr_establish_fdt; - arm_intr_register_fdt(&a1xintc_ic); -} - -void -a1xintc_calc_masks(void) -{ - struct cpu_info *ci = curcpu(); - int irq; - struct intrhand *ih; - int i; - - for (irq = 0; irq < NIRQ; irq++) { - int max = IPL_NONE; - int min = IPL_HIGH; - TAILQ_FOREACH(ih, &a1xintc_handler[irq].iq_list, ih_list) { - if (ih->ih_ipl > max) - max = ih->ih_ipl; - if (ih->ih_ipl < min) - min = ih->ih_ipl; - } - - a1xintc_handler[irq].iq_irq = max; - - if (max == IPL_NONE) - min = IPL_NONE; - -#ifdef DEBUG_INTC - if (min != IPL_NONE) { - printf("irq %d to block at %d %d reg %d bit %d\n", - irq, max, min, IRQ2REG32(irq), - IRQ2BIT32(irq)); - } -#endif - /* Enable interrupts at lower levels, clear -> enable */ - for (i = 0; i < min; i++) - a1xintc_imask[IRQ2REG32(irq)][i] &= - ~(1 << IRQ2BIT32(irq)); - for (; i < NIPL; i++) - a1xintc_imask[IRQ2REG32(irq)][i] |= - (1 << IRQ2BIT32(irq)); - /* XXX - set enable/disable, priority */ - } - - a1xintc_setipl(ci->ci_cpl); -} - -void -a1xintc_splx(int new) -{ - struct cpu_info *ci = curcpu(); - a1xintc_setipl(new); - - if (ci->ci_ipending & arm_smask[ci->ci_cpl]) - arm_do_pending_intr(ci->ci_cpl); -} - -int -a1xintc_spllower(int new) -{ - struct cpu_info *ci = curcpu(); - int old = ci->ci_cpl; - a1xintc_splx(new); - return (old); -} - -int -a1xintc_splraise(int new) -{ - struct cpu_info *ci = curcpu(); - int old; - old = ci->ci_cpl; - - /* - * setipl must always be called because there is a race window - * where the variable is updated before the mask is set - * an interrupt occurs in that window without the mask always - * being set, the hardware might not get updated on the next - * splraise completely messing up spl protection. - */ - if (old > new) - new = old; - - a1xintc_setipl(new); - - return (old); -} - -void -a1xintc_setipl(int new) -{ - struct cpu_info *ci = curcpu(); - int i, psw; -#if 1 - /* - * XXX not needed, because all interrupts are disabled - * by default, so touching maskregs has no effect, i hope. - */ - if (a1xintc_attached == 0) { - ci->ci_cpl = new; - return; - } -#endif - psw = disable_interrupts(PSR_I); - ci->ci_cpl = new; - for (i = 0; i < NBANKS; i++) - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_MASK_REG(i), a1xintc_imask[i][new]); - restore_interrupts(psw); -} - -void -a1xintc_irq_handler(void *frame) -{ - struct intrhand *ih; - void *arg; - uint32_t pr; - int irq, prio, s; - - irq = bus_space_read_4(a1xintc_iot, a1xintc_ioh, INTC_VECTOR_REG) >> 2; - if (irq == 0) - return; - - prio = a1xintc_handler[irq].iq_irq; - s = a1xintc_splraise(prio); - splassert(prio); - - pr = bus_space_read_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq))); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq)), - pr & ~(1 << IRQ2BIT32(irq))); - - /* clear pending */ - pr = bus_space_read_4(a1xintc_iot, a1xintc_ioh, - INTC_IRQ_PENDING_REG(IRQ2REG32(irq))); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_IRQ_PENDING_REG(IRQ2REG32(irq)), - pr | (1 << IRQ2BIT32(irq))); - - pr = bus_space_read_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq))); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq)), - pr | (1 << IRQ2BIT32(irq))); - - TAILQ_FOREACH(ih, &a1xintc_handler[irq].iq_list, ih_list) { - if (ih->ih_arg != 0) - arg = ih->ih_arg; - else - arg = frame; - - if (ih->ih_func(arg)) - ih->ih_count.ec_count++; - } - a1xintc_splx(s); -} - -void * -a1xintc_intr_establish(int irq, int level, int (*func)(void *), - void *arg, char *name) -{ - int psw; - struct intrhand *ih; - uint32_t er; - - if (irq <= 0 || irq >= NIRQ) - panic("intr_establish: bogus irq %d %s\n", irq, name); - - DPRINTF(("intr_establish: irq %d level %d [%s]\n", irq, level, - name != NULL ? name : "NULL")); - - psw = disable_interrupts(PSR_I); - - /* no point in sleeping unless someone can free memory. */ - ih = (struct intrhand *)malloc (sizeof *ih, M_DEVBUF, - cold ? M_NOWAIT : M_WAITOK); - if (ih == NULL) - panic("intr_establish: can't malloc handler info\n"); - ih->ih_func = func; - ih->ih_arg = arg; - ih->ih_ipl = level; - ih->ih_irq = irq; - ih->ih_name = name; - - TAILQ_INSERT_TAIL(&a1xintc_handler[irq].iq_list, ih, ih_list); - - if (name != NULL) - evcount_attach(&ih->ih_count, name, &ih->ih_irq); - - er = bus_space_read_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq))); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq)), - er | (1 << IRQ2BIT32(irq))); - - a1xintc_calc_masks(); - - restore_interrupts(psw); - return (ih); -} - -void * -a1xintc_intr_establish_fdt(void *cookie, int *cell, int level, - int (*func)(void *), void *arg, char *name) -{ - return a1xintc_intr_establish(cell[0], level, func, arg, name); -} - -void -a1xintc_intr_disestablish(void *cookie) -{ - struct intrhand *ih = cookie; - int irq = ih->ih_irq; - int psw; - uint32_t er; - - psw = disable_interrupts(PSR_I); - - TAILQ_REMOVE(&a1xintc_handler[irq].iq_list, ih, ih_list); - - if (ih->ih_name != NULL) - evcount_detach(&ih->ih_count); - - free(ih, M_DEVBUF, 0); - - er = bus_space_read_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq))); - bus_space_write_4(a1xintc_iot, a1xintc_ioh, - INTC_ENABLE_REG(IRQ2REG32(irq)), - er & ~(1 << IRQ2BIT32(irq))); - - a1xintc_calc_masks(); - - restore_interrupts(psw); -} - -const char * -a1xintc_intr_string(void *cookie) -{ - return "asd?"; -} diff --git a/sys/arch/armv7/sunxi/a1xintc.h b/sys/arch/armv7/sunxi/a1xintc.h deleted file mode 100644 index 2d8c1d22fb1..00000000000 --- a/sys/arch/armv7/sunxi/a1xintc.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $OpenBSD: a1xintc.h,v 1.3 2015/05/19 06:09:35 jsg Exp $ */ -/* - * Copyright (c) 2007,2009 Dale Rahn - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _A1XINTC_H_ -#define _A1XINTC_H_ - -#ifndef _LOCORE - -#include -#include -#include -#include - -extern volatile int current_spl_level; -extern volatile int softint_pending; -void a1xintc_do_pending(void); - -#define SI_TO_IRQBIT(si) (1U<<(si)) -void a1xintc_setipl(int); -void a1xintc_splx(int); -int a1xintc_splraise(int); -int a1xintc_spllower(int); -void a1xintc_setsoftintr(int); - -void a1xintc_irq_handler(void *); -void *a1xintc_intr_establish(int, int, int (*)(void *), void *, char *); -void a1xintc_intr_disestablish(void *); -const char *a1xintc_intr_string(void *); - -#endif /* ! _LOCORE */ - -#endif /* _A1XINTC_H_ */ - diff --git a/sys/arch/armv7/sunxi/files.sunxi b/sys/arch/armv7/sunxi/files.sunxi index 59d75620db2..d18eec743f3 100644 --- a/sys/arch/armv7/sunxi/files.sunxi +++ b/sys/arch/armv7/sunxi/files.sunxi @@ -1,4 +1,4 @@ -# $OpenBSD: files.sunxi,v 1.7 2016/08/05 19:00:25 kettenis Exp $ +# $OpenBSD: files.sunxi,v 1.8 2016/08/05 20:38:17 kettenis Exp $ define sunxi {} device sunxi: sunxi @@ -16,9 +16,9 @@ device sxipio {}: gpiobus attach sxipio at sunxi file arch/armv7/sunxi/sxipio.c sxipio -device a1xintc -attach a1xintc at fdt -file arch/armv7/sunxi/a1xintc.c a1xintc +device sxiintc +attach sxiintc at fdt +file arch/armv7/sunxi/sxiintc.c sxiintc device sxitimer attach sxitimer at sunxi diff --git a/sys/arch/armv7/sunxi/sxiintc.c b/sys/arch/armv7/sunxi/sxiintc.c new file mode 100644 index 00000000000..452361ecd76 --- /dev/null +++ b/sys/arch/armv7/sunxi/sxiintc.c @@ -0,0 +1,458 @@ +/* $OpenBSD: sxiintc.c,v 1.1 2016/08/05 20:38:17 kettenis Exp $ */ +/* + * Copyright (c) 2007,2009 Dale Rahn + * Copyright (c) 2013 Artturi Alm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef DEBUG_INTC +#define DPRINTF(x) do { if (sxiintcdebug) printf x; } while (0) +#define DPRINTFN(n,x) do { if (sxiintcdebug>(n)) printf x; } while (0) +int sxiintcdebug = 10; +char *ipl_strtbl[NIPL] = { + "IPL_NONE", + "IPL_SOFT", + "IPL_SOFTCLOCK", + "IPL_SOFTNET", + "IPL_SOFTTTY", + "IPL_BIO|IPL_USB", + "IPL_NET", + "IPL_TTY", + "IPL_VM", + "IPL_AUDIO", + "IPL_CLOCK", + "IPL_STATCLOCK", + "IPL_SCHED|IPL_HIGH" +}; +#else +#define DPRINTF(x) +#define DPRINTFN(n,x) +#endif + +#define NIRQ 96 +#define NBANKS 3 +#define NIRQPRIOREGS 5 + +/* registers */ +#define INTC_VECTOR_REG 0x00 +#define INTC_BASE_ADR_REG 0x04 +#define INTC_PROTECTION_REG 0x08 +#define INTC_NMI_CTRL_REG 0x0c + +#define INTC_IRQ_PENDING_REG0 0x10 +#define INTC_IRQ_PENDING_REG1 0x14 +#define INTC_IRQ_PENDING_REG2 0x18 + +#define INTC_SELECT_REG0 0x30 +#define INTC_SELECT_REG1 0x34 +#define INTC_SELECT_REG2 0x38 + +#define INTC_ENABLE_REG0 0x40 +#define INTC_ENABLE_REG1 0x44 +#define INTC_ENABLE_REG2 0x48 + +#define INTC_MASK_REG0 0x50 +#define INTC_MASK_REG1 0x54 +#define INTC_MASK_REG2 0x58 + +#define INTC_RESP_REG0 0x60 +#define INTC_RESP_REG1 0x64 +#define INTC_RESP_REG2 0x68 + +#define INTC_PRIO_REG0 0x80 +#define INTC_PRIO_REG1 0x84 +#define INTC_PRIO_REG2 0x88 +#define INTC_PRIO_REG3 0x8c +#define INTC_PRIO_REG4 0x90 + +#define INTC_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4)) +#define INTC_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4)) +#define INTC_SELECT_REG(_b) (0x30 + ((_b) * 4)) +#define INTC_ENABLE_REG(_b) (0x40 + ((_b) * 4)) +#define INTC_MASK_REG(_b) (0x50 + ((_b) * 4)) +#define INTC_RESP_REG(_b) (0x60 + ((_b) * 4)) +#define INTC_PRIO_REG(_b) (0x80 + ((_b) * 4)) + +#define IRQ2REG32(i) (((i) >> 5) & 0x3) +#define IRQ2BIT32(i) ((i) & 0x1f) + +#define IRQ2REG16(i) (((i) >> 4) & 0x5) +#define IRQ2BIT16(i) (((i) & 0x0f) * 2) + +#define INTC_IRQ_HIPRIO 0x3 +#define INTC_IRQ_ENABLED 0x2 +#define INTC_IRQ_DISABLED 0x1 +#define INTC_IRQ_LOWPRIO 0x0 +#define INTC_PRIOCLEAR(i) (~(INTC_IRQ_HIPRIO << IRQ2BIT16((i)))) +#define INTC_PRIOENABLE(i) (INTC_IRQ_ENABLED << IRQ2BIT16((i))) +#define INTC_PRIOHI(i) (INTC_IRQ_HIPRIO << IRQ2BIT16((i))) + + +struct intrhand { + TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */ + int (*ih_func)(void *); /* handler */ + void *ih_arg; /* arg for handler */ + int ih_ipl; /* IPL_* */ + int ih_irq; /* IRQ number */ + struct evcount ih_count; + char *ih_name; +}; + +struct intrq { + TAILQ_HEAD(, intrhand) iq_list; /* handler list */ + int iq_irq; /* IRQ to mask while handling */ + int iq_levels; /* IPL_*'s this IRQ has */ + int iq_ist; /* share type */ +}; + +volatile int a1xsoftint_pending; + +struct intrq sxiintc_handler[NIRQ]; +u_int32_t sxiintc_smask[NIPL]; +u_int32_t sxiintc_imask[NBANKS][NIPL]; +struct interrupt_controller sxiintc_ic; + +bus_space_tag_t sxiintc_iot; +bus_space_handle_t sxiintc_ioh; +int sxiintc_nirq; + +int sxiintc_match(struct device *, void *, void *); +void sxiintc_attach(struct device *, struct device *, void *); +int sxiintc_spllower(int); +int sxiintc_splraise(int); +void sxiintc_setipl(int); +void sxiintc_calc_masks(void); +void *sxiintc_intr_establish_fdt(void *, int *, int, int (*)(void *), + void *, char *); + +struct cfattach sxiintc_ca = { + sizeof (struct device), sxiintc_match, sxiintc_attach +}; + +struct cfdriver sxiintc_cd = { + NULL, "sxiintc", DV_DULL +}; + +int sxiintc_attached = 0; + +int +sxiintc_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-ic"); +} + +void +sxiintc_attach(struct device *parent, struct device *self, void *aux) +{ + struct fdt_attach_args *faa = aux; + int i, j; + + sxiintc_iot = faa->fa_iot; + if (bus_space_map(sxiintc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sxiintc_ioh)) + panic("sxiintc_attach: bus_space_map failed!"); + + /* disable/mask/clear all interrupts */ + for (i = 0; i < NBANKS; i++) { + bus_space_write_4(sxiintc_iot, sxiintc_ioh, INTC_ENABLE_REG(i), 0); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, INTC_MASK_REG(i), 0); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, INTC_IRQ_PENDING_REG(i), + 0xffffffff); + for (j = 0; j < NIPL; j++) + sxiintc_imask[i][j] = 0; + } + + /* XXX */ + bus_space_write_4(sxiintc_iot, sxiintc_ioh, INTC_PROTECTION_REG, 1); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, INTC_NMI_CTRL_REG, 0); + + for (i = 0; i < NIRQ; i++) + TAILQ_INIT(&sxiintc_handler[i].iq_list); + + sxiintc_calc_masks(); + + arm_init_smask(); + sxiintc_attached = 1; + + /* insert self as interrupt handler */ + arm_set_intr_handler(sxiintc_splraise, sxiintc_spllower, sxiintc_splx, + sxiintc_setipl, + sxiintc_intr_establish, sxiintc_intr_disestablish, sxiintc_intr_string, + sxiintc_irq_handler); + sxiintc_setipl(IPL_HIGH); /* XXX ??? */ + enable_interrupts(PSR_I); + printf("\n"); + + sxiintc_ic.ic_node = faa->fa_node; + sxiintc_ic.ic_establish = sxiintc_intr_establish_fdt; + arm_intr_register_fdt(&sxiintc_ic); +} + +void +sxiintc_calc_masks(void) +{ + struct cpu_info *ci = curcpu(); + int irq; + struct intrhand *ih; + int i; + + for (irq = 0; irq < NIRQ; irq++) { + int max = IPL_NONE; + int min = IPL_HIGH; + TAILQ_FOREACH(ih, &sxiintc_handler[irq].iq_list, ih_list) { + if (ih->ih_ipl > max) + max = ih->ih_ipl; + if (ih->ih_ipl < min) + min = ih->ih_ipl; + } + + sxiintc_handler[irq].iq_irq = max; + + if (max == IPL_NONE) + min = IPL_NONE; + +#ifdef DEBUG_INTC + if (min != IPL_NONE) { + printf("irq %d to block at %d %d reg %d bit %d\n", + irq, max, min, IRQ2REG32(irq), + IRQ2BIT32(irq)); + } +#endif + /* Enable interrupts at lower levels, clear -> enable */ + for (i = 0; i < min; i++) + sxiintc_imask[IRQ2REG32(irq)][i] &= + ~(1 << IRQ2BIT32(irq)); + for (; i < NIPL; i++) + sxiintc_imask[IRQ2REG32(irq)][i] |= + (1 << IRQ2BIT32(irq)); + /* XXX - set enable/disable, priority */ + } + + sxiintc_setipl(ci->ci_cpl); +} + +void +sxiintc_splx(int new) +{ + struct cpu_info *ci = curcpu(); + sxiintc_setipl(new); + + if (ci->ci_ipending & arm_smask[ci->ci_cpl]) + arm_do_pending_intr(ci->ci_cpl); +} + +int +sxiintc_spllower(int new) +{ + struct cpu_info *ci = curcpu(); + int old = ci->ci_cpl; + sxiintc_splx(new); + return (old); +} + +int +sxiintc_splraise(int new) +{ + struct cpu_info *ci = curcpu(); + int old; + old = ci->ci_cpl; + + /* + * setipl must always be called because there is a race window + * where the variable is updated before the mask is set + * an interrupt occurs in that window without the mask always + * being set, the hardware might not get updated on the next + * splraise completely messing up spl protection. + */ + if (old > new) + new = old; + + sxiintc_setipl(new); + + return (old); +} + +void +sxiintc_setipl(int new) +{ + struct cpu_info *ci = curcpu(); + int i, psw; +#if 1 + /* + * XXX not needed, because all interrupts are disabled + * by default, so touching maskregs has no effect, i hope. + */ + if (sxiintc_attached == 0) { + ci->ci_cpl = new; + return; + } +#endif + psw = disable_interrupts(PSR_I); + ci->ci_cpl = new; + for (i = 0; i < NBANKS; i++) + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_MASK_REG(i), sxiintc_imask[i][new]); + restore_interrupts(psw); +} + +void +sxiintc_irq_handler(void *frame) +{ + struct intrhand *ih; + void *arg; + uint32_t pr; + int irq, prio, s; + + irq = bus_space_read_4(sxiintc_iot, sxiintc_ioh, INTC_VECTOR_REG) >> 2; + if (irq == 0) + return; + + prio = sxiintc_handler[irq].iq_irq; + s = sxiintc_splraise(prio); + splassert(prio); + + pr = bus_space_read_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq))); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq)), + pr & ~(1 << IRQ2BIT32(irq))); + + /* clear pending */ + pr = bus_space_read_4(sxiintc_iot, sxiintc_ioh, + INTC_IRQ_PENDING_REG(IRQ2REG32(irq))); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_IRQ_PENDING_REG(IRQ2REG32(irq)), + pr | (1 << IRQ2BIT32(irq))); + + pr = bus_space_read_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq))); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq)), + pr | (1 << IRQ2BIT32(irq))); + + TAILQ_FOREACH(ih, &sxiintc_handler[irq].iq_list, ih_list) { + if (ih->ih_arg != 0) + arg = ih->ih_arg; + else + arg = frame; + + if (ih->ih_func(arg)) + ih->ih_count.ec_count++; + } + sxiintc_splx(s); +} + +void * +sxiintc_intr_establish(int irq, int level, int (*func)(void *), + void *arg, char *name) +{ + int psw; + struct intrhand *ih; + uint32_t er; + + if (irq <= 0 || irq >= NIRQ) + panic("intr_establish: bogus irq %d %s\n", irq, name); + + DPRINTF(("intr_establish: irq %d level %d [%s]\n", irq, level, + name != NULL ? name : "NULL")); + + psw = disable_interrupts(PSR_I); + + /* no point in sleeping unless someone can free memory. */ + ih = (struct intrhand *)malloc (sizeof *ih, M_DEVBUF, + cold ? M_NOWAIT : M_WAITOK); + if (ih == NULL) + panic("intr_establish: can't malloc handler info\n"); + ih->ih_func = func; + ih->ih_arg = arg; + ih->ih_ipl = level; + ih->ih_irq = irq; + ih->ih_name = name; + + TAILQ_INSERT_TAIL(&sxiintc_handler[irq].iq_list, ih, ih_list); + + if (name != NULL) + evcount_attach(&ih->ih_count, name, &ih->ih_irq); + + er = bus_space_read_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq))); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq)), + er | (1 << IRQ2BIT32(irq))); + + sxiintc_calc_masks(); + + restore_interrupts(psw); + return (ih); +} + +void * +sxiintc_intr_establish_fdt(void *cookie, int *cell, int level, + int (*func)(void *), void *arg, char *name) +{ + return sxiintc_intr_establish(cell[0], level, func, arg, name); +} + +void +sxiintc_intr_disestablish(void *cookie) +{ + struct intrhand *ih = cookie; + int irq = ih->ih_irq; + int psw; + uint32_t er; + + psw = disable_interrupts(PSR_I); + + TAILQ_REMOVE(&sxiintc_handler[irq].iq_list, ih, ih_list); + + if (ih->ih_name != NULL) + evcount_detach(&ih->ih_count); + + free(ih, M_DEVBUF, 0); + + er = bus_space_read_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq))); + bus_space_write_4(sxiintc_iot, sxiintc_ioh, + INTC_ENABLE_REG(IRQ2REG32(irq)), + er & ~(1 << IRQ2BIT32(irq))); + + sxiintc_calc_masks(); + + restore_interrupts(psw); +} + +const char * +sxiintc_intr_string(void *cookie) +{ + return "asd?"; +} diff --git a/sys/arch/armv7/sunxi/sxiintc.h b/sys/arch/armv7/sunxi/sxiintc.h new file mode 100644 index 00000000000..849594d02f8 --- /dev/null +++ b/sys/arch/armv7/sunxi/sxiintc.h @@ -0,0 +1,47 @@ +/* $OpenBSD: sxiintc.h,v 1.1 2016/08/05 20:38:17 kettenis Exp $ */ +/* + * Copyright (c) 2007,2009 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SXIINTC_H_ +#define _SXIINTC_H_ + +#ifndef _LOCORE + +#include +#include +#include +#include + +extern volatile int current_spl_level; +extern volatile int softint_pending; +void sxiintc_do_pending(void); + +#define SI_TO_IRQBIT(si) (1U<<(si)) +void sxiintc_setipl(int); +void sxiintc_splx(int); +int sxiintc_splraise(int); +int sxiintc_spllower(int); +void sxiintc_setsoftintr(int); + +void sxiintc_irq_handler(void *); +void *sxiintc_intr_establish(int, int, int (*)(void *), void *, char *); +void sxiintc_intr_disestablish(void *); +const char *sxiintc_intr_string(void *); + +#endif /* ! _LOCORE */ + +#endif /* _SXIINTC_H_ */ +