diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-12 08:14:03 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-12 08:14:03 +0000 |
commit | 366c630a0b1904abc330618f8cbb768c50cf6638 (patch) | |
tree | 98010acfa66515504957e4c476e0ee34dc79d103 /sys | |
parent | b6d0a50e9558bc0e1b1d189cfcacb6422ff0cdfc (diff) |
Overhaul per-platform specific operation by moving all the differences into
per-platform structs or function pointers; therefore bonito(4) no longer needs
to know about particular systems.
While there, bring little bits of Fuloong 2F support, tested on otto@'s
machine.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/loongson/conf/GENERIC | 5 | ||||
-rw-r--r-- | sys/arch/loongson/dev/bonito.c | 546 | ||||
-rw-r--r-- | sys/arch/loongson/dev/bonitoreg.h | 3 | ||||
-rw-r--r-- | sys/arch/loongson/dev/bonitovar.h | 8 | ||||
-rw-r--r-- | sys/arch/loongson/include/autoconf.h | 29 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/gdium_machdep.c | 54 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/machdep.c | 65 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/wscons_machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/yeeloong_machdep.c | 76 |
9 files changed, 499 insertions, 291 deletions
diff --git a/sys/arch/loongson/conf/GENERIC b/sys/arch/loongson/conf/GENERIC index dfc989dc8e6..27ba3c0085e 100644 --- a/sys/arch/loongson/conf/GENERIC +++ b/sys/arch/loongson/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.7 2010/02/09 12:15:37 jasper Exp $ +# $OpenBSD: GENERIC,v 1.8 2010/02/12 08:14:00 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -43,6 +43,7 @@ pckbd* at pckbc? wskbd* at pckbd? mux 1 pmsi* at pckbc? wsmouse* at pmsi? mux 0 +com0 at isa? port 0x2f8 irq 3 pciide* at pci? wd* at pciide? flags 0x0000 @@ -118,6 +119,7 @@ wsdisplay* at udl? # NICs ral* at pci? +re* at pci? rl* at pci? # Media Independent Interface (mii) drivers @@ -125,6 +127,7 @@ acphy* at mii? # Altima AC101 PHYs amphy* at mii? # AMD 79C873 PHYs bmtphy* at mii? # Broadcom 10/100 PHYs eephy* at mii? # Marvell 88E1000 series PHY +rgephy* at mii? # Realtek 8169S/8110S PHY rlphy* at mii? # RealTek 8139 internal PHYs urlphy* at mii? # Realtek RTL8150L internal PHY ukphy* at mii? # "unknown" PHYs diff --git a/sys/arch/loongson/dev/bonito.c b/sys/arch/loongson/dev/bonito.c index 2bb0e19e953..6762eec2025 100644 --- a/sys/arch/loongson/dev/bonito.c +++ b/sys/arch/loongson/dev/bonito.c @@ -1,9 +1,9 @@ -/* $OpenBSD: bonito.c,v 1.9 2010/02/10 21:09:40 miod Exp $ */ +/* $OpenBSD: bonito.c,v 1.10 2010/02/12 08:14:02 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 $ */ /* - * 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 @@ -50,6 +50,10 @@ * PCI configuration space support for the Loongson PCI and memory controller * chip, which is derived from the Algorithmics BONITO chip. */ +/* + * XXX The legacy interrupt scheme is entangled and as many parts as + * XXX possible should move to pcib.c... + */ #include <sys/param.h> #include <sys/systm.h> @@ -75,6 +79,10 @@ #include <loongson/dev/bonitovar.h> #include <loongson/dev/bonito_irq.h> +#if 0 +#define BONITO_DEBUG +#endif + int bonito_match(struct device *, void *, void *); void bonito_attach(struct device *, struct device *, void *); @@ -113,18 +121,16 @@ void bonito_pci_intr_disestablish(void *, void *); int bonito_conf_addr(const struct bonito_config *, pcitag_t, int, u_int32_t *, u_int32_t *); -uint bonito_get_isa_imr(void); -uint bonito_get_isa_isr(void); -void bonito_set_isa_imr(uint); -void bonito_isa_specific_eoi(int); - -uint32_t bonito_isa_intr(uint32_t, struct trap_frame *); - void bonito_splx(int); void bonito_setintrmask(int); -void bonito_isa_splx(int); -void bonito_isa_setintrmask(int); +uint loongson_get_isa_imr(void); +uint loongson_get_isa_isr(void); +void loongson_set_isa_imr(uint); +void loongson_isa_specific_eoi(int); +uint32_t loongson_isa_intr(uint32_t, struct trap_frame *); +void loongson_isa_splx(int); +void loongson_isa_setintrmask(int); /* * Bonito interrupt handling declarations. @@ -134,8 +140,7 @@ struct intrhand *bonito_intrhand[BONITO_NINTS]; uint64_t bonito_intem; uint64_t bonito_imask[NIPLS]; -#define REGVAL8(x) *((volatile u_int8_t *)PHYS_TO_XKPHYS(x, CCA_NC)) -uint bonito_isaimr; +uint loongson_isaimr; struct machine_bus_dma_tag bonito_bus_dma_tag = { ._dmamap_create = _dmamap_create, @@ -158,6 +163,9 @@ struct machine_bus_dma_tag bonito_bus_dma_tag = { ._device_to_pa = bonito_device_to_pa }; +int bonito_io_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); + struct mips_bus_space bonito_pci_io_space_tag = { .bus_base = PHYS_TO_XKPHYS(BONITO_PCIIO_BASE, CCA_NC), ._space_read_1 = generic_space_read_1, @@ -174,7 +182,7 @@ struct mips_bus_space bonito_pci_io_space_tag = { ._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 = generic_space_map, + ._space_map = bonito_io_map, ._space_unmap = generic_space_unmap, ._space_subregion = generic_space_region, ._space_vaddr = generic_space_vaddr @@ -220,9 +228,7 @@ bonito_attach(struct device *parent, struct device *self, void *aux) struct pcibus_attach_args pba; pci_chipset_tag_t pc = &sc->sc_pc; const struct bonito_config *bc; - struct extent *ioex, *memex; uint32_t reg; - int real_bonito; /* * Loongson 2F processors do not use a real Bonito64 chip but @@ -232,12 +238,12 @@ bonito_attach(struct device *parent, struct device *self, void *aux) */ if (curcpu()->ci_hw.type == MIPS_LOONGSON2 && (curcpu()->ci_hw.c0prid & 0xff) == 0x2f - 0x2c) - real_bonito = 0; + sc->sc_compatible = 0; else - real_bonito = 1; + sc->sc_compatible = 1; reg = PCI_REVISION(REGVAL(BONITO_PCI_REG(PCI_CLASS_REG))); - if (real_bonito) { + if (sc->sc_compatible) { 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)); @@ -246,26 +252,51 @@ bonito_attach(struct device *parent, struct device *self, void *aux) PCI_REVISION(REGVAL(BONITO_PCI_REG(PCI_CLASS_REG)))); } - bc = sys_config.sys_bc; + bc = sys_platform->bonito_config; sc->sc_bonito = bc; SLIST_INIT(&sc->sc_hook); +#ifdef BONITO_DEBUG + if (!sc->sc_compatible) + printf("ISR4C: %08x\n", REGVAL(BONITO_PCI_REG(0x4c))); + printf("PCIMAP: %08x\n", REGVAL(BONITO_PCIMAP)); + printf("MEMWIN: %08x.%08x - %08x.%08x\n", + REGVAL(BONITO_MEM_WIN_BASE_H), REGVAL(BONITO_MEM_WIN_BASE_L), + REGVAL(BONITO_MEM_WIN_MASK_H), REGVAL(BONITO_MEM_WIN_MASK_L)); + if (!sc->sc_compatible) { + printf("HITSEL0: %08x.%08x\n", + REGVAL(LOONGSON_PCI_HIT0_SEL_H), + REGVAL(LOONGSON_PCI_HIT0_SEL_L)); + printf("HITSEL1: %08x.%08x\n", + REGVAL(LOONGSON_PCI_HIT1_SEL_H), + REGVAL(LOONGSON_PCI_HIT1_SEL_L)); + printf("HITSEL2: %08x.%08x\n", + REGVAL(LOONGSON_PCI_HIT2_SEL_H), + REGVAL(LOONGSON_PCI_HIT2_SEL_L)); + } + printf("PCI BAR 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x\n", + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 0 * 4)), + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 1 * 4)), + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 2 * 4)), + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 3 * 4)), + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 4 * 4)), + REGVAL(BONITO_PCI_REG(PCI_MAPREG_START + 5 * 4))); +#endif + /* * Setup proper abitration. */ - 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 */ - } + if (!sc->sc_compatible) { + /* + * 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? + */ + /* c2000001 -> d2000001 */ + REGVAL(BONITO_PCI_REG(0x4c)) |= 0x10000000; /* all pci devices may need to hold the bus */ reg = REGVAL(LOONGSON_PXARB_CFG); @@ -281,56 +312,21 @@ 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) + if (sc->sc_compatible) REGVAL(BONITO_INTSTEER) = bc->bc_intSteer; REGVAL(BONITO_INTPOL) = bc->bc_intPol; REGVAL(BONITO_INTENCLR) = 0xffffffff; (void)REGVAL(BONITO_INTENCLR); - switch (sys_config.system_type) { - case LOONGSON_YEELOONG: + if (bc->bc_legacy_pic) { 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_ISA, CR_INT_0, loongson_isa_intr); + loongson_isaimr = loongson_get_isa_imr(); + register_splx_handler(loongson_isa_splx); + } else { 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. - */ - - ioex = extent_create("pciio", 0, 0xffffffff, M_DEVBUF, NULL, 0, - EX_NOWAIT | EX_FILLED); - if (ioex != NULL) - (void)extent_free(ioex, 0, BONITO_PCIIO_SIZE, EX_NOWAIT); - - memex = extent_create("pcimem", 0, 0xffffffff, M_DEVBUF, NULL, 0, - EX_NOWAIT | EX_FILLED); - if (memex != NULL) { - reg = REGVAL(BONITO_PCIMAP); - (void)extent_free(memex, BONITO_PCIMAP_WINBASE((reg & - BONITO_PCIMAP_PCIMAP_LO0) >> BONITO_PCIMAP_PCIMAP_LO0_SHIFT), - BONITO_PCIMAP_WINSIZE, EX_NOWAIT); - (void)extent_free(memex, BONITO_PCIMAP_WINBASE((reg & - BONITO_PCIMAP_PCIMAP_LO1) >> BONITO_PCIMAP_PCIMAP_LO1_SHIFT), - BONITO_PCIMAP_WINSIZE, EX_NOWAIT); - (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 */ - } } /* @@ -359,8 +355,10 @@ bonito_attach(struct device *parent, struct device *self, void *aux) pba.pba_pc = pc; pba.pba_domain = pci_ndomains++; pba.pba_bus = 0; - pba.pba_ioex = ioex; - pba.pba_memex = memex; +#ifdef notyet + pba.pba_ioex = bonito_get_resource_extent(pc, 1); + pba.pba_memex = bonito_get_resource_extent(pc, 0); +#endif config_found(&sc->sc_dev, &pba, bonito_print); } @@ -443,8 +441,7 @@ bonito_intr_disestablish(void *ih) } /* - * Update interrupt masks. Two set of routines: one when ISA interrupts - * are involved, one without. + * Update interrupt masks. This is for designs without legacy PIC. */ void @@ -463,21 +460,6 @@ bonito_splx(int newipl) } 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; @@ -500,30 +482,6 @@ bonito_setintrmask(int level) 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. */ @@ -576,7 +534,7 @@ bonito_intr_makemasks() } /* - * Process direct interrupts + * Process native interrupts */ uint32_t @@ -660,101 +618,6 @@ done: } /* - * Process ISA interrupts. - * - * 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... - */ - -/* - * Interrupt dispatcher. - */ -uint32_t -bonito_isa_intr(uint32_t hwpend, struct trap_frame *frame) -{ - uint64_t imr, isr, mask; - int bit; - struct intrhand *ih; - int rc; - - isr = bonito_get_isa_isr(); - imr = bonito_get_isa_imr(); - - isr &= imr; - isr &= ~(1 << 2); /* cascade */ -#ifdef DEBUG - printf("isa interrupt: imr %04x isr %04x\n", imr, isr); -#endif - if (isr == 0) - return 0; /* not for us */ - - /* - * Mask all pending interrupts. - */ - - bonito_set_isa_imr(imr & ~isr); - - /* - * If interrupts are spl-masked, mask them and wait for splx() - * to reenable them when necessary. - */ - if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) { - isr &= ~mask; - imr &= ~mask; - } - - /* - * Now process allowed interrupts. - */ - if (isr != 0) { - int lvl, bitno; - uint64_t tmpisr; - - /* Service higher level interrupts first */ - bit = BONITO_NISA - 1; - for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) { - tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^ - bonito_imask[lvl - 1]); - if (tmpisr == 0) - continue; - for (bitno = bit, mask = 1UL << bitno; mask != 0; - bitno--, mask >>= 1) { - if ((tmpisr & mask) == 0) - continue; - - rc = 0; - for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)]; - ih != NULL; ih = ih->ih_next) { - if ((*ih->ih_fun)(ih->ih_arg) != 0) { - rc = 1; - ih->ih_count.ec_count++; - } - } - if (rc == 0) - printf("spurious isa interrupt %d\n", - bitno); - - bonito_isa_specific_eoi(bitno); - - if ((isr ^= mask) == 0) - goto done; - if ((tmpisr ^= mask) == 0) - break; - } - } -done: - - /* - * Reenable interrupts which have been serviced. - */ - bonito_set_isa_imr(imr); - } - - return hwpend; -} - -/* * various PCI helpers */ @@ -1018,11 +881,108 @@ bonito_pci_intr_disestablish(void *cookie, void *ihp) } /* - * ISA Interrupt handling + * Legacy (ISA) interrupt handling */ +/* + * Process legacy interrupts. + * + * 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... + */ + +/* + * Interrupt dispatcher. + */ +uint32_t +loongson_isa_intr(uint32_t hwpend, struct trap_frame *frame) +{ + uint64_t imr, isr, mask; + int bit; + struct intrhand *ih; + int rc; + + isr = loongson_get_isa_isr(); + imr = loongson_get_isa_imr(); + + isr &= imr; + isr &= ~(1 << 2); /* cascade */ +#ifdef DEBUG + printf("isa interrupt: imr %04x isr %04x\n", imr, isr); +#endif + if (isr == 0) + return 0; /* not for us */ + + /* + * Mask all pending interrupts. + */ + + loongson_set_isa_imr(imr & ~isr); + + /* + * If interrupts are spl-masked, mask them and wait for splx() + * to reenable them when necessary. + */ + if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) { + isr &= ~mask; + imr &= ~mask; + } + + /* + * Now process allowed interrupts. + */ + if (isr != 0) { + int lvl, bitno; + uint64_t tmpisr; + + /* Service higher level interrupts first */ + bit = BONITO_NISA - 1; + for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) { + tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^ + bonito_imask[lvl - 1]); + if (tmpisr == 0) + continue; + for (bitno = bit, mask = 1UL << bitno; mask != 0; + bitno--, mask >>= 1) { + if ((tmpisr & mask) == 0) + continue; + + rc = 0; + for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)]; + ih != NULL; ih = ih->ih_next) { + if ((*ih->ih_fun)(ih->ih_arg) != 0) { + rc = 1; + ih->ih_count.ec_count++; + } + } + if (rc == 0) + printf("spurious isa interrupt %d\n", + bitno); + + loongson_isa_specific_eoi(bitno); + + if ((isr ^= mask) == 0) + goto done; + if ((tmpisr ^= mask) == 0) + break; + } + } +done: + + /* + * Reenable interrupts which have been serviced. + */ + loongson_set_isa_imr(imr); + } + + return hwpend; +} + +#define REGVAL8(x) *((volatile u_int8_t *)PHYS_TO_XKPHYS(x, CCA_NC)) + uint -bonito_get_isa_imr() +loongson_get_isa_imr() { uint imr1, imr2; @@ -1034,7 +994,7 @@ bonito_get_isa_imr() } uint -bonito_get_isa_isr() +loongson_get_isa_isr() { uint isr1, isr2; @@ -1045,7 +1005,7 @@ bonito_get_isa_isr() } void -bonito_set_isa_imr(uint newimr) +loongson_set_isa_imr(uint newimr) { uint imr1, imr2; @@ -1059,19 +1019,19 @@ bonito_set_isa_imr(uint newimr) * this if the value changes. * Note that interrupts have been disabled by the caller. */ - if ((newimr ^ bonito_isaimr) & 0xff00) { + if ((newimr ^ loongson_isaimr) & 0xff00) { REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1) = imr2; (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1); } - if ((newimr ^ bonito_isaimr) & 0x00ff) { + if ((newimr ^ loongson_isaimr) & 0x00ff) { REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1) = imr1; (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1); } - bonito_isaimr = newimr; + loongson_isaimr = newimr; } void -bonito_isa_specific_eoi(int bit) +loongson_isa_specific_eoi(int bit) { if (bit & 8) { REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 0) = 0x60 | (bit & 7); @@ -1082,6 +1042,49 @@ bonito_isa_specific_eoi(int bit) (void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 0); } +/* + * Update interrupt masks. This is for designs with legacy PIC. + */ + +void +loongson_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"); + loongson_isa_setintrmask(newipl); + /* If we still have softints pending trigger processing. */ + if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT) + setsoftintr0(); +} + +void +loongson_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); + + loongson_set_isa_imr(BONITO_ISA_MASK(active)); + + setsr(sr); +} + void isa_attach_hook(struct device *parent, struct device *self, struct isabus_attach_args *iba) @@ -1103,6 +1106,107 @@ isa_intr_disestablish(void *v, void *ih) } /* + * Legacy I/O access protection. + * Since MI ISA code does not expect bus access to cause any failure when + * accessing missing hardware, but only receive bogus data in return, we + * force bus_space_map() to fail if there is no hardware there. + */ + +int +bonito_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; + + if (offs < BONITO_PCIIO_LEGACY) { + size--; + for (r = sys_platform->legacy_io_ranges; r->start != 0; r++) + if (offs >= r->start && offs + size <= r->end) + break; + + if (r->start == 0) + return ENXIO; + } + + *bshp = t->bus_base + offs; + return 0; +} + +/* + * PCI resource handling + */ + +struct extent * +bonito_get_resource_extent(pci_chipset_tag_t pc, int io) +{ + struct bonito_softc *sc = pc->pc_conf_v; + struct extent *ex; + char *exname; + size_t exnamesz; + uint32_t reg; + int errors; + + exnamesz = 1 + 16 + 4; + exname = (char *)malloc(exnamesz, M_DEVBUF, M_NOWAIT); + if (exname == NULL) + return NULL; + snprintf(exname, exnamesz, "%s%s", sc->sc_dev.dv_xname, + io ? "_io" : "_mem"); + + ex = extent_create(exname, 0, 0xffffffff, M_DEVBUF, NULL, 0, + EX_NOWAIT | EX_FILLED); + if (ex == NULL) + goto out; + + errors = 0; + if (io) { + /* + * Reserve the low 16KB of I/O space to the legacy hardware, + * if any. + */ + if (extent_free(ex, BONITO_PCIIO_LEGACY, BONITO_PCIIO_SIZE, + EX_NOWAIT) != 0) + errors++; + } else { + reg = REGVAL(BONITO_PCIMAP); + if (extent_free(ex, + BONITO_PCIMAP_WINBASE((reg & BONITO_PCIMAP_PCIMAP_LO0) >> + BONITO_PCIMAP_PCIMAP_LO0_SHIFT), + BONITO_PCIMAP_WINSIZE, EX_NOWAIT) != 0) + errors++; + if (extent_free(ex, + BONITO_PCIMAP_WINBASE((reg & BONITO_PCIMAP_PCIMAP_LO1) >> + BONITO_PCIMAP_PCIMAP_LO1_SHIFT), + BONITO_PCIMAP_WINSIZE, EX_NOWAIT) != 0) + errors++; + if (extent_free(ex, + BONITO_PCIMAP_WINBASE((reg & BONITO_PCIMAP_PCIMAP_LO2) >> + BONITO_PCIMAP_PCIMAP_LO2_SHIFT), + BONITO_PCIMAP_WINSIZE, EX_NOWAIT) != 0) + errors++; + + if (sc->sc_compatible) { + /* XXX make PCIMAP_HI available if PCIMAP_2 set */ + } + } + + if (errors != 0) { + extent_destroy(ex); + ex = NULL; + } + +#ifdef BONITO_DEBUG + extent_print(ex); +#endif + +out: + if (exname != NULL) + free(exname, M_DEVBUF); + + return ex; +} + +/* * Functions used during early system configuration (before bonito attaches). */ @@ -1115,5 +1219,5 @@ pci_make_tag_early(int b, int d, int f) pcireg_t pci_conf_read_early(pcitag_t tag, int reg) { - return bonito_conf_read_internal(sys_config.sys_bc, tag, reg); + return bonito_conf_read_internal(sys_platform->bonito_config, tag, reg); } diff --git a/sys/arch/loongson/dev/bonitoreg.h b/sys/arch/loongson/dev/bonitoreg.h index 23b5097cc18..99c3f7f0ed2 100644 --- a/sys/arch/loongson/dev/bonitoreg.h +++ b/sys/arch/loongson/dev/bonitoreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bonitoreg.h,v 1.3 2010/02/05 20:51:22 miod Exp $ */ +/* $OpenBSD: bonitoreg.h,v 1.4 2010/02/12 08:14:02 miod Exp $ */ /* $NetBSD: bonitoreg.h,v 1.6 2005/12/24 20:07:19 perry Exp $ */ /* @@ -55,6 +55,7 @@ #define BONITO_PCIHI_SIZE 0x20000000 #define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1) #define BONITO_PCIIO_BASE 0x1fd00000 +#define BONITO_PCIIO_LEGACY 0x00004000 #define BONITO_PCIIO_SIZE 0x00100000 #define BONITO_PCIIO_TOP (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1) #define BONITO_PCICFG_BASE 0x1fe80000 diff --git a/sys/arch/loongson/dev/bonitovar.h b/sys/arch/loongson/dev/bonitovar.h index 400d8ccfcc8..1d181be1c77 100644 --- a/sys/arch/loongson/dev/bonitovar.h +++ b/sys/arch/loongson/dev/bonitovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bonitovar.h,v 1.3 2010/02/09 21:31:46 miod Exp $ */ +/* $OpenBSD: bonitovar.h,v 1.4 2010/02/12 08:14:02 miod Exp $ */ /* $NetBSD: bonitovar.h,v 1.4 2008/04/28 20:23:28 martin Exp $ */ /*- @@ -36,6 +36,7 @@ #include <dev/pci/pcivar.h> struct bonito_cfg_hook; +struct extent; struct bonito_config { int bc_adbase; /* AD line base for config access */ @@ -46,6 +47,8 @@ struct bonito_config { uint32_t bc_intSteer; uint32_t bc_intPol; + int bc_legacy_pic; /* nonzero if legacy PIC */ + /* PCI Attach hook for the first bus */ void (*bc_attach_hook)(pci_chipset_tag_t); @@ -55,6 +58,7 @@ struct bonito_config { struct bonito_softc { struct device sc_dev; + int sc_compatible; /* real Bonito hw */ const struct bonito_config *sc_bonito; struct mips_pci_chipset sc_pc; @@ -70,6 +74,8 @@ int bonito_pci_hook(pci_chipset_tag_t, void *, int (*)(void *, pci_chipset_tag_t, pcitag_t, int, pcireg_t *), int (*)(void *, pci_chipset_tag_t, pcitag_t, int, pcireg_t)); int bonito_print(void *, const char *); +struct extent + *bonito_get_resource_extent(pci_chipset_tag_t, int); #endif /* _KERNEL */ #endif /* _LOONGSON_DEV_BONITOVAR_H_ */ diff --git a/sys/arch/loongson/include/autoconf.h b/sys/arch/loongson/include/autoconf.h index ae1fe1e7d43..93a91e7d303 100644 --- a/sys/arch/loongson/include/autoconf.h +++ b/sys/arch/loongson/include/autoconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.h,v 1.3 2010/02/05 20:51:22 miod Exp $ */ +/* $OpenBSD: autoconf.h,v 1.4 2010/02/12 08:14:02 miod Exp $ */ /* * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -38,24 +38,33 @@ struct bonito_config; /* - * Structure holding all misc config information. + * List of legacy I/O ranges. */ -struct sys_rec { - int system_type; +struct legacy_io_range { + bus_addr_t start; + bus_size_t end; /* inclusive */ +}; + +/* + * Per platform information. + */ +struct platform { + int system_type; + char *vendor; + char *product; + + const struct bonito_config *bonito_config; + const struct legacy_io_range *legacy_io_ranges; - /* Bonito configuration */ - const struct bonito_config *sys_bc; + void (*powerdown)(void); }; -extern struct sys_rec sys_config; +extern const struct platform *sys_platform; 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 index dfd1355def7..84a5fdd4245 100644 --- a/sys/arch/loongson/loongson/gdium_machdep.c +++ b/sys/arch/loongson/loongson/gdium_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gdium_machdep.c,v 1.2 2010/02/09 21:31:47 miod Exp $ */ +/* $OpenBSD: gdium_machdep.c,v 1.3 2010/02/12 08:14:02 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -24,11 +24,13 @@ #include <sys/systm.h> #include <sys/device.h> +#include <mips64/archtype.h> #include <machine/autoconf.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> +#include <loongson/dev/bonitoreg.h> #include <loongson/dev/bonitovar.h> #include <loongson/dev/bonito_irq.h> @@ -36,6 +38,7 @@ int gdium_revision = 0; void gdium_attach_hook(pci_chipset_tag_t); int gdium_intr_map(int, int, int); +void gdium_powerdown(void); const struct bonito_config gdium_bonito = { .bc_adbase = 11, @@ -47,52 +50,76 @@ const struct bonito_config gdium_bonito = { .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR | LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR, + .bc_legacy_pic = 0, + .bc_attach_hook = gdium_attach_hook, .bc_intr_map = gdium_intr_map }; +const struct platform gdium_platform = { + .system_type = LOONGSON_GDIUM, + .vendor = "EMTEC", + .product = "Gdium", + + .bonito_config = &gdium_bonito, + .legacy_io_ranges = NULL, + + .powerdown = gdium_powerdown +}; + void gdium_attach_hook(pci_chipset_tag_t pc) { pcireg_t id; pcitag_t tag; +#ifdef notyet int bar; +#endif #if 0 pcireg_t reg; int dev, func; #endif +#ifdef notyet /* * Clear all BAR of the mini PCI slot; PMON did not initialize * it, and we do not want it to conflict with anything. */ - tag = pci_make_tag(pc, 0, 13, 0); for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4) pci_conf_write(pc, tag, bar, 0); +#else + /* + * Force a non conflicting BAR for the wireless controller, + * until proper resource configuration code is added to + * bonito (work in progress). + * XXX The card does not work correctly anyway at the moment. + */ + tag = pci_make_tag(pc, 0, 13, 0); + pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000); +#endif /* * Figure out which motherboard we are running on. * Might not be good enough... */ - tag = pci_make_tag(pc, 0, 17, 0); id = pci_conf_read(pc, tag, PCI_ID_REG); if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB)) gdium_revision = 1; -#if 0 /* XXX Linux does this... but this causes enumeration to fail */ +#if 0 /* * Tweak the usb controller capabilities. */ - for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) { tag = pci_make_tag(pc, 0, dev, 0); id = pci_conf_read(pc, tag, PCI_ID_REG); if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB)) continue; - if (gdium_revision == 0) { + if (gdium_revision != 0) { reg = pci_conf_read(pc, tag, 0xe0); + /* enable ports 1 and 2 */ reg |= 0x00000003; pci_conf_write(pc, tag, 0xe0, reg); } else { @@ -105,16 +132,12 @@ gdium_attach_hook(pci_chipset_tag_t pc) PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2) continue; - /* 0114331f -> 0114331d */ reg = pci_conf_read(pc, tag, 0xe0); + /* enable ports 1 and 3, disable port 2 */ reg &= ~0x00000007; reg |= 0x00000005; pci_conf_write(pc, tag, 0xe0, reg); - - /* 00006c42 -> 00006c62 */ - reg = pci_conf_read(pc, tag, 0xe4); - reg |= 0x00000020; - pci_conf_write(pc, tag, 0xe4, reg); + pci_conf_write(pc, tag, 0xe4, 0x00000020); } } } @@ -153,3 +176,10 @@ gdium_intr_map(int dev, int fn, int pin) return -1; } + +void +gdium_powerdown() +{ + REGVAL(BONITO_GPIODATA) |= 0x00000002; + REGVAL(BONITO_GPIOIE) &= ~0x00000002; +} diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c index cb2363a1170..892a64aca88 100644 --- a/sys/arch/loongson/loongson/machdep.c +++ b/sys/arch/loongson/loongson/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.11 2010/02/09 21:30:11 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.12 2010/02/12 08:14:02 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -108,7 +108,7 @@ int ncpu = 1; /* At least one CPU in the system. */ struct user *proc0paddr; int kbd_reset; -struct sys_rec sys_config; +const struct platform *sys_platform; struct cpu_hwinfo bootcpu_hwinfo; /* Pointers to the start and end of the symbol table. */ @@ -150,18 +150,23 @@ struct consdev pmoncons = { struct bonito_flavour { const char *prefix; - int systype; - const struct bonito_config *bc; + const struct platform *platform; }; +extern const struct platform fuloong_platform; +extern const struct platform gdium_platform; +extern const struct platform yeeloong_platform; + 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 }, + /* Lemote Fuloong 2F mini-PC */ + { "LM6004", &fuloong_platform }, /* EMTEC Gdium Liberty 1000 */ - { "Gdium", LOONGSON_GDIUM, &gdium_bonito }, + { "Gdium", &gdium_platform }, + /* Lemote Yeeloong 8.9" netbook */ + { "LM8089", &yeeloong_platform }, + /* supposedly Lemote Yeeloong 10.1" netbook, but those found so far + report themselves as LM8089 */ + { "LM8101", &yeeloong_platform }, { NULL } }; @@ -267,30 +272,18 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv) 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; + sys_platform = f->platform; break; } - if (sys_config.system_type == 0) { + if (sys_platform == NULL) { pmon_printf("This kernel doesn't support model \"%s\".\n", envvar); goto unsupported; } - switch (sys_config.system_type) { - case LOONGSON_YEELOONG: - hw_vendor = "Lemote"; - hw_prod = "Yeeloong"; - break; - case LOONGSON_GDIUM: - hw_vendor = "EMTEC"; - hw_prod = "Gdium"; - break; - default: /* won't happen */ - goto unsupported; - } - + hw_vendor = sys_platform->vendor; + hw_prod = sys_platform->product; pmon_printf("Found %s %s, setting up.\n", hw_vendor, hw_prod); snprintf(cpu_model, sizeof cpu_model, "Loongson %X", loongson_ver); @@ -424,8 +417,6 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv) /* * Configure cache. - * Note that the caches being physically tagged, there is no - * need to invalidate or flush it. */ Loongson2_ConfigCache(curcpu()); @@ -823,18 +814,12 @@ haltsys: if (howto & RB_HALT) { if (howto & RB_POWERDOWN) { - printf("System Power Down.\n"); - 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; + if (sys_platform->powerdown != NULL) { + printf("System Power Down.\n"); + (*(sys_platform->powerdown))(); + } else { + printf("System Power Down not supported," + " halting system.\n"); } } else printf("System Halt.\n"); diff --git a/sys/arch/loongson/loongson/wscons_machdep.c b/sys/arch/loongson/loongson/wscons_machdep.c index 50b3a613748..a8187830b92 100644 --- a/sys/arch/loongson/loongson/wscons_machdep.c +++ b/sys/arch/loongson/loongson/wscons_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_machdep.c,v 1.3 2010/02/11 20:15:29 otto Exp $ */ +/* $OpenBSD: wscons_machdep.c,v 1.4 2010/02/12 08:14:02 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -157,7 +157,7 @@ setup_kbd: rc = ENXIO; #if NPCKBC > 0 - switch (sys_config.system_type) { + switch (sys_platform->system_type) { default: /* no pckbc or no legacy hardware */ break; diff --git a/sys/arch/loongson/loongson/yeeloong_machdep.c b/sys/arch/loongson/loongson/yeeloong_machdep.c index b70383a63bb..786eb58593d 100644 --- a/sys/arch/loongson/loongson/yeeloong_machdep.c +++ b/sys/arch/loongson/loongson/yeeloong_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: yeeloong_machdep.c,v 1.2 2010/02/09 21:31:47 miod Exp $ */ +/* $OpenBSD: yeeloong_machdep.c,v 1.3 2010/02/12 08:14:02 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -17,18 +17,22 @@ */ /* - * Lemote Yeeloong specific code and configuration data. + * Lemote Fuloong 2F and Yeeloong specific 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 <dev/isa/isareg.h> + #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> +#include <loongson/dev/bonitoreg.h> #include <loongson/dev/bonitovar.h> #include <loongson/dev/bonito_irq.h> #include <loongson/dev/glxvar.h> @@ -36,6 +40,8 @@ void yeeloong_attach_hook(pci_chipset_tag_t); int yeeloong_intr_map(int, int, int); +void yeeloong_powerdown(void); + const struct bonito_config yeeloong_bonito = { .bc_adbase = 11, @@ -47,10 +53,67 @@ const struct bonito_config yeeloong_bonito = { LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR | LOONGSON_INTRMASK_INT0 | LOONGSON_INTRMASK_INT1, + .bc_legacy_pic = 1, + .bc_attach_hook = yeeloong_attach_hook, .bc_intr_map = yeeloong_intr_map }; +const struct legacy_io_range fuloong_legacy_ranges[] = { + /* isa */ + { IO_DMAPG + 4, IO_DMAPG + 4 }, + /* mcclock */ + { IO_RTC, IO_RTC + 1 }, + /* pciide */ + { 0x170, 0x170 + 7 }, + { 0x1f0, 0x1f0 + 7 }, + { 0x376, 0x376 }, + { 0x3f6, 0x3f6 }, + /* com */ + { IO_COM2, IO_COM2 + 8 }, + + { 0 } +}; + +const struct legacy_io_range yeeloong_legacy_ranges[] = { + /* isa */ + { IO_DMAPG + 4, IO_DMAPG + 4 }, + /* pckbc */ + { IO_KBD, IO_KBD }, + { IO_KBD + 4, IO_KBD + 4 }, + /* mcclock */ + { IO_RTC, IO_RTC + 1 }, + /* pciide */ + { 0x170, 0x170 + 7 }, + { 0x1f0, 0x1f0 + 7 }, + { 0x376, 0x376 }, + { 0x3f6, 0x3f6 }, + + { 0 } +}; + +const struct platform fuloong_platform = { + .system_type = LOONGSON_FULOONG, + .vendor = "Lemote", + .product = "Fuloong", + + .bonito_config = &yeeloong_bonito, + .legacy_io_ranges = fuloong_legacy_ranges, + + .powerdown = NULL /* XXX TBD */ +}; + +const struct platform yeeloong_platform = { + .system_type = LOONGSON_YEELOONG, + .vendor = "Lemote", + .product = "Yeeloong", + + .bonito_config = &yeeloong_bonito, + .legacy_io_ranges = yeeloong_legacy_ranges, + + .powerdown = yeeloong_powerdown +}; + void yeeloong_attach_hook(pci_chipset_tag_t pc) { @@ -96,7 +159,7 @@ yeeloong_intr_map(int dev, int fn, int pin) switch (fn) { case 1: /* Flash */ return BONITO_ISA_IRQ(6); - case 2: /* AC97 */ + case 3: /* AC97 */ return BONITO_ISA_IRQ(9); case 4: /* OHCI */ case 5: /* EHCI */ @@ -109,3 +172,10 @@ yeeloong_intr_map(int dev, int fn, int pin) return -1; } + +void +yeeloong_powerdown() +{ + REGVAL(BONITO_GPIODATA) &= ~0x00000001; + REGVAL(BONITO_GPIOIE) &= ~0x00000001; +} |