summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2016-11-17 14:41:22 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2016-11-17 14:41:22 +0000
commit57e5d4c118b16705a380446009d65f0b39f9a495 (patch)
treee5a40fda2477afbd78a714099714b45308399bac /sys
parent47227fa5812f4aa501f90b47a9ae06b1f67c2504 (diff)
Add drivers for PCI host bridge and built-in UARTs on Loongson 3A,
and put the pieces together by platform glue. Feedback from miod@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/loongson/conf/files.loongson17
-rw-r--r--sys/arch/loongson/dev/com_leioc.c106
-rw-r--r--sys/arch/loongson/dev/htb.c434
-rw-r--r--sys/arch/loongson/dev/htbreg.h38
-rw-r--r--sys/arch/loongson/dev/htbvar.h28
-rw-r--r--sys/arch/loongson/dev/leioc.c82
-rw-r--r--sys/arch/loongson/dev/leiocreg.h37
-rw-r--r--sys/arch/loongson/dev/leiocvar.h34
-rw-r--r--sys/arch/loongson/dev/mainbus.c8
-rw-r--r--sys/arch/loongson/include/intr.h5
-rw-r--r--sys/arch/loongson/loongson/generic3a_machdep.c281
-rw-r--r--sys/arch/loongson/loongson/machdep.c33
12 files changed, 1091 insertions, 12 deletions
diff --git a/sys/arch/loongson/conf/files.loongson b/sys/arch/loongson/conf/files.loongson
index 52d579e36f6..f647efbd38c 100644
--- a/sys/arch/loongson/conf/files.loongson
+++ b/sys/arch/loongson/conf/files.loongson
@@ -1,4 +1,4 @@
-# $OpenBSD: files.loongson,v 1.23 2016/11/06 10:20:33 visa Exp $
+# $OpenBSD: files.loongson,v 1.24 2016/11/17 14:41:21 visa Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -19,8 +19,8 @@ file arch/loongson/loongson/conf.c
file arch/loongson/loongson/disksubr.c disk
file arch/loongson/loongson/gdium_machdep.c cpu_loongson2
file arch/loongson/loongson/generic2e_machdep.c cpu_loongson2
+file arch/loongson/loongson/generic3a_machdep.c cpu_loongson3
file arch/loongson/loongson/isa_machdep.c isa
-file arch/loongson/loongson/lemote3a_machdep.c cpu_loongson3
file arch/loongson/loongson/loongson2_machdep.c
file arch/loongson/loongson/loongson3_intr.c cpu_loongson3
file arch/loongson/loongson/loongson3_machdep.c cpu_loongson3
@@ -63,6 +63,10 @@ device bonito {}: pcibus
attach bonito at mainbus
file arch/loongson/dev/bonito.c bonito
+device htb {}: pcibus
+attach htb at mainbus
+file arch/loongson/dev/htb.c htb
+
# AMD Geode CS5536 companion chip
file arch/loongson/dev/glx.c bonito & pci
@@ -129,3 +133,12 @@ file arch/loongson/dev/apm.c apm needs-flag
device glxclk
attach glxclk at glxpcib
file arch/loongson/dev/glxclk.c glxclk
+
+define leiobus {}
+
+device leioc: leiobus
+attach leioc at mainbus
+file arch/loongson/dev/leioc.c leioc
+
+attach com at leiobus with com_leioc
+file arch/loongson/dev/com_leioc.c com_leioc
diff --git a/sys/arch/loongson/dev/com_leioc.c b/sys/arch/loongson/dev/com_leioc.c
new file mode 100644
index 00000000000..2c4399cee1a
--- /dev/null
+++ b/sys/arch/loongson/dev/com_leioc.c
@@ -0,0 +1,106 @@
+/* $OpenBSD: com_leioc.c,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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/conf.h>
+#include <sys/device.h>
+#include <sys/termios.h>
+#include <sys/tty.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/loongson3.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+#include <loongson/dev/leiocreg.h>
+#include <loongson/dev/leiocvar.h>
+
+#define UART_FREQ 33000000
+#define UART_RATE 115200
+
+int com_leioc_match(struct device *, void *, void *);
+void com_leioc_attach(struct device *, struct device *, void *);
+
+const struct cfattach com_leioc_ca = {
+ sizeof(struct com_softc), com_leioc_match, com_leioc_attach
+};
+
+extern struct cfdriver com_cd;
+
+int
+com_leioc_match(struct device *parent, void *match, void *aux)
+{
+ struct leioc_attach_args *laa = aux;
+
+ if (strcmp(laa->laa_name, com_cd.cd_name) == 0)
+ return 1;
+
+ return 0;
+}
+
+void
+com_leioc_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct leioc_attach_args *laa = aux;
+ struct com_softc *sc = (void *)self;
+ int console = 0;
+
+ if (comconsiot == &leioc_io_space_tag && comconsaddr == laa->laa_base)
+ console = 1;
+
+ sc->sc_hwflags = 0;
+ sc->sc_swflags = 0;
+ sc->sc_frequency = UART_FREQ;
+
+ if (!console || comconsattached) {
+ sc->sc_iot = &leioc_io_space_tag;
+ sc->sc_iobase = laa->laa_base;
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase, COM_NPORTS, 0,
+ &sc->sc_ioh)) {
+ printf(": could not map UART registers\n");
+ return;
+ }
+ } else {
+ /* Reuse the early console settings. */
+ sc->sc_iot = comconsiot;
+ sc->sc_iobase = comconsaddr;
+ if (comcnattach(sc->sc_iot, sc->sc_iobase, comconsrate,
+ sc->sc_frequency, comconscflag))
+ panic("could not set up serial console");
+ sc->sc_ioh = comconsioh;
+ }
+
+ com_attach_subr(sc);
+
+ loongson3_intr_establish(LS3_IRQ_LPC, IPL_TTY, comintr, sc,
+ sc->sc_dev.dv_xname);
+}
+
+void
+leioc_cons_setup(void)
+{
+ comconsiot = &leioc_io_space_tag;
+ comconsaddr = LEIOC_UART0_BASE;
+ comconsfreq = UART_FREQ;
+ comconsrate = UART_RATE;
+ comconscflag = (TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) |
+ CS8 | CLOCAL;
+}
diff --git a/sys/arch/loongson/dev/htb.c b/sys/arch/loongson/dev/htb.c
new file mode 100644
index 00000000000..2dd3057bee5
--- /dev/null
+++ b/sys/arch/loongson/dev/htb.c
@@ -0,0 +1,434 @@
+/* $OpenBSD: htb.c,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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.
+ */
+
+/*
+ * PCI host bridge driver for Loongson 3A.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/loongson3.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/ppbreg.h>
+
+#include <loongson/dev/htbreg.h>
+#include <loongson/dev/htbvar.h>
+
+struct htb_softc {
+ struct device sc_dev;
+ struct mips_pci_chipset sc_pc;
+};
+
+int htb_match(struct device *, void *, void *);
+void htb_attach(struct device *, struct device *, void *);
+int htb_print(void *, const char *);
+
+void htb_attach_hook(struct device *, struct device *,
+ struct pcibus_attach_args *pba);
+int htb_bus_maxdevs(void *, int);
+pcitag_t htb_make_tag(void *, int, int, int);
+void htb_decompose_tag(void *, pcitag_t, int *, int *, int *);
+int htb_conf_addr(const struct bonito_config *, pcitag_t, int,
+ u_int32_t *, u_int32_t *);
+int htb_conf_size(void *, pcitag_t);
+pcireg_t htb_conf_read(void *, pcitag_t, int);
+void htb_conf_write(void *, pcitag_t, int, pcireg_t);
+int htb_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
+const char *
+ htb_pci_intr_string(void *, pci_intr_handle_t);
+void *htb_pci_intr_establish(void *, pci_intr_handle_t, int,
+ int (*)(void *), void *, char *);
+void htb_pci_intr_disestablish(void *, void *);
+
+bus_addr_t htb_pa_to_device(paddr_t);
+paddr_t htb_device_to_pa(bus_addr_t);
+
+int htb_io_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+int htb_mem_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+paddr_t htb_mem_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
+
+paddr_t htb_cfg_space_addr(pcitag_t, int);
+
+pcireg_t htb_conf_read_early(pcitag_t, int);
+pcitag_t htb_make_tag_early(int, int, int);
+
+const struct cfattach htb_ca = {
+ sizeof(struct htb_softc), htb_match, htb_attach
+};
+
+struct cfdriver htb_cd = {
+ NULL, "htb", DV_DULL
+};
+
+struct machine_bus_dma_tag htb_bus_dma_tag = {
+ ._dmamap_create = _dmamap_create,
+ ._dmamap_destroy = _dmamap_destroy,
+ ._dmamap_load = _dmamap_load,
+ ._dmamap_load_mbuf = _dmamap_load_mbuf,
+ ._dmamap_load_uio = _dmamap_load_uio,
+ ._dmamap_load_raw = _dmamap_load_raw,
+ ._dmamap_load_buffer = _dmamap_load_buffer,
+ ._dmamap_unload = _dmamap_unload,
+ ._dmamap_sync = _dmamap_sync,
+ ._dmamem_alloc = _dmamem_alloc,
+ ._dmamem_free = _dmamem_free,
+ ._dmamem_map = _dmamem_map,
+ ._dmamem_unmap = _dmamem_unmap,
+ ._dmamem_mmap = _dmamem_mmap,
+
+ ._pa_to_device = htb_pa_to_device,
+ ._device_to_pa = htb_device_to_pa
+};
+
+struct mips_bus_space htb_pci_io_space_tag = {
+ .bus_base = PHYS_TO_XKPHYS(HTB_IO_BASE, CCA_NC),
+ ._space_read_1 = generic_space_read_1,
+ ._space_write_1 = generic_space_write_1,
+ ._space_read_2 = generic_space_read_2,
+ ._space_write_2 = generic_space_write_2,
+ ._space_read_4 = generic_space_read_4,
+ ._space_write_4 = generic_space_write_4,
+ ._space_read_8 = generic_space_read_8,
+ ._space_write_8 = generic_space_write_8,
+ ._space_read_raw_2 = generic_space_read_raw_2,
+ ._space_write_raw_2 = generic_space_write_raw_2,
+ ._space_read_raw_4 = generic_space_read_raw_4,
+ ._space_write_raw_4 = generic_space_write_raw_4,
+ ._space_read_raw_8 = generic_space_read_raw_8,
+ ._space_write_raw_8 = generic_space_write_raw_8,
+ ._space_map = htb_io_map,
+ ._space_unmap = generic_space_unmap,
+ ._space_subregion = generic_space_region,
+ ._space_vaddr = generic_space_vaddr,
+ ._space_mmap = generic_space_mmap
+};
+
+struct mips_bus_space htb_pci_mem_space_tag = {
+ .bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
+ ._space_read_1 = generic_space_read_1,
+ ._space_write_1 = generic_space_write_1,
+ ._space_read_2 = generic_space_read_2,
+ ._space_write_2 = generic_space_write_2,
+ ._space_read_4 = generic_space_read_4,
+ ._space_write_4 = generic_space_write_4,
+ ._space_read_8 = generic_space_read_8,
+ ._space_write_8 = generic_space_write_8,
+ ._space_read_raw_2 = generic_space_read_raw_2,
+ ._space_write_raw_2 = generic_space_write_raw_2,
+ ._space_read_raw_4 = generic_space_read_raw_4,
+ ._space_write_raw_4 = generic_space_write_raw_4,
+ ._space_read_raw_8 = generic_space_read_raw_8,
+ ._space_write_raw_8 = generic_space_write_raw_8,
+ ._space_map = htb_mem_map,
+ ._space_unmap = generic_space_unmap,
+ ._space_subregion = generic_space_region,
+ ._space_vaddr = generic_space_vaddr,
+ ._space_mmap = htb_mem_mmap
+};
+
+int
+htb_match(struct device *parent, void *match, void *aux)
+{
+ struct mainbus_attach_args *maa = aux;
+
+ if (loongson_ver != 0x3a && loongson_ver != 0x3b)
+ return 0;
+
+ if (strcmp(maa->maa_name, htb_cd.cd_name) != 0)
+ return 0;
+
+ return 1;
+}
+
+void
+htb_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct pcibus_attach_args pba;
+ struct htb_softc *sc = (struct htb_softc *)self;
+ pci_chipset_tag_t pc = &sc->sc_pc;
+
+ printf("\n");
+
+ pc->pc_conf_v = sc;
+ pc->pc_attach_hook = htb_attach_hook;
+ pc->pc_bus_maxdevs = htb_bus_maxdevs;
+ pc->pc_make_tag = htb_make_tag;
+ pc->pc_decompose_tag = htb_decompose_tag;
+ pc->pc_conf_size = htb_conf_size;
+ pc->pc_conf_read = htb_conf_read;
+ pc->pc_conf_write = htb_conf_write;
+
+ pc->pc_intr_v = sc;
+ pc->pc_intr_map = htb_pci_intr_map;
+ pc->pc_intr_string = htb_pci_intr_string;
+ pc->pc_intr_establish = htb_pci_intr_establish;
+ pc->pc_intr_disestablish = htb_pci_intr_disestablish;
+
+ memset(&pba, 0, sizeof(pba));
+ pba.pba_busname = "pci";
+ pba.pba_iot = &htb_pci_io_space_tag;
+ pba.pba_memt = &htb_pci_mem_space_tag;
+ pba.pba_dmat = &htb_bus_dma_tag;
+ pba.pba_pc = pc;
+ pba.pba_ioex = extent_create("htb_io", 0, 0xffffffff, M_DEVBUF,
+ NULL, 0, EX_NOWAIT | EX_FILLED);
+ if (pba.pba_ioex != NULL) {
+ extent_free(pba.pba_ioex, 0, HTB_IO_SIZE, EX_NOWAIT);
+ }
+ pba.pba_memex = extent_create("htb_mem", 0, 0xffffffff, M_DEVBUF,
+ NULL, 0, EX_NOWAIT | EX_FILLED);
+ if (pba.pba_memex != NULL) {
+ extent_free(pba.pba_memex, HTB_MEM_BASE, HTB_MEM_SIZE,
+ EX_NOWAIT);
+ }
+ pba.pba_domain = pci_ndomains++;
+ pba.pba_bus = 0;
+ config_found(&sc->sc_dev, &pba, htb_print);
+}
+
+int
+htb_print(void *aux, const char *pnp)
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if (pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+
+ return UNCONF;
+}
+
+void
+htb_attach_hook(struct device *parent, struct device *self,
+ struct pcibus_attach_args *pba)
+{
+}
+
+int
+htb_bus_maxdevs(void *v, int busno)
+{
+ return 32;
+}
+
+pcitag_t
+htb_make_tag(void *unused, int b, int d, int f)
+{
+ return (b << 16) | (d << 11) | (f << 8);
+}
+
+void
+htb_decompose_tag(void *unused, pcitag_t tag, int *bp, int *dp, int *fp)
+{
+ if (bp != NULL)
+ *bp = (tag >> 16) & 0xff;
+ if (dp != NULL)
+ *dp = (tag >> 11) & 0x1f;
+ if (fp != NULL)
+ *fp = (tag >> 8) & 0x7;
+}
+
+int
+htb_conf_addr(const struct bonito_config *bc, pcitag_t tag, int offset,
+ u_int32_t *cfgoff, u_int32_t *pcimap_cfg)
+{
+ return -1;
+}
+
+int
+htb_conf_size(void *v, pcitag_t tag)
+{
+ return PCIE_CONFIG_SPACE_SIZE;
+}
+
+pcireg_t
+htb_conf_read(void *v, pcitag_t tag, int offset)
+{
+ return REGVAL(htb_cfg_space_addr(tag, offset));
+}
+
+void
+htb_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data)
+{
+ REGVAL(htb_cfg_space_addr(tag, offset)) = data;
+}
+
+paddr_t
+htb_cfg_space_addr(pcitag_t tag, int offset)
+{
+ paddr_t pa;
+ int bus;
+
+ htb_decompose_tag(NULL, tag, &bus, NULL, NULL);
+ if (bus == 0)
+ pa = HTB_CFG_TYPE0_BASE;
+ else
+ pa = HTB_CFG_TYPE1_BASE;
+ return pa + tag + (offset & 0xfffc);
+}
+
+/*
+ * PCI interrupt handling
+ */
+
+int
+htb_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
+{
+ int dev, pin;
+
+ *ihp = (pci_intr_handle_t)-1;
+
+ if (pa->pa_intrpin == 0)
+ return 1;
+
+ if (pa->pa_intrpin > PCI_INTERRUPT_PIN_MAX) {
+ printf(": bad interrupt pin %d\n", pa->pa_intrpin);
+ return 1;
+ }
+
+ pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL);
+ if (pa->pa_bridgetag != NULL) {
+ pin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev);
+ if (pa->pa_bridgeih[pin - 1] != (pci_intr_handle_t)-1) {
+ *ihp = pa->pa_bridgeih[pin - 1];
+ return 0;
+ }
+ }
+
+ if (pa->pa_intrline != 0) {
+ *ihp = pa->pa_intrline;
+ return 0;
+ }
+
+ return 1;
+}
+
+const char *
+htb_pci_intr_string(void *cookie, pci_intr_handle_t ih)
+{
+ static char irqstr[16];
+
+ snprintf(irqstr, sizeof(irqstr), "irq %lu", ih);
+ return irqstr;
+}
+
+void *
+htb_pci_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
+ int (*cb)(void *), void *cbarg, char *name)
+{
+ return loongson3_ht_intr_establish(ih, level, cb, cbarg, name);
+}
+
+void
+htb_pci_intr_disestablish(void *cookie, void *ihp)
+{
+ loongson3_ht_intr_disestablish(ihp);
+}
+
+bus_addr_t
+htb_pa_to_device(paddr_t pa)
+{
+ return pa ^ loongson_dma_base;
+}
+
+paddr_t
+htb_device_to_pa(bus_addr_t addr)
+{
+ return addr ^ loongson_dma_base;
+}
+
+/*
+ * bus_space(9) mapping routines
+ */
+
+int
+htb_io_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ const struct legacy_io_range *r;
+ bus_addr_t end;
+
+ if (offs >= HTB_IO_SIZE)
+ return EINVAL;
+
+ if (offs < HTB_IO_LEGACY) {
+ end = offs + size - 1;
+ if ((r = sys_platform->legacy_io_ranges) == NULL)
+ return ENXIO;
+ for ( ; r->start != 0; r++) {
+ if (offs >= r->start && end <= r->end)
+ break;
+ }
+ if (r->end == 0)
+ return ENXIO;
+ }
+
+ *bshp = t->bus_base + offs;
+ return 0;
+}
+
+int
+htb_mem_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ if (offs < HTB_MEM_BASE || offs >= HTB_MEM_BASE + HTB_MEM_SIZE)
+ return EINVAL;
+
+ *bshp = t->bus_base + offs;
+ return 0;
+}
+
+paddr_t
+htb_mem_mmap(bus_space_tag_t t, bus_addr_t addr, off_t off, int prot,
+ int flags)
+{
+ return addr + off;
+}
+
+/*
+ * Functions for system setup
+ */
+
+void
+htb_early_setup(void)
+{
+ pci_make_tag_early = htb_make_tag_early;
+ pci_conf_read_early = htb_conf_read_early;
+
+ early_mem_t = &htb_pci_mem_space_tag;
+ early_io_t = &htb_pci_io_space_tag;
+}
+
+pcitag_t
+htb_make_tag_early(int b, int d, int f)
+{
+ return htb_make_tag(NULL, b, d, f);
+}
+
+pcireg_t
+htb_conf_read_early(pcitag_t tag, int reg)
+{
+ return htb_conf_read(NULL, tag, reg);
+}
diff --git a/sys/arch/loongson/dev/htbreg.h b/sys/arch/loongson/dev/htbreg.h
new file mode 100644
index 00000000000..0480f831e51
--- /dev/null
+++ b/sys/arch/loongson/dev/htbreg.h
@@ -0,0 +1,38 @@
+/* $OpenBSD: htbreg.h,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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 _LOONGSON_DEV_HTBREG_H_
+#define _LOONGSON_DEV_HTBREG_H_
+
+/*
+ * These addresses are translated by the CPU nodes' crossbar to the address
+ * space of the HT interface that connects to the northbridge. The translation
+ * is set up by the firmware.
+ */
+
+#define HTB_IO_BASE 0x18000000u
+#define HTB_CFG_TYPE0_BASE 0x1a000000u
+#define HTB_CFG_TYPE1_BASE 0x1b000000u
+#define HTB_MEM_BASE 0x40000000u
+
+#define HTB_IO_SIZE 0x01000000u
+#define HTB_MEM_SIZE 0x40000000u
+
+#define HTB_IO_LEGACY 0x4000u
+
+#endif /* _LOONGSON_DEV_HTBREG_H_ */
diff --git a/sys/arch/loongson/dev/htbvar.h b/sys/arch/loongson/dev/htbvar.h
new file mode 100644
index 00000000000..3caffe43cc3
--- /dev/null
+++ b/sys/arch/loongson/dev/htbvar.h
@@ -0,0 +1,28 @@
+/* $OpenBSD: htbvar.h,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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 _LOONGSON_DEV_HTBVAR_H_
+#define _LOONGSON_DEV_HTBVAR_H_
+
+extern struct mips_isa_chipset htb_isa_chipset;
+extern struct mips_bus_space htb_pci_mem_space_tag;
+extern struct mips_bus_space htb_pci_io_space_tag;
+
+void htb_early_setup(void);
+
+#endif /* _LOONGSON_DEV_HTBVAR_H_ */
diff --git a/sys/arch/loongson/dev/leioc.c b/sys/arch/loongson/dev/leioc.c
new file mode 100644
index 00000000000..71500f63218
--- /dev/null
+++ b/sys/arch/loongson/dev/leioc.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: leioc.c,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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.
+ */
+
+/*
+ * Driver for the Loongson 3A low-end IO controller.
+ *
+ * Each Loongson 3A CPU package has a built-in `low-end' IO controller.
+ * The controller provides GPIO, LPCI, PCI, SPI, and UART interfaces.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+
+#include <machine/autoconf.h>
+
+#include <loongson/dev/leiocreg.h>
+#include <loongson/dev/leiocvar.h>
+
+int leioc_match(struct device *, void *, void*);
+void leioc_attach(struct device *, struct device *, void *);
+
+const struct cfattach leioc_ca = {
+ sizeof(struct device), leioc_match, leioc_attach
+};
+
+struct cfdriver leioc_cd = {
+ NULL, "leioc", DV_DULL
+};
+
+struct mips_bus_space leioc_io_space_tag = {
+ .bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
+ ._space_read_1 = generic_space_read_1,
+ ._space_write_1 = generic_space_write_1,
+ ._space_map = generic_space_map,
+ ._space_unmap = generic_space_unmap
+};
+
+int
+leioc_match(struct device *parent, void *cfg, void *aux)
+{
+ struct mainbus_attach_args *maa = aux;
+
+ if (loongson_ver != 0x3a && loongson_ver != 0x3b)
+ return 0;
+
+ if (strcmp(maa->maa_name, leioc_cd.cd_name) != 0)
+ return 0;
+
+ return 1;
+}
+
+void
+leioc_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct leioc_attach_args laa;
+
+ printf("\n");
+
+ laa.laa_name = "com";
+ laa.laa_iot = &leioc_io_space_tag;
+ laa.laa_base = LEIOC_UART0_BASE;
+ config_found(self, &laa, NULL);
+ laa.laa_base = LEIOC_UART1_BASE;
+ config_found(self, &laa, NULL);
+}
diff --git a/sys/arch/loongson/dev/leiocreg.h b/sys/arch/loongson/dev/leiocreg.h
new file mode 100644
index 00000000000..f24b9988332
--- /dev/null
+++ b/sys/arch/loongson/dev/leiocreg.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: leiocreg.h,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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 _LOONGSON_DEV_LEIOCREG_H_
+#define _LOONGSON_DEV_LEIOCREG_H_
+
+#define LEIOC_PCI_CFG_BASE 0x1fe00000
+#define LEIOC_IO_CFG_BASE 0x1fe00100
+#define LEIOC_UART0_BASE 0x1fe001e0
+#define LEIOC_UART1_BASE 0x1fe001e8
+#define LEIOC_SPI_BASE 0x1fe001f0
+
+#define LEIOC_LPC_MEM_BASE 0x1c000000
+#define LEIOC_LPC_MEM_SIZE 0x01000000
+#define LEIOC_LPC_BOOT_BASE 0x1fc00000
+#define LEIOC_LPC_BOOT_SIZE 0x00100000
+#define LEIOC_LPC_REG_BASE 0x1fe00200
+#define LEIOC_LPC_REG_SIZE 0x00000100
+#define LEIOC_LPC_IO_BASE 0x1ff00000
+#define LEIOC_LPC_IO_SIZE 0x00010000
+
+#endif /* _LOONGSON_DEV_LEIOCREG_H_ */
diff --git a/sys/arch/loongson/dev/leiocvar.h b/sys/arch/loongson/dev/leiocvar.h
new file mode 100644
index 00000000000..c9e16b3529f
--- /dev/null
+++ b/sys/arch/loongson/dev/leiocvar.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: leiocvar.h,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Visa Hankala
+ *
+ * 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 _LOONGSON_DEV_LEIOCVAR_H_
+#define _LOONGSON_DEV_LEIOCVAR_H_
+
+struct leioc_attach_args {
+ paddr_t laa_base;
+ const char *laa_name;
+
+ bus_space_tag_t laa_iot;
+ bus_space_handle_t laa_ioh;
+};
+
+extern struct mips_bus_space leioc_io_space_tag;
+
+void leioc_cons_setup(void);
+
+#endif /* _LOONGSON_DEV_LEIOCVAR_H_ */
diff --git a/sys/arch/loongson/dev/mainbus.c b/sys/arch/loongson/dev/mainbus.c
index ee8c6b6eff3..87501a88c2e 100644
--- a/sys/arch/loongson/dev/mainbus.c
+++ b/sys/arch/loongson/dev/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.8 2013/05/30 16:15:01 deraadt Exp $ */
+/* $OpenBSD: mainbus.c,v 1.9 2016/11/17 14:41:21 visa Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -70,6 +70,12 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
caa.caa_maa.maa_name = "bonito";
config_found(self, &caa.caa_maa, mainbus_print);
+ caa.caa_maa.maa_name = "htb";
+ config_found(self, &caa.caa_maa, mainbus_print);
+
+ caa.caa_maa.maa_name = "leioc";
+ config_found(self, &caa.caa_maa, mainbus_print);
+
if (md_startclock == NULL) {
caa.caa_maa.maa_name = "clock";
config_found(self, &caa.caa_maa, mainbus_print);
diff --git a/sys/arch/loongson/include/intr.h b/sys/arch/loongson/include/intr.h
index 5d8d9fa9e6b..949e33f6b0e 100644
--- a/sys/arch/loongson/include/intr.h
+++ b/sys/arch/loongson/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.9 2016/11/06 10:20:33 visa Exp $ */
+/* $OpenBSD: intr.h,v 1.10 2016/11/17 14:41:21 visa Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -57,7 +57,8 @@
#define IPL_STATCLOCK IPL_CLOCK
#define IPL_SCHED 7 /* everything */
#define IPL_HIGH 7 /* everything */
-#define NIPLS 8 /* Number of levels */
+#define IPL_IPI 8 /* interprocessor interrupt */
+#define NIPLS 9 /* Number of levels */
#define IPL_MPFLOOR IPL_TTY
diff --git a/sys/arch/loongson/loongson/generic3a_machdep.c b/sys/arch/loongson/loongson/generic3a_machdep.c
new file mode 100644
index 00000000000..8d891c28ff0
--- /dev/null
+++ b/sys/arch/loongson/loongson/generic3a_machdep.c
@@ -0,0 +1,281 @@
+/* $OpenBSD: generic3a_machdep.c,v 1.1 2016/11/17 14:41:21 visa Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010, 2012 Miodrag Vallat.
+ * Copyright (c) 2016 Visa Hankala.
+ *
+ * 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.
+ */
+
+/*
+ * Generic Loongson 2Gq and 3A code and configuration data.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <mips64/archtype.h>
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <machine/pmon.h>
+
+#include <mips64/loongson3.h>
+
+#include <dev/ic/i8259reg.h>
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <loongson/dev/htbreg.h>
+#include <loongson/dev/htbvar.h>
+#include <loongson/dev/leiocvar.h>
+
+#define IRQ_CASCADE 2
+
+void generic3a_device_register(struct device *, void *);
+void generic3a_powerdown(void);
+void generic3a_reset(void);
+void generic3a_setup(void);
+
+void rs780e_setup(void);
+
+void rs780e_isa_attach_hook(struct device *, struct device *,
+ struct isabus_attach_args *iba);
+void *rs780e_isa_intr_establish(void *, int, int, int, int (*)(void *),
+ void *, char *);
+void rs780e_isa_intr_disestablish(void *, void *);
+
+void rs780e_eoi(int);
+void rs780e_set_imask(uint32_t);
+void rs780e_irq_mask(int);
+void rs780e_irq_unmask(int);
+
+/* Firmware entry points */
+void (*generic3a_reboot_entry)(void);
+void (*generic3a_poweroff_entry)(void);
+
+struct mips_isa_chipset rs780e_isa_chipset = {
+ .ic_v = NULL,
+ .ic_attach_hook = rs780e_isa_attach_hook,
+ .ic_intr_establish = rs780e_isa_intr_establish,
+ .ic_intr_disestablish = rs780e_isa_intr_disestablish
+};
+
+const struct legacy_io_range rs780e_legacy_ranges[] = {
+ /* isa */
+ { IO_DMAPG + 4, IO_DMAPG + 4 },
+ /* mcclock */
+ { IO_RTC, IO_RTC + 1 },
+#ifdef notyet
+ /* pciide */
+ { 0x170, 0x170 + 7 },
+ { 0x1f0, 0x1f0 + 7 },
+ { 0x376, 0x376 },
+ { 0x3f6, 0x3f6 },
+#endif
+ /* pckbc */
+ { IO_KBD, IO_KBD },
+ { IO_KBD + 4, IO_KBD + 4 },
+
+ { 0, 0 }
+};
+
+const struct platform rs780e_platform = {
+ .system_type = LOONGSON_3A,
+ .vendor = "Loongson",
+ .product = "LS3A with RS780E",
+
+ .isa_chipset = &rs780e_isa_chipset,
+ .legacy_io_ranges = rs780e_legacy_ranges,
+
+ .setup = rs780e_setup,
+ .device_register = generic3a_device_register,
+
+ .powerdown = generic3a_powerdown,
+ .reset = generic3a_reset
+};
+
+const struct pic rs780e_pic = {
+ rs780e_eoi, rs780e_irq_mask, rs780e_irq_unmask
+};
+
+uint32_t rs780e_imask;
+
+/*
+ * Generic 3A routines
+ */
+
+void
+generic3a_powerdown(void)
+{
+ if (generic3a_poweroff_entry != NULL)
+ generic3a_poweroff_entry();
+}
+
+void
+generic3a_reset(void)
+{
+ if (generic3a_reboot_entry != NULL)
+ generic3a_reboot_entry();
+}
+
+void
+generic3a_setup(void)
+{
+ const struct pmon_env_reset *resetenv = pmon_get_env_reset();
+
+ if (resetenv != NULL) {
+ generic3a_reboot_entry = resetenv->warm_boot;
+ generic3a_poweroff_entry = resetenv->poweroff;
+ }
+
+ loongson3_intr_init();
+}
+
+void
+generic3a_device_register(struct device *dev, void *aux)
+{
+#if notyet
+ const char *drvrname = dev->dv_cfdata->cf_driver->cd_name;
+ const char *name = dev->dv_xname;
+
+ if (dev->dv_class != bootdev_class)
+ return;
+
+ /*
+ * The device numbering must match. There's no way
+ * pmon tells us more info. Depending on the usb slot
+ * and hubs used you may be lucky. Also, assume umass/sd for usb
+ * attached devices.
+ */
+ switch (bootdev_class) {
+ case DV_DISK:
+ if (strcmp(drvrname, "wd") == 0 && strcmp(name, bootdev) == 0)
+ bootdv = dev;
+ else {
+ /* XXX this really only works safely for usb0... */
+ if ((strcmp(drvrname, "sd") == 0 ||
+ strcmp(drvrname, "cd") == 0) &&
+ strncmp(bootdev, "usb", 3) == 0 &&
+ strcmp(name + 2, bootdev + 3) == 0)
+ bootdv = dev;
+ }
+ break;
+ case DV_IFNET:
+ /*
+ * This relies on the onboard Ethernet interface being
+ * attached before any other (usb) interface.
+ */
+ bootdv = dev;
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
+/*
+ * Routines for RS780E-based systems
+ */
+
+void
+rs780e_setup(void)
+{
+ generic3a_setup();
+
+ htb_early_setup();
+
+ /*
+ * Set up the PIC in the southbridge.
+ */
+
+ /* master */
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_ICW1) = ICW1_SELECT | ICW1_IC4;
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0);
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(IRQ_CASCADE);
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086;
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_OCW1) = 0xff;
+
+ /* slave */
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_ICW1) = ICW1_SELECT | ICW1_IC4;
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8);
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(IRQ_CASCADE);
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086;
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_OCW1) = 0xff;
+
+ loongson3_register_ht_pic(&rs780e_pic);
+}
+
+void
+rs780e_isa_attach_hook(struct device *parent, struct device *self,
+ struct isabus_attach_args *iba)
+{
+}
+
+void *
+rs780e_isa_intr_establish(void *v, int irq, int type, int level,
+ int (*cb)(void *), void *cbarg, char *name)
+{
+ return loongson3_ht_intr_establish(irq, level, cb, cbarg, name);
+}
+
+void
+rs780e_isa_intr_disestablish(void *v, void *ih)
+{
+ loongson3_ht_intr_disestablish(ih);
+}
+
+void
+rs780e_eoi(int irq)
+{
+ KASSERT((unsigned int)irq <= 15);
+
+ if (irq & 8) {
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_OCW2) =
+ OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq);
+ irq = IRQ_CASCADE;
+ }
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_OCW2) =
+ OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq);
+}
+
+void
+rs780e_set_imask(uint32_t new_imask)
+{
+ uint8_t imr1, imr2;
+
+ imr1 = 0xff & ~new_imask;
+ imr1 &= ~(1u << IRQ_CASCADE);
+ imr2 = 0xff & ~(new_imask >> 8);
+
+ REGVAL8(HTB_IO_BASE + IO_ICU2 + PIC_OCW1) = imr2;
+ REGVAL8(HTB_IO_BASE + IO_ICU1 + PIC_OCW1) = imr1;
+
+ rs780e_imask = new_imask;
+}
+
+void
+rs780e_irq_mask(int irq)
+{
+ rs780e_set_imask(rs780e_imask & ~(1u << irq));
+}
+
+void
+rs780e_irq_unmask(int irq)
+{
+ rs780e_set_imask(rs780e_imask | (1u << irq));
+}
diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c
index 8a7f79ffb0e..0f65dd05e95 100644
--- a/sys/arch/loongson/loongson/machdep.c
+++ b/sys/arch/loongson/loongson/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.67 2016/10/09 11:25:39 tom Exp $ */
+/* $OpenBSD: machdep.c,v 1.68 2016/11/17 14:41:21 visa Exp $ */
/*
* Copyright (c) 2009, 2010, 2014 Miodrag Vallat.
@@ -114,6 +114,7 @@ caddr_t msgbufbase;
int physmem; /* Max supported memory, changes to actual. */
int ncpu = 1; /* At least one CPU in the system. */
+int nnodes = 1; /* Number of NUMA nodes, only on 3A. */
struct user *proc0paddr;
const struct platform *sys_platform;
@@ -142,6 +143,8 @@ extern void parsepmonbp(void);
const struct platform *loongson_identify(const char *, int);
vaddr_t mips_init(uint64_t, uint64_t, uint64_t, uint64_t, char *);
+extern void htb_early_setup(void);
+
extern void loongson2e_setup(u_long, u_long);
extern void loongson2f_setup(u_long, u_long);
extern void loongson3a_setup(u_long, u_long);
@@ -173,8 +176,8 @@ extern const struct platform ebenton_platform;
extern const struct platform fuloong_platform;
extern const struct platform gdium_platform;
extern const struct platform generic2e_platform;
-extern const struct platform lemote3a_platform;
extern const struct platform lynloong_platform;
+extern const struct platform rs780e_platform;
extern const struct platform yeeloong_platform;
const struct bonito_flavour bonito_flavours[] = {
@@ -198,12 +201,12 @@ const struct bonito_flavour bonito_flavours[] = {
#endif
#ifdef CPU_LOONGSON3
/* Laptops */
- { "A1004", &lemote3a_platform }, /* 3A */
- { "A1201", &lemote3a_platform }, /* 2Gq */
+ { "A1004", &rs780e_platform }, /* 3A */
+ { "A1201", &rs780e_platform }, /* 2Gq */
/* Lemote Xinghuo 6100 (mini-ITX PC) */
- { "A1101", &lemote3a_platform }, /* 3A */
+ { "A1101", &rs780e_platform }, /* 3A */
/* All-in-one PC */
- { "A1205", &lemote3a_platform }, /* 2Gq */
+ { "A1205", &rs780e_platform }, /* 2Gq */
#endif
{ NULL }
};
@@ -220,7 +223,23 @@ loongson_identify(const char *version, int envtype)
switch (envtype) {
#ifdef CPU_LOONGSON3
case PMON_ENVTYPE_EFI:
- return &lemote3a_platform;
+ if (loongson_ver == 0x3a || loongson_ver == 0x3b) {
+ pcitag_t tag;
+ pcireg_t id;
+
+ htb_early_setup();
+
+ /* Determine platform by host bridge. */
+ tag = pci_make_tag_early(0, 0, 0);
+ id = pci_conf_read_early(tag, PCI_ID_REG);
+ switch (id) {
+ case PCI_ID_CODE(PCI_VENDOR_AMD,
+ PCI_PRODUCT_AMD_RS780_HB):
+ return &rs780e_platform;
+ }
+ }
+ pmon_printf("Unable to figure out model!\n");
+ return NULL;
#endif
default: