summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/loongson/conf/files.loongson6
-rw-r--r--sys/arch/loongson/dev/bonito.c290
-rw-r--r--sys/arch/loongson/dev/bonito_irq.h92
-rw-r--r--sys/arch/loongson/dev/bonitoreg.h8
-rw-r--r--sys/arch/loongson/dev/bonitovar.h5
-rw-r--r--sys/arch/loongson/dev/lemote_irq.h72
-rw-r--r--sys/arch/loongson/include/autoconf.h11
-rw-r--r--sys/arch/loongson/loongson/gdium_machdep.c82
-rw-r--r--sys/arch/loongson/loongson/machdep.c64
-rw-r--r--sys/arch/loongson/loongson/pmon.c4
-rw-r--r--sys/arch/loongson/loongson/yeeloong_machdep.c84
-rw-r--r--sys/arch/mips64/include/archtype.h5
12 files changed, 507 insertions, 216 deletions
diff --git a/sys/arch/loongson/conf/files.loongson b/sys/arch/loongson/conf/files.loongson
index 52b3c00347d..f7d56de48bc 100644
--- a/sys/arch/loongson/conf/files.loongson
+++ b/sys/arch/loongson/conf/files.loongson
@@ -1,4 +1,4 @@
-# $OpenBSD: files.loongson,v 1.1 2009/12/25 21:09:57 miod Exp $
+# $OpenBSD: files.loongson,v 1.2 2010/02/05 20:51:20 miod Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -17,6 +17,7 @@ file arch/loongson/loongson/bus_dma.c
file arch/loongson/loongson/bus_space.c
file arch/loongson/loongson/conf.c
file arch/loongson/loongson/disksubr.c disk
+file arch/loongson/loongson/gdium_machdep.c
file arch/loongson/loongson/loongson2_machdep.c
file arch/loongson/loongson/machdep.c
file arch/loongson/loongson/mutex.c
@@ -24,6 +25,7 @@ file arch/loongson/loongson/pciide_machdep.c pciide
file arch/loongson/loongson/pmon.c
file arch/loongson/loongson/pmon32.S
file arch/loongson/loongson/wscons_machdep.c wsdisplay
+file arch/loongson/loongson/yeeloong_machdep.c
include "dev/ata/files.ata"
include "dev/atapiscsi/files.atapiscsi"
@@ -65,7 +67,7 @@ attach glxpcib at pci
file arch/loongson/dev/glxpcib.c glxpcib
file arch/loongson/dev/pcib.c glxpcib
-# RTC
+# Lemote Yeeloong RTC
device mcclock
attach mcclock at isa with mcclock_isa
file arch/loongson/dev/mcclock.c mcclock
diff --git a/sys/arch/loongson/dev/bonito.c b/sys/arch/loongson/dev/bonito.c
index 78c42b997f3..ba2c0348338 100644
--- a/sys/arch/loongson/dev/bonito.c
+++ b/sys/arch/loongson/dev/bonito.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonito.c,v 1.5 2010/02/05 20:47:15 miod Exp $ */
+/* $OpenBSD: bonito.c,v 1.6 2010/02/05 20:51:22 miod Exp $ */
/* $NetBSD: bonito_mainbus.c,v 1.11 2008/04/28 20:23:10 martin Exp $ */
/* $NetBSD: bonito_pci.c,v 1.5 2008/04/28 20:23:28 martin Exp $ */
@@ -57,6 +57,8 @@
#include <sys/extent.h>
#include <sys/malloc.h>
+#include <mips64/archtype.h>
+
#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/intr.h>
@@ -71,8 +73,8 @@
#include <loongson/dev/bonitoreg.h>
#include <loongson/dev/bonitovar.h>
+#include <loongson/dev/bonito_irq.h>
#include <loongson/dev/glxvar.h>
-#include <loongson/dev/lemote_irq.h>
int bonito_match(struct device *, void *, void *);
void bonito_attach(struct device *, struct device *, void *);
@@ -92,10 +94,7 @@ bus_addr_t bonito_pa_to_device(paddr_t);
paddr_t bonito_device_to_pa(bus_addr_t);
void bonito_intr_makemasks(void);
-void bonito_splx(int);
uint32_t bonito_intr(uint32_t, struct trap_frame *);
-uint32_t bonito_isa_intr(uint32_t, struct trap_frame *);
-void bonito_setintrmask(int);
void bonito_attach_hook(struct device *, struct device *,
struct pcibus_attach_args *);
@@ -119,25 +118,19 @@ uint bonito_get_isa_isr(void);
void bonito_set_isa_imr(uint);
void bonito_isa_specific_eoi(int);
-/*
- * Bonito interrupt handling declarations: on the Yeelong, we have 14
- * interrupts on Bonito, and 16 (well, 15) ISA interrupts with the usual
- * 8259 pair. Bonito and ISA interrupts happen on two different levels.
- *
- * For simplicity we allocate 16 vectors for direct interrupts, and 16
- * vectors for ISA interrupts as well.
- */
-
-#define BONITO_NINTS (16 + 16)
-struct intrhand *bonito_intrhand[BONITO_NINTS];
+uint32_t bonito_isa_intr(uint32_t, struct trap_frame *);
-#define BONITO_ISA_IRQ(i) ((i) + 16)
-#define BONITO_DIRECT_IRQ(i) (i)
-#define BONITO_IRQ_IS_ISA(i) ((i) >= 16)
+void bonito_splx(int);
+void bonito_setintrmask(int);
-#define INTPRI_BONITO (INTPRI_CLOCK + 1)
-#define INTPRI_ISA (INTPRI_BONITO + 1)
+void bonito_isa_splx(int);
+void bonito_isa_setintrmask(int);
+/*
+ * Bonito interrupt handling declarations.
+ * See <loongson/dev/bonito_irq.h> for details.
+ */
+struct intrhand *bonito_intrhand[BONITO_NINTS];
uint64_t bonito_intem;
uint64_t bonito_imask[NIPLS];
@@ -220,17 +213,6 @@ bonito_match(struct device *parent, void *vcf, void *aux)
return (0);
}
-const struct bonito_config yeelong_bonito = {
- .bc_adbase = 11,
-
- .bc_gpioIE = YEELONG_INTRMASK_GPIO,
- .bc_intEdge = YEELONG_INTRMASK_PCI_SYSERR | YEELONG_INTRMASK_PCI_PARERR,
- .bc_intSteer = 0,
- .bc_intPol = YEELONG_INTRMASK_DRAM_PARERR |
- YEELONG_INTRMASK_PCI_SYSERR | YEELONG_INTRMASK_PCI_PARERR |
- YEELONG_INTRMASK_INT0 | YEELONG_INTRMASK_INT1
-};
-
void
bonito_attach(struct device *parent, struct device *self, void *aux)
{
@@ -240,12 +222,31 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
const struct bonito_config *bc;
struct extent *ioex, *memex;
uint32_t reg;
+ int real_bonito;
- printf(": memory and PCI-X controller, rev. %d\n",
- PCI_REVISION(REGVAL(BONITO_PCI_REG(PCI_CLASS_REG))));
+ /*
+ * Loongson 2F processors do not use a real Bonito64 chip but
+ * their own derivative, which is no longer 100% compatible.
+ * We need to make sure we never try to access an unimplemented
+ * register...
+ */
+ if (curcpu()->ci_hw.type == MIPS_LOONGSON2 &&
+ (curcpu()->ci_hw.c0prid & 0xff) == 0x2f - 0x2c)
+ real_bonito = 0;
+ else
+ real_bonito = 1;
- bc = &yeelong_bonito;
+ reg = PCI_REVISION(REGVAL(BONITO_PCI_REG(PCI_CLASS_REG)));
+ if (real_bonito) {
+ printf(": BONITO Memory and PCI controller, %s rev %d.%d\n",
+ BONITO_REV_FPGA(reg) ? "FPGA" : "ASIC",
+ BONITO_REV_MAJOR(reg), BONITO_REV_MINOR(reg));
+ } else {
+ printf(": memory and PCI-X controller, rev %d\n",
+ PCI_REVISION(REGVAL(BONITO_PCI_REG(PCI_CLASS_REG))));
+ }
+ bc = sys_config.sys_bc;
sc->sc_bonito = bc;
SLIST_INIT(&sc->sc_hook);
@@ -253,18 +254,26 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
* Setup proper abitration.
*/
- /*
- * according to linux, changing the value of this undocumented
- * register ``avoids deadlock of PCI reading/writing lock operation''.
- */
- REGVAL(BONITO_PCI_REG(0x4c)) = 0xd2000001; /* instead of c2000001 */
+ if (!real_bonito) {
+ if (sys_config.system_type == LOONGSON_YEELOONG) {
+ /*
+ * According to Linux, changing the value of this
+ * undocumented register ``avoids deadlock of PCI
+ * reading/writing lock operation''.
+ * Is this really necessary, and if so, does it
+ * matter on other designs?
+ */
+ REGVAL(BONITO_PCI_REG(0x4c)) = 0xd2000001;
+ /* was c2000001 */
+ }
- /* all pci devices may need to hold the bus */
- reg = REGVAL(LOONGSON_PXARB_CFG);
- reg &= ~LOONGSON_PXARB_RUDE_DEV_MSK;
- reg |= 0xfe << LOONGSON_PXARB_RUDE_DEV_SHFT;
- REGVAL(LOONGSON_PXARB_CFG) = reg;
- (void)REGVAL(LOONGSON_PXARB_CFG);
+ /* all pci devices may need to hold the bus */
+ reg = REGVAL(LOONGSON_PXARB_CFG);
+ reg &= ~LOONGSON_PXARB_RUDE_DEV_MSK;
+ reg |= 0xfe << LOONGSON_PXARB_RUDE_DEV_SHFT;
+ REGVAL(LOONGSON_PXARB_CFG) = reg;
+ (void)REGVAL(LOONGSON_PXARB_CFG);
+ }
/*
* Setup interrupt handling.
@@ -272,15 +281,29 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
REGVAL(BONITO_GPIOIE) = bc->bc_gpioIE;
REGVAL(BONITO_INTEDGE) = bc->bc_intEdge;
+ if (real_bonito)
+ REGVAL(BONITO_INTSTEER) = bc->bc_intSteer;
REGVAL(BONITO_INTPOL) = bc->bc_intPol;
+
REGVAL(BONITO_INTENCLR) = 0xffffffff;
(void)REGVAL(BONITO_INTENCLR);
- bonito_isaimr = bonito_get_isa_imr();
-
- set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr);
- set_intr(INTPRI_ISA, CR_INT_0, bonito_isa_intr);
- register_splx_handler(bonito_splx);
+ switch (sys_config.system_type) {
+ case LOONGSON_YEELOONG:
+ set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr);
+ set_intr(INTPRI_ISA, CR_INT_0, bonito_isa_intr);
+ bonito_isaimr = bonito_get_isa_imr();
+ register_splx_handler(bonito_isa_splx);
+ break;
+ case LOONGSON_GDIUM:
+ set_intr(INTPRI_BONITO, CR_INT_4, bonito_intr);
+ register_splx_handler(bonito_splx);
+ break;
+ default:
+ /* we should have died way earlier */
+ panic("missing interrupt configuration code for this system");
+ break;
+ }
/*
* Setup PCI resource extents.
@@ -304,6 +327,10 @@ bonito_attach(struct device *parent, struct device *self, void *aux)
(void)extent_free(memex, BONITO_PCIMAP_WINBASE((reg &
BONITO_PCIMAP_PCIMAP_LO2) >> BONITO_PCIMAP_PCIMAP_LO2_SHIFT),
BONITO_PCIMAP_WINSIZE, EX_NOWAIT);
+
+ if (real_bonito) {
+ /* XXX make PCIMAP_HI available if PCIMAP_2 set */
+ }
}
/*
@@ -415,6 +442,11 @@ bonito_intr_disestablish(void *ih)
panic("%s not implemented", __func__);
}
+/*
+ * Update interrupt masks. Two set of routines: one when ISA interrupts
+ * are involved, one without.
+ */
+
void
bonito_splx(int newipl)
{
@@ -430,6 +462,68 @@ bonito_splx(int newipl)
setsoftintr0();
}
+void
+bonito_isa_splx(int newipl)
+{
+ struct cpu_info *ci = curcpu();
+
+ /* Update masks to new ipl. Order highly important! */
+ __asm__ (".set noreorder\n");
+ ci->ci_ipl = newipl;
+ __asm__ ("sync\n\t.set reorder\n");
+ bonito_isa_setintrmask(newipl);
+ /* If we still have softints pending trigger processing. */
+ if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT)
+ setsoftintr0();
+}
+
+void
+bonito_setintrmask(int level)
+{
+ uint64_t active;
+ uint32_t clear, set;
+ uint32_t sr;
+
+ active = bonito_intem & ~bonito_imask[level];
+ /* don't bother masking high bits, there are no isa interrupt sources */
+ clear = bonito_imask[level];
+ set = active;
+
+ sr = disableintr();
+
+ if (clear != 0)
+ REGVAL(BONITO_INTENCLR) = clear;
+ if (set != 0)
+ REGVAL(BONITO_INTENSET) = set;
+ (void)REGVAL(BONITO_INTENSET);
+
+ setsr(sr);
+}
+
+void
+bonito_isa_setintrmask(int level)
+{
+ uint64_t active;
+ uint32_t clear, set;
+ uint32_t sr;
+
+ active = bonito_intem & ~bonito_imask[level];
+ clear = BONITO_DIRECT_MASK(bonito_imask[level]);
+ set = BONITO_DIRECT_MASK(active);
+
+ sr = disableintr();
+
+ if (clear != 0)
+ REGVAL(BONITO_INTENCLR) = clear;
+ if (set != 0)
+ REGVAL(BONITO_INTENSET) = set;
+ (void)REGVAL(BONITO_INTENSET);
+
+ bonito_set_isa_imr(BONITO_ISA_MASK(active));
+
+ setsr(sr);
+}
+
/*
* Recompute interrupt masks.
*/
@@ -493,7 +587,7 @@ bonito_intr(uint32_t hwpend, struct trap_frame *frame)
struct intrhand *ih;
int rc;
- isr = REGVAL(BONITO_INTISR) & YEELONG_INTRMASK_LVL4;
+ isr = REGVAL(BONITO_INTISR) & LOONGSON_INTRMASK_LVL4;
imr = REGVAL(BONITO_INTEN);
isr &= imr;
#ifdef DEBUG
@@ -525,7 +619,7 @@ bonito_intr(uint32_t hwpend, struct trap_frame *frame)
uint64_t tmpisr;
/* Service higher level interrupts first */
- bit = YEELONG_INTR_DRAM_PARERR;
+ bit = LOONGSON_INTR_DRAM_PARERR; /* skip non-pci interrupts */
for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
tmpisr = isr & (bonito_imask[lvl] ^ bonito_imask[lvl - 1]);
if (tmpisr == 0)
@@ -567,8 +661,8 @@ done:
/*
* Process ISA interrupts.
*
- * XXX ISA interrupts only occur on YEELONG_INTR_INT0, but since the other
- * XXX YEELONG_INTR_INT# are unmaskable, bad things will happen if they
+ * XXX ISA interrupts only occur on LOONGSON_INTR_INT0, but since the other
+ * XXX LOONGSON_INTR_INT# are unmaskable, bad things will happen if they
* XXX are triggered...
*/
@@ -604,7 +698,7 @@ bonito_isa_intr(uint32_t hwpend, struct trap_frame *frame)
* If interrupts are spl-masked, mask them and wait for splx()
* to reenable them when necessary.
*/
- if ((mask = isr & (bonito_imask[frame->ipl] >> 16)) != 0) {
+ if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) {
isr &= ~mask;
imr &= ~mask;
}
@@ -617,10 +711,10 @@ bonito_isa_intr(uint32_t hwpend, struct trap_frame *frame)
uint64_t tmpisr;
/* Service higher level interrupts first */
- bit = 15;
+ bit = BONITO_NISA - 1;
for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
- tmpisr = isr &
- ((bonito_imask[lvl] ^ bonito_imask[lvl - 1]) >> 16);
+ tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^
+ bonito_imask[lvl - 1]);
if (tmpisr == 0)
continue;
for (bitno = bit, mask = 1UL << bitno; mask != 0;
@@ -629,7 +723,7 @@ bonito_isa_intr(uint32_t hwpend, struct trap_frame *frame)
continue;
rc = 0;
- for (ih = bonito_intrhand[bitno + 16];
+ for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)];
ih != NULL; ih = ih->ih_next) {
if ((*ih->ih_fun)(ih->ih_arg) != 0) {
rc = 1;
@@ -659,31 +753,6 @@ done:
return hwpend;
}
-
-void
-bonito_setintrmask(int level)
-{
- uint64_t active;
- uint32_t clear, set;
- uint32_t sr;
-
- active = bonito_intem & ~bonito_imask[level];
- clear = bonito_imask[level] & 0xffff;
- set = active & 0xffff;
-
- sr = disableintr();
-
- if (clear != 0)
- REGVAL(BONITO_INTENCLR) = clear;
- if (set != 0)
- REGVAL(BONITO_INTENSET) = set;
- (void)REGVAL(BONITO_INTENSET);
-
- bonito_set_isa_imr(active >> 16);
-
- setsr(sr);
-}
-
/*
* various PCI helpers
*/
@@ -895,7 +964,9 @@ bonito_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data)
int
bonito_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
- int dev, fn, pin;
+ struct bonito_softc *sc = pa->pa_pc->pc_intr_v;
+ const struct bonito_config *bc = sc->sc_bonito;
+ int bus, dev, fn, pin;
*ihp = -1;
@@ -909,44 +980,13 @@ bonito_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
}
#endif
- pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, &fn);
+ pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &fn);
if (pa->pa_bridgetag) {
pin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev);
*ihp = pa->pa_bridgeih[pin - 1];
} else {
- switch (dev) {
- /* onboard devices, only pin A is wired */
- case 6:
- case 7:
- case 8:
- case 9:
- if (pa->pa_intrpin == PCI_INTERRUPT_PIN_A)
- *ihp = BONITO_DIRECT_IRQ(YEELONG_INTR_PCIA +
- (dev - 6));
- break;
- /* PCI slot */
- case 10:
- *ihp = BONITO_DIRECT_IRQ(YEELONG_INTR_PCIA +
- (pa->pa_intrpin - PCI_INTERRUPT_PIN_A));
- break;
- /* Geode chip */
- case 14:
- switch (fn) {
- case 1: /* Flash */
- *ihp = BONITO_ISA_IRQ(6);
- break;
- case 2: /* AC97 */
- *ihp = BONITO_ISA_IRQ(9);
- break;
- case 4: /* OHCI */
- case 5: /* EHCI */
- *ihp = BONITO_ISA_IRQ(11);
- break;
- }
- break;
- default:
- break;
- }
+ if (bus == 0)
+ *ihp = (*bc->bc_intr_map)(dev, fn, pa->pa_intrpin);
if (*ihp < 0)
return 1;
@@ -961,7 +1001,8 @@ bonito_pci_intr_string(void *cookie, pci_intr_handle_t ih)
static char irqstr[1 + 12];
if (BONITO_IRQ_IS_ISA(ih))
- snprintf(irqstr, sizeof irqstr, "isa irq %d", ih - 16);
+ snprintf(irqstr, sizeof irqstr, "isa irq %d",
+ ih - BONITO_NDIRECT);
else
snprintf(irqstr, sizeof irqstr, "irq %d", ih);
return irqstr;
@@ -1016,7 +1057,12 @@ bonito_set_isa_imr(uint newimr)
imr1 &= ~(1 << 2); /* enable cascade */
imr2 = 0xff & ~(newimr >> 8);
- /* interrupts have been disabled by the caller */
+ /*
+ * For some reason, trying to write the same value to the PIC
+ * registers causes an immediate system freeze, so we only do
+ * this if the value changes.
+ * Note that interrupts have been disabled by the caller.
+ */
if ((newimr ^ bonito_isaimr) & 0xff00) {
REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1) = imr2;
(void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1);
diff --git a/sys/arch/loongson/dev/bonito_irq.h b/sys/arch/loongson/dev/bonito_irq.h
new file mode 100644
index 00000000000..667a2b991ac
--- /dev/null
+++ b/sys/arch/loongson/dev/bonito_irq.h
@@ -0,0 +1,92 @@
+/* $OpenBSD: bonito_irq.h,v 1.1 2010/02/05 20:51:22 miod Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 Miodrag Vallat.
+ *
+ * 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.
+ */
+
+/*
+ * Bonito interrupt assignments
+ */
+
+#define LOONGSON_INTR_GPIO0 0
+#define LOONGSON_INTR_GPIO1 1
+#define LOONGSON_INTR_GPIO2 2
+#define LOONGSON_INTR_GPIO3 3
+
+/* pci interrupts */
+#define LOONGSON_INTR_PCIA 4
+#define LOONGSON_INTR_PCIB 5
+#define LOONGSON_INTR_PCIC 6
+#define LOONGSON_INTR_PCID 7
+
+#define LOONGSON_INTR_PCI_PARERR 8
+#define LOONGSON_INTR_PCI_SYSERR 9
+#define LOONGSON_INTR_DRAM_PARERR 10
+
+/* non-PCI interrupts */
+#define LOONGSON_INTR_INT0 11
+#define LOONGSON_INTR_INT1 12
+#define LOONGSON_INTR_INT2 13
+#define LOONGSON_INTR_INT3 14
+
+#define LOONGSON_INTRMASK_GPIO0 0x00000001 /* can't interrupt */
+#define LOONGSON_INTRMASK_GPIO1 0x00000002
+#define LOONGSON_INTRMASK_GPIO2 0x00000004
+#define LOONGSON_INTRMASK_GPIO3 0x00000008
+
+#define LOONGSON_INTRMASK_GPIO 0x0000000f
+
+/* pci interrupts */
+#define LOONGSON_INTRMASK_PCIA 0x00000010
+#define LOONGSON_INTRMASK_PCIB 0x00000020
+#define LOONGSON_INTRMASK_PCIC 0x00000040
+#define LOONGSON_INTRMASK_PCID 0x00000080
+
+#define LOONGSON_INTRMASK_PCI_PARERR 0x00000100
+#define LOONGSON_INTRMASK_PCI_SYSERR 0x00000200
+#define LOONGSON_INTRMASK_DRAM_PARERR 0x00000400
+
+/* non-PCI interrupts */
+#define LOONGSON_INTRMASK_INT0 0x00000800
+#define LOONGSON_INTRMASK_INT1 0x00001000
+#define LOONGSON_INTRMASK_INT2 0x00002000
+#define LOONGSON_INTRMASK_INT3 0x00004000
+
+#define LOONGSON_INTRMASK_LVL0 0x00007800 /* not maskable in bonito */
+#define LOONGSON_INTRMASK_LVL4 0x000007ff
+
+/*
+ * Bonito interrupt handling recipes:
+ * - we have 14 interrupts on Bonito
+ * - on the Yeeloong, there are also 16 (well, 15) ISA interrupts with the
+ * usual 8259 pair. Bonito and ISA interrupts happen on two different levels.
+ *
+ * For simplicity we allocate 16 vectors for direct interrupts, and 16
+ * vectors for ISA interrupts as well (which will only be used if we are
+ * running on a Yeeloong).
+ */
+
+#define INTPRI_BONITO (INTPRI_CLOCK + 1)
+#define INTPRI_ISA (INTPRI_BONITO + 1)
+
+#define BONITO_NDIRECT 16
+#define BONITO_NISA 16
+#define BONITO_NINTS (BONITO_NDIRECT + BONITO_NISA)
+#define BONITO_ISA_IRQ(i) ((i) + BONITO_NDIRECT)
+#define BONITO_DIRECT_IRQ(i) (i)
+#define BONITO_IRQ_IS_ISA(i) ((i) >= BONITO_NDIRECT)
+
+#define BONITO_DIRECT_MASK(imask) ((imask) & ((1 << BONITO_NDIRECT) - 1))
+#define BONITO_ISA_MASK(imask) ((imask) >> BONITO_NDIRECT)
diff --git a/sys/arch/loongson/dev/bonitoreg.h b/sys/arch/loongson/dev/bonitoreg.h
index 0ece5e21c19..23b5097cc18 100644
--- a/sys/arch/loongson/dev/bonitoreg.h
+++ b/sys/arch/loongson/dev/bonitoreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonitoreg.h,v 1.2 2010/01/31 19:12:12 miod Exp $ */
+/* $OpenBSD: bonitoreg.h,v 1.3 2010/02/05 20:51:22 miod Exp $ */
/* $NetBSD: bonitoreg.h,v 1.6 2005/12/24 20:07:19 perry Exp $ */
/*
@@ -70,6 +70,10 @@
#define BONITO_PCI_REG(x) BONITO(BONITO_PCICONFIGBASE + (x))
+#define BONITO_REV_FPGA(x) ((x) & 0x80)
+#define BONITO_REV_MAJOR(x) (((x) >> 4) & 0x7)
+#define BONITO_REV_MINOR(x) ((x) & 0xf)
+
/* Controller configuration */
#define LOONGSON_PONCFG BONITO(BONITO_REGBASE + 0x00)
@@ -90,7 +94,7 @@
/* ICU Configuration Regs - r/w */
#define BONITO_INTEDGE BONITO(BONITO_REGBASE + 0x24)
-/* INTSTEER is not implemented */
+#define BONITO_INTSTEER BONITO(BONITO_REGBASE + 0x28)
#define BONITO_INTPOL BONITO(BONITO_REGBASE + 0x2c)
/* ICU Enable Regs - INTEN and INTISR are read only */
diff --git a/sys/arch/loongson/dev/bonitovar.h b/sys/arch/loongson/dev/bonitovar.h
index 4e184740808..061950cfa4f 100644
--- a/sys/arch/loongson/dev/bonitovar.h
+++ b/sys/arch/loongson/dev/bonitovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonitovar.h,v 1.1 2009/12/25 21:28:23 miod Exp $ */
+/* $OpenBSD: bonitovar.h,v 1.2 2010/02/05 20:51:22 miod Exp $ */
/* $NetBSD: bonitovar.h,v 1.4 2008/04/28 20:23:28 martin Exp $ */
/*-
@@ -45,6 +45,9 @@ struct bonito_config {
uint32_t bc_intEdge;
uint32_t bc_intSteer;
uint32_t bc_intPol;
+
+ /* PCI Interrupt Assignment for the first bus */
+ int (*bc_intr_map)(int, int, int);
};
struct bonito_softc {
diff --git a/sys/arch/loongson/dev/lemote_irq.h b/sys/arch/loongson/dev/lemote_irq.h
deleted file mode 100644
index b38df51649a..00000000000
--- a/sys/arch/loongson/dev/lemote_irq.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $OpenBSD: lemote_irq.h,v 1.1 2009/12/25 21:11:07 miod Exp $ */
-
-/*
- * Copyright (c) 2009 Miodrag Vallat.
- *
- * 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.
- */
-
-/*
- * Lemote Yeelong specific hardware defines
- */
-
-/*
- * Bonito interrupt assignments
- */
-
-#define YEELONG_INTR_GPIO0 0
-#define YEELONG_INTR_GPIO1 1
-#define YEELONG_INTR_GPIO2 2
-#define YEELONG_INTR_GPIO3 3
-
-/* pci interrupts */
-#define YEELONG_INTR_PCIA 4
-#define YEELONG_INTR_PCIB 5
-#define YEELONG_INTR_PCIC 6
-#define YEELONG_INTR_PCID 7
-
-#define YEELONG_INTR_PCI_PARERR 8
-#define YEELONG_INTR_PCI_SYSERR 9
-#define YEELONG_INTR_DRAM_PARERR 10
-
-/* isa interrupts on i8259 */
-#define YEELONG_INTR_INT0 11
-#define YEELONG_INTR_INT1 12
-#define YEELONG_INTR_INT2 13
-#define YEELONG_INTR_INT3 14
-
-#define YEELONG_INTRMASK_GPIO0 0x00000001 /* can't interrupt */
-#define YEELONG_INTRMASK_GPIO1 0x00000002
-#define YEELONG_INTRMASK_GPIO2 0x00000004
-#define YEELONG_INTRMASK_GPIO3 0x00000008
-
-#define YEELONG_INTRMASK_GPIO 0x0000000f
-
-/* pci interrupts */
-#define YEELONG_INTRMASK_PCIA 0x00000010
-#define YEELONG_INTRMASK_PCIB 0x00000020
-#define YEELONG_INTRMASK_PCIC 0x00000040
-#define YEELONG_INTRMASK_PCID 0x00000080
-
-#define YEELONG_INTRMASK_PCI_PARERR 0x00000100
-#define YEELONG_INTRMASK_PCI_SYSERR 0x00000200
-#define YEELONG_INTRMASK_DRAM_PARERR 0x00000400
-
-/* isa interrupts on i8259 */
-#define YEELONG_INTRMASK_INT0 0x00000800
-#define YEELONG_INTRMASK_INT1 0x00001000
-#define YEELONG_INTRMASK_INT2 0x00002000
-#define YEELONG_INTRMASK_INT3 0x00004000
-
-#define YEELONG_INTRMASK_LVL4 0x000007ff
-#define YEELONG_INTRMASK_LVL0 0x00007800 /* not maskable in bonito */
diff --git a/sys/arch/loongson/include/autoconf.h b/sys/arch/loongson/include/autoconf.h
index eb471091533..ae1fe1e7d43 100644
--- a/sys/arch/loongson/include/autoconf.h
+++ b/sys/arch/loongson/include/autoconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.h,v 1.2 2010/01/09 20:33:16 miod Exp $ */
+/* $OpenBSD: autoconf.h,v 1.3 2010/02/05 20:51:22 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -35,14 +35,16 @@
#include <machine/bus.h>
+struct bonito_config;
+
/*
* Structure holding all misc config information.
*/
struct sys_rec {
int system_type;
- /* Serial console configuration. */
- struct mips_bus_space console_io;
+ /* Bonito configuration */
+ const struct bonito_config *sys_bc;
};
extern struct sys_rec sys_config;
@@ -51,6 +53,9 @@ struct mainbus_attach_args {
const char *maa_name;
};
+extern const struct bonito_config gdium_bonito;
+extern const struct bonito_config yeeloong_bonito;
+
#include <mips64/autoconf.h>
#endif /* _MACHINE_AUTOCONF_H_ */
diff --git a/sys/arch/loongson/loongson/gdium_machdep.c b/sys/arch/loongson/loongson/gdium_machdep.c
new file mode 100644
index 00000000000..c01c9f04159
--- /dev/null
+++ b/sys/arch/loongson/loongson/gdium_machdep.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: gdium_machdep.c,v 1.1 2010/02/05 20:51:22 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * 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.
+ */
+
+/*
+ * Gdium Liberty specific code and configuration data.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <loongson/dev/bonitovar.h>
+#include <loongson/dev/bonito_irq.h>
+
+int gdium_intr_map(int, int, int);
+
+const struct bonito_config gdium_bonito = {
+ .bc_adbase = 11,
+
+ .bc_gpioIE = LOONGSON_INTRMASK_GPIO,
+ .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
+ LOONGSON_INTRMASK_PCI_PARERR,
+ .bc_intSteer = 0,
+ .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
+ LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
+
+ .bc_intr_map = gdium_intr_map
+};
+
+int
+gdium_intr_map(int dev, int fn, int pin)
+{
+ switch (dev) {
+ /* Wireless */
+ case 13: /* C D A B */
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4);
+ /* Frame buffer */
+ case 14:
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA);
+ /* USB */
+ case 15:
+#if 0 /* on revision 1 -- how to tell them apart? */
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
+ (pa->pa_intrpin - 1));
+#else
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB);
+#endif
+ /* Ethernet */
+ case 16:
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID);
+ /* USB */
+ case 17:
+#if 0 /* not present on revision 1 */
+ break;
+#else
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC);
+#endif
+ default:
+ break;
+ }
+
+ return -1;
+}
diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c
index 8658e3f4d09..2b2425740d3 100644
--- a/sys/arch/loongson/loongson/machdep.c
+++ b/sys/arch/loongson/loongson/machdep.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: machdep.c,v 1.8 2010/02/04 16:41:16 otto Exp $ */
+/* $OpenBSD: machdep.c,v 1.9 2010/02/05 20:51:22 miod Exp $ */
/*
- * Copyright (c) 2009 Miodrag Vallat.
+ * Copyright (c) 2009, 2010 Miodrag Vallat.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -78,6 +78,7 @@
#include <mips64/archtype.h>
#include <loongson/dev/bonitoreg.h>
+#include <loongson/dev/bonitovar.h>
/* The following is used externally (sysctl_hw) */
char machine[] = MACHINE; /* Machine "architecture" */
@@ -143,6 +144,28 @@ struct consdev pmoncons = {
};
/*
+ * List of supported system types, from the ``Version'' environment
+ * variable.
+ */
+
+struct bonito_flavour {
+ const char *prefix;
+ int systype;
+ const struct bonito_config *bc;
+};
+
+const struct bonito_flavour bonito_flavours[] = {
+ /* 8.9" Lemote Yeeloong netbook */
+ { "LM8089", LOONGSON_YEELOONG, &yeeloong_bonito },
+ /* supposedly 10.1" Lemote Yeeloong netbook, but those found so far
+ report themselves as LM8089 */
+ { "LM8101", LOONGSON_YEELOONG, &yeeloong_bonito },
+ /* EMTEC Gdium Liberty 1000 */
+ { "Gdium", LOONGSON_GDIUM, &gdium_bonito },
+ { NULL }
+};
+
+/*
* Do all the stuff that locore normally does before calling main().
* Reset mapping and set up mapping to hardware and init "wired" reg.
*/
@@ -155,6 +178,7 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv)
vaddr_t xtlb_handler;
const char *envvar;
int i;
+ const struct bonito_flavour *f;
extern char start[], edata[], end[];
extern char exception[], e_exception[];
@@ -241,10 +265,12 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv)
goto unsupported;
}
- /* Lemote Yeelong 8089 */
- if (strncmp(envvar, "LM8089", 6) == 0) {
- sys_config.system_type = LOONGSON_YEELONG;
- }
+ for (f = bonito_flavours; f->prefix != NULL; f++)
+ if (strncmp(envvar, f->prefix, strlen(f->prefix)) == 0) {
+ sys_config.system_type = f->systype;
+ sys_config.sys_bc = f->bc;
+ break;
+ }
if (sys_config.system_type == 0) {
pmon_printf("This kernel doesn't support model \"%s\".\n",
@@ -253,9 +279,13 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv)
}
switch (sys_config.system_type) {
- case LOONGSON_YEELONG:
+ case LOONGSON_YEELOONG:
hw_vendor = "Lemote";
- hw_prod = "Yeelong";
+ hw_prod = "Yeeloong";
+ break;
+ case LOONGSON_GDIUM:
+ hw_vendor = "EMTEC";
+ hw_prod = "Gdium";
break;
default: /* won't happen */
goto unsupported;
@@ -784,8 +814,18 @@ haltsys:
if (howto & RB_HALT) {
if (howto & RB_POWERDOWN) {
printf("System Power Down.\n");
- REGVAL(BONITO_GPIODATA) &= ~0x00000001;
- REGVAL(BONITO_GPIOIE) &= ~0x00000001;
+ switch (sys_config.system_type) {
+ case LOONGSON_YEELOONG:
+ REGVAL(BONITO_GPIODATA) &= ~0x00000001;
+ REGVAL(BONITO_GPIOIE) &= ~0x00000001;
+ break;
+ case LOONGSON_GDIUM:
+ REGVAL(BONITO_GPIODATA) |= 0x00000002;
+ REGVAL(BONITO_GPIOIE) &= ~0x00000002;
+ break;
+ default:
+ break;
+ }
} else
printf("System Halt.\n");
} else {
@@ -909,6 +949,10 @@ pmoncngetc(dev_t dev)
* PMON does not give us a getc routine. So try to get a whole line
* and return it char by char, trying not to lose the \n. Kind
* of ugly but should work.
+ *
+ * Note that one could theoretically use pmon_read(STDIN, &c, 1)
+ * but the value of STDIN within PMON is not a constant and there
+ * does not seem to be a way of letting us know which value to use.
*/
static char buf[1 + PMON_MAXLN];
static char *bufpos = buf;
diff --git a/sys/arch/loongson/loongson/pmon.c b/sys/arch/loongson/loongson/pmon.c
index fec7d956332..9268dacf873 100644
--- a/sys/arch/loongson/loongson/pmon.c
+++ b/sys/arch/loongson/loongson/pmon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmon.c,v 1.1 2009/11/23 14:47:13 miod Exp $ */
+/* $OpenBSD: pmon.c,v 1.2 2010/02/05 20:51:22 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -60,7 +60,7 @@ pmon_getenv(const char *var)
while (*envptr != 0) {
envstr = (const char *)(vaddr_t)*envptr;
/*
- * There is a PMON2000 bug, at least on Lemote Yeelong,
+ * There is a PMON2000 bug, at least on Lemote Yeeloong,
* which causes it to override part of the environment
* pointers array with the environment data itself.
*
diff --git a/sys/arch/loongson/loongson/yeeloong_machdep.c b/sys/arch/loongson/loongson/yeeloong_machdep.c
new file mode 100644
index 00000000000..1f812872159
--- /dev/null
+++ b/sys/arch/loongson/loongson/yeeloong_machdep.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: yeeloong_machdep.c,v 1.1 2010/02/05 20:51:22 miod Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 Miodrag Vallat.
+ *
+ * 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.
+ */
+
+/*
+ * Lemote Yeeloong specific code and configuration data.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <loongson/dev/bonitovar.h>
+#include <loongson/dev/bonito_irq.h>
+
+int yeeloong_intr_map(int, int, int);
+
+const struct bonito_config yeeloong_bonito = {
+ .bc_adbase = 11,
+
+ .bc_gpioIE = LOONGSON_INTRMASK_GPIO,
+ .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
+ LOONGSON_INTRMASK_PCI_PARERR,
+ .bc_intSteer = 0,
+ .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
+ LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR |
+ LOONGSON_INTRMASK_INT0 | LOONGSON_INTRMASK_INT1,
+
+ .bc_intr_map = yeeloong_intr_map
+};
+
+int
+yeeloong_intr_map(int dev, int fn, int pin)
+{
+ switch (dev) {
+ /* onboard devices, only pin A is wired */
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ if (pin == PCI_INTERRUPT_PIN_A)
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
+ (dev - 6));
+ break;
+ /* PCI slot */
+ case 10:
+ return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
+ (pin - PCI_INTERRUPT_PIN_A));
+ /* Geode chip */
+ case 14:
+ switch (fn) {
+ case 1: /* Flash */
+ return BONITO_ISA_IRQ(6);
+ case 2: /* AC97 */
+ return BONITO_ISA_IRQ(9);
+ case 4: /* OHCI */
+ case 5: /* EHCI */
+ return BONITO_ISA_IRQ(11);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -1;
+}
diff --git a/sys/arch/mips64/include/archtype.h b/sys/arch/mips64/include/archtype.h
index 17afe639c8a..8411bb1f07d 100644
--- a/sys/arch/mips64/include/archtype.h
+++ b/sys/arch/mips64/include/archtype.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: archtype.h,v 1.8 2009/11/07 14:49:00 miod Exp $ */
+/* $OpenBSD: archtype.h,v 1.9 2010/02/05 20:51:22 miod Exp $ */
/*
* Copyright (c) 1997-2004 Opsycon AB, Sweden (www.opsycon.se)
*
@@ -78,7 +78,8 @@
#define WG8232 0x005a /* Willowglen CPU-8232 */
#define LOONGSON_CLASS 0x0060 /* Loongson + PMON2000 class */
-#define LOONGSON_YEELONG 0x0061 /* Lemote Yeelong */
+#define LOONGSON_YEELOONG 0x0061 /* Lemote Yeeloong */
+#define LOONGSON_GDIUM 0x0062 /* EMTEC Gdium Liberty */
#define MISC_CLASS 0x00f0 /* Misc machines... */
#define LAGUNA 0x00f1 /* Heurikon Laguna VME board */