We don't want drivers with numbers in their names.
authorkettenis <kettenis@openbsd.org>
Fri, 5 Aug 2016 20:38:17 +0000 (20:38 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 5 Aug 2016 20:38:17 +0000 (20:38 +0000)
Requested by deraadt@

sys/arch/armv7/conf/GENERIC
sys/arch/armv7/conf/RAMDISK
sys/arch/armv7/sunxi/a1xintc.c [deleted file]
sys/arch/armv7/sunxi/a1xintc.h [deleted file]
sys/arch/armv7/sunxi/files.sunxi
sys/arch/armv7/sunxi/sxiintc.c [new file with mode: 0644]
sys/arch/armv7/sunxi/sxiintc.h [new file with mode: 0644]

index 28042e8..dd03c19 100644 (file)
@@ -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
index 06b66e1..f88d65b 100644 (file)
@@ -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 (file)
index 3eed1f4..0000000
+++ /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 <drahn@openbsd.org>
- * 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 <sys/param.h>
-#include <sys/systm.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#include <sys/device.h>
-#include <sys/evcount.h>
-
-#include <machine/bus.h>
-#include <machine/fdt.h>
-
-#include <armv7/armv7/armv7var.h>
-#include <armv7/sunxi/sunxireg.h>
-#include <armv7/sunxi/a1xintc.h>
-
-#include <dev/ofw/openfirm.h>
-#include <dev/ofw/fdt.h>
-
-#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 (file)
index 2d8c1d2..0000000
+++ /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 <drahn@openbsd.org>
- *
- * 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 <arm/armreg.h>
-#include <arm/cpufunc.h>
-#include <machine/intr.h>
-#include <arm/softintr.h>
-
-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_ */
-
index 59d7562..d18eec7 100644 (file)
@@ -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 (file)
index 0000000..452361e
--- /dev/null
@@ -0,0 +1,458 @@
+/*     $OpenBSD: sxiintc.c,v 1.1 2016/08/05 20:38:17 kettenis Exp $    */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/sunxi/sunxireg.h>
+#include <armv7/sunxi/sxiintc.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#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 (file)
index 0000000..849594d
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $OpenBSD: sxiintc.h,v 1.1 2016/08/05 20:38:17 kettenis Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * 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 <arm/armreg.h>
+#include <arm/cpufunc.h>
+#include <machine/intr.h>
+#include <arm/softintr.h>
+
+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_ */
+