diff --git a/sys/arch/arm/xscale/becc.c b/sys/arch/arm/xscale/becc.c new file mode 100644 index 000000000000..037fda2910cf --- /dev/null +++ b/sys/arch/arm/xscale/becc.c @@ -0,0 +1,297 @@ +/* $NetBSD: becc.c,v 1.1 2003/01/25 01:57:17 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Autoconfiguration support for the ADI Engineering Big Endian + * Companion Chip. + */ + +#include +#include +#include + +#define _ARM32_BUS_DMA_PRIVATE +#include + +#include +#include +#include + +/* + * Virtual address at which the BECC is mapped. This is filled in + * by machine-dependent code. + */ +vaddr_t becc_vaddr; + +/* + * BECC revision number. This is initialized by early bootstrap code. + */ +int becc_rev; +const char *becc_revisions[] = { + "<= 7", + "8", + ">= 9", +}; + +/* + * There can be only one BECC, so we keep a global pointer to + * the softc, so board-specific code can use features of the + * BECC without having to have a handle on the softc itself. + */ +struct becc_softc *becc_softc; + +static int becc_pcibus_print(void *, const char *); + +static void becc_pci_dma_init(struct becc_softc *); + +/* + * becc_attach: + * + * Board-independent attach routine for the BECC. + */ +void +becc_attach(struct becc_softc *sc) +{ + struct pcibus_attach_args pba; + uint32_t reg; + + becc_softc = sc; + + /* + * Set the AF bit in the BCUMOD since the BECC will honor it. + * This allows the BECC to return the requested 4-byte word + * first when filling a cache line. + */ + __asm __volatile("mrc p13, 0, %0, c1, c1, 0" : "=r" (reg) ); + __asm __volatile("mcr p13, 0, %0, c1, c1, 0" : : "r" (reg | BCUMOD_AF)); + + /* + * Program the address windows of the PCI core. Note + * that PCI master and target cycles must be disabled + * while we configure the windows. + */ + reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); + reg &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE); + becc_pcicore_write(sc, PCI_COMMAND_STATUS_REG, reg); + + /* + * Program the two inbound PCI memory windows. + */ + becc_pcicore_write(sc, PCI_MAPREG_START + 0, + sc->sc_iwin[0].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | + PCI_MAPREG_MEM_PREFETCHABLE_MASK); + reg = becc_pcicore_read(sc, PCI_MAPREG_START + 0); + BECC_CSR_WRITE(BECC_PSTR0, sc->sc_iwin[0].iwin_xlate & PSTRx_ADDRMASK); + + becc_pcicore_write(sc, PCI_MAPREG_START + 4, + sc->sc_iwin[1].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | + PCI_MAPREG_MEM_PREFETCHABLE_MASK); + reg = becc_pcicore_read(sc, PCI_MAPREG_START + 4); + BECC_CSR_WRITE(BECC_PSTR1, sc->sc_iwin[1].iwin_xlate & PSTRx_ADDRMASK); + + /* + * ...and the third on v8 and later. + */ + if (becc_rev >= BECC_REV_V8) { + becc_pcicore_write(sc, PCI_MAPREG_START + 8, + sc->sc_iwin[2].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | + PCI_MAPREG_MEM_PREFETCHABLE_MASK); + reg = becc_pcicore_read(sc, PCI_MAPREG_START + 8); + BECC_CSR_WRITE(BECC_PSTR1, + sc->sc_iwin[2].iwin_xlate & PSTR2_ADDRMASK); + } + + /* + * Program the two outbound PCI memory windows. On a + * big-endian system, we byte-swap the first window. + * The second window is used for STREAM transfers. + * + * There's a third window on v9 and later, but we don't + * use it for anything; program it anyway, just to be + * safe. + */ +#ifdef __ARMEB__ + BECC_CSR_WRITE(BECC_POMR1, sc->sc_owin_xlate[0] /* | POMRx_F32 */ | + POMRx_BEE); +#else + BECC_CSR_WRITE(BECC_POMR1, sc->sc_owin_xlate[0] /* | POMRx_F32 */); +#endif + BECC_CSR_WRITE(BECC_POMR2, sc->sc_owin_xlate[1] /* | POMRx_F32 */); + + if (becc_rev >= BECC_REV_V9) + BECC_CSR_WRITE(BECC_POMR3, + sc->sc_owin_xlate[2] /* | POMRx_F32 */); + + /* + * Program the PCI I/O window. On a big-endian system, + * we do byte-swapping. + * + * XXX What about STREAM transfers? + */ +#ifdef __ARMEB__ + BECC_CSR_WRITE(BECC_POIR, sc->sc_ioout_xlate | POIR_BEE); +#else + BECC_CSR_WRITE(BECC_POIR, sc->sc_ioout_xlate); +#endif + + /* + * Configure PCI configuration cycle access. + */ + BECC_CSR_WRITE(BECC_POCR, 0); + + /* + * ...and now reenable PCI access. + */ + reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); + reg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | + PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; + becc_pcicore_write(sc, PCI_COMMAND_STATUS_REG, reg); + + /* Initialize the bus space tags. */ + becc_io_bs_init(&sc->sc_pci_iot, sc); + becc_mem_bs_init(&sc->sc_pci_memt, sc); + + /* Initialize the PCI chipset tag. */ + becc_pci_init(&sc->sc_pci_chipset, sc); + + /* Initialize the DMA tags. */ + becc_pci_dma_init(sc); + + /* + * Attach the PCI bus. + */ + pba.pba_busname = "pci"; + pba.pba_iot = &sc->sc_pci_iot; + pba.pba_memt = &sc->sc_pci_memt; + pba.pba_dmat = &sc->sc_pci_dmat; + pba.pba_pc = &sc->sc_pci_chipset; + pba.pba_bus = 0; + pba.pba_bridgetag = NULL; + pba.pba_intrswiz = 0; + pba.pba_intrtag = 0; + pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | + PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; + (void) config_found(&sc->sc_dev, &pba, becc_pcibus_print); +} + +/* + * becc_pcibus_print: + * + * Autoconfiguration cfprint routine when attaching + * to the "pcibus" attribute. + */ +static int +becc_pcibus_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); +} + +/* + * becc_pci_dma_init: + * + * Initialize the PCI DMA tag. + */ +static void +becc_pci_dma_init(struct becc_softc *sc) +{ + bus_dma_tag_t dmat = &sc->sc_pci_dmat; + struct arm32_dma_range *dr = sc->sc_pci_dma_range; + int i = 0; + + /* + * If we have the 128MB window, put it first, since it + * will always cover the entire memory range. + */ + if (becc_rev >= BECC_REV_V8) { + dr[i].dr_sysbase = sc->sc_iwin[2].iwin_xlate; + dr[i].dr_busbase = sc->sc_iwin[2].iwin_base; + dr[i].dr_len = (128U * 1024 * 1024); + i++; + } + + dr[i].dr_sysbase = sc->sc_iwin[0].iwin_xlate; + dr[i].dr_busbase = sc->sc_iwin[0].iwin_base; + dr[i].dr_len = (32U * 1024 * 1024); + i++; + + dr[i].dr_sysbase = sc->sc_iwin[1].iwin_xlate; + dr[i].dr_busbase = sc->sc_iwin[1].iwin_base; + dr[i].dr_len = (32U * 1024 * 1024); + i++; + + dmat->_ranges = dr; + dmat->_nranges = i; + + dmat->_dmamap_create = _bus_dmamap_create; + dmat->_dmamap_destroy = _bus_dmamap_destroy; + dmat->_dmamap_load = _bus_dmamap_load; + dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; + dmat->_dmamap_load_uio = _bus_dmamap_load_uio; + dmat->_dmamap_load_raw = _bus_dmamap_load_raw; + dmat->_dmamap_unload = _bus_dmamap_unload; + dmat->_dmamap_sync_pre = _bus_dmamap_sync; + dmat->_dmamap_sync_post = NULL; + + dmat->_dmamem_alloc = _bus_dmamem_alloc; + dmat->_dmamem_free = _bus_dmamem_free; + dmat->_dmamem_map = _bus_dmamem_map; + dmat->_dmamem_unmap = _bus_dmamem_unmap; + dmat->_dmamem_mmap = _bus_dmamem_mmap; +} + +uint32_t +becc_pcicore_read(struct becc_softc *sc, bus_addr_t reg) +{ + vaddr_t va = sc->sc_pci_cfg_base | (1U << BECC_IDSEL_BIT) | reg; + + return (*(__volatile uint32_t *) va); +} + +void +becc_pcicore_write(struct becc_softc *sc, bus_addr_t reg, uint32_t val) +{ + vaddr_t va = sc->sc_pci_cfg_base | (1U << BECC_IDSEL_BIT) | reg; + + *(__volatile uint32_t *) va = val; +} diff --git a/sys/arch/arm/xscale/becc_csrvar.h b/sys/arch/arm/xscale/becc_csrvar.h new file mode 100644 index 000000000000..0bd04d5d6258 --- /dev/null +++ b/sys/arch/arm/xscale/becc_csrvar.h @@ -0,0 +1,55 @@ +/* $NetBSD: becc_csrvar.h,v 1.1 2003/01/25 01:57:18 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BECC_CSRVAR_H_ +#define _BECC_CSRVAR_H_ + +/* + * Machine-dependent code maps the BECC quite early, and plops the + * virtual address of the BECC in this variable. + */ +extern vaddr_t becc_vaddr; + +/* + * Macros to read/write the BECC registers. + */ +#define BECC_CSR_READ(x) *(__volatile uint32_t *)(becc_vaddr + (x)) +#define BECC_CSR_WRITE(x, v) *(__volatile uint32_t *)(becc_vaddr + (x)) = (v) + +extern const char *becc_irqnames[]; + +#endif /* _BECC_CSRVAR_H_ */ diff --git a/sys/arch/arm/xscale/becc_icu.c b/sys/arch/arm/xscale/becc_icu.c new file mode 100644 index 000000000000..fd8bf16dc49f --- /dev/null +++ b/sys/arch/arm/xscale/becc_icu.c @@ -0,0 +1,508 @@ +/* $NetBSD: becc_icu.c,v 1.1 2003/01/25 01:57:18 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Interrupt support for the ADI Engineering Big Endian Companion Chip. + */ + +#ifndef EVBARM_SPL_NOINLINE +#define EVBARM_SPL_NOINLINE +#endif + +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +/* Interrupt handler queues. */ +struct intrq intrq[NIRQ]; + +/* Interrupts to mask at each level. */ +uint32_t becc_imask[NIPL]; + +/* Current interrupt priority level. */ +__volatile uint32_t current_spl_level; + +/* Interrupts pending. */ +__volatile uint32_t becc_ipending; +__volatile uint32_t becc_sipending; + +/* Software copy of the IRQs we have enabled. */ +__volatile uint32_t intr_enabled; + +/* Mask if interrupts steered to FIQs. */ +uint32_t intr_steer; + +/* + * Interrupt bit names. + * XXX Some of these are BRH-centric. + */ +const char *becc_irqnames[] = { + "soft", + "timer A", + "timer B", + "irq 3", + "irq 4", + "irq 5", + "irq 6", + "diagerr", + "DMA EOT", + "DMA PERR", + "DMA TABT", + "DMA MABT", + "irq 12", + "irq 13", + "irq 14", + "irq 15", + "PCI PERR", + "irq 17", + "irq 18", + "PCI SERR", + "PCI OAPE", + "PCI OATA", + "PCI OAMA", + "irq 23", + "irq 24", + "irq 25", + "irq 26", /* PCI INTA */ + "irq 27", /* PCI INTB */ + "irq 28", /* PCI INTC */ + "irq 29", /* PCI INTD */ + "pushbutton", + "irq 31", +}; + +void becc_intr_dispatch(struct clockframe *frame); + +static __inline uint32_t +becc_icsr_read(void) +{ + uint32_t icsr; + + icsr = BECC_CSR_READ(BECC_ICSR); + + /* + * The ICSR register shows bits that are active even if they are + * masked in ICMR, so we have to mask them off with the interrupts + * we consider enabled. + */ + return (icsr & intr_enabled); +} + +static __inline void +becc_set_intrsteer(void) +{ + + BECC_CSR_WRITE(BECC_ICSTR, intr_steer & ICU_VALID_MASK); + (void) BECC_CSR_READ(BECC_ICSTR); +} + +static __inline void +becc_enable_irq(int irq) +{ + + intr_enabled |= (1U << irq); + becc_set_intrmask(); +} + +static __inline void +becc_disable_irq(int irq) +{ + + intr_enabled &= ~(1U << irq); + becc_set_intrmask(); +} + +/* + * NOTE: This routine must be called with interrupts disabled in the CPSR. + */ +static void +becc_intr_calculate_masks(void) +{ + struct intrq *iq; + struct intrhand *ih; + int irq, ipl; + + /* First, figure out which IPLs each IRQ has. */ + for (irq = 0; irq < NIRQ; irq++) { + int levels = 0; + iq = &intrq[irq]; + becc_disable_irq(irq); + for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; + ih = TAILQ_NEXT(ih, ih_list)) + levels |= (1U << ih->ih_ipl); + iq->iq_levels = levels; + } + + /* Next, figure out which IRQs are used by each IPL. */ + for (ipl = 0; ipl < NIPL; ipl++) { + int irqs = 0; + for (irq = 0; irq < NIRQ; irq++) { + if (intrq[irq].iq_levels & (1U << ipl)) + irqs |= (1U << irq); + } + becc_imask[ipl] = irqs; + } + + becc_imask[IPL_NONE] = 0; + + /* + * Initialize the soft interrupt masks to block themselves. + * Note they all come in at the same physical IRQ. + */ + becc_imask[IPL_SOFT] = (1U << ICU_SOFT); + becc_imask[IPL_SOFTCLOCK] = (1U << ICU_SOFT); + becc_imask[IPL_SOFTNET] = (1U << ICU_SOFT); + becc_imask[IPL_SOFTSERIAL] = (1U << ICU_SOFT); + + /* + * splsoftclock() is the only interface that users of the + * generic software interrupt facility have to block their + * soft intrs, so splsoftclock() must also block IPL_SOFT. + */ + becc_imask[IPL_SOFTCLOCK] |= becc_imask[IPL_SOFT]; + + /* + * splsoftnet() must also block splsoftclock(), since we don't + * want timer-driven network events to occur while we're + * processing incoming packets. + */ + becc_imask[IPL_SOFTNET] |= becc_imask[IPL_SOFTCLOCK]; + + /* + * Enforce a heirarchy that gives "slow" device (or devices with + * limited input buffer space/"real-time" requirements) a better + * chance at not dropping data. + */ + becc_imask[IPL_BIO] |= becc_imask[IPL_SOFTNET]; + becc_imask[IPL_NET] |= becc_imask[IPL_BIO]; + becc_imask[IPL_SOFTSERIAL] |= becc_imask[IPL_NET]; + becc_imask[IPL_TTY] |= becc_imask[IPL_SOFTSERIAL]; + + /* + * splvm() blocks all interrupts that use the kernel memory + * allocation facilities. + */ + becc_imask[IPL_IMP] |= becc_imask[IPL_TTY]; + + /* + * Audio devices are not allowed to perform memory allocation + * in their interrupt routines, and they have fairly "real-time" + * requirements, so give them a high interrupt priority. + */ + becc_imask[IPL_AUDIO] |= becc_imask[IPL_IMP]; + + /* + * splclock() must block anything that uses the scheduler. + */ + becc_imask[IPL_CLOCK] |= becc_imask[IPL_AUDIO]; + + /* + * No separate statclock on the IQ80310. + */ + becc_imask[IPL_STATCLOCK] |= becc_imask[IPL_CLOCK]; + + /* + * splhigh() must block "everything". + */ + becc_imask[IPL_HIGH] |= becc_imask[IPL_STATCLOCK]; + + /* + * XXX We need serial drivers to run at the absolute highest priority + * in order to avoid overruns, so serial > high. + */ + becc_imask[IPL_SERIAL] |= becc_imask[IPL_HIGH]; + + /* + * Now compute which IRQs must be blocked when servicing any + * given IRQ. + */ + for (irq = 0; irq < NIRQ; irq++) { + int irqs = (1U << irq); + iq = &intrq[irq]; + if (TAILQ_FIRST(&iq->iq_list) != NULL) + becc_enable_irq(irq); + for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; + ih = TAILQ_NEXT(ih, ih_list)) + irqs |= becc_imask[ih->ih_ipl]; + iq->iq_mask = irqs; + } +} + +void +splx(int new) +{ + + becc_splx(new); +} + +int +_spllower(int ipl) +{ + + return (becc_spllower(ipl)); +} + +int +_splraise(int ipl) +{ + + return (becc_splraise(ipl)); +} + +void +_setsoftintr(int si) +{ + + becc_setsoftintr(si); +} + +static const int si_to_ipl[SI_NQUEUES] = { + IPL_SOFT, /* SI_SOFT */ + IPL_SOFTCLOCK, /* SI_SOFTCLOCK */ + IPL_SOFTNET, /* SI_SOFTNET */ + IPL_SOFTSERIAL, /* SI_SOFTSERIAL */ +}; + +int +becc_softint(void *arg) +{ + static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED; + uint32_t new, oldirqstate; + + /* Clear interrupt */ + BECC_CSR_WRITE(BECC_ICSR, 0); + + if (__cpu_simple_lock_try(&processing) == 0) + return 0; + + oldirqstate = disable_interrupts(I32_bit); + + new = current_spl_level; + +#define DO_SOFTINT(si) \ + if (becc_sipending & (1 << (si))) { \ + becc_sipending &= ~(1 << (si)); \ + current_spl_level |= becc_imask[si_to_ipl[(si)]]; \ + restore_interrupts(oldirqstate); \ + softintr_dispatch(si); \ + oldirqstate = disable_interrupts(I32_bit); \ + current_spl_level = new; \ + } + + DO_SOFTINT(SI_SOFTSERIAL); + DO_SOFTINT(SI_SOFTNET); + DO_SOFTINT(SI_SOFTCLOCK); + DO_SOFTINT(SI_SOFT); + + __cpu_simple_unlock(&processing); + + restore_interrupts(oldirqstate); + + return 1; +} + +/* + * becc_icu_init: + * + * Initialize the BECC ICU. Called early in bootstrap + * to make sure the ICU is in a pristine state. + */ +void +becc_icu_init(void) +{ + + intr_enabled = 0; /* All interrupts disabled */ + becc_set_intrmask(); + + intr_steer = 0; /* All interrupts steered to IRQ */ + becc_set_intrsteer(); + + i80200_extirq_dispatch = becc_intr_dispatch; + + i80200_intr_enable(INTCTL_IM); +} + +/* + * becc_intr_init: + * + * Initialize the rest of the interrupt subsystem, making it + * ready to handle interrupts from devices. + */ +void +becc_intr_init(void) +{ + struct intrq *iq; + int i; + + intr_enabled = 0; + + for (i = 0; i < NIRQ; i++) { + iq = &intrq[i]; + TAILQ_INIT(&iq->iq_list); + + evcnt_attach_dynamic(&iq->iq_ev, EVCNT_TYPE_INTR, + NULL, "becc", becc_irqnames[i]); + } + + becc_intr_calculate_masks(); + + /* Enable IRQs (don't yet use FIQs). */ + enable_interrupts(I32_bit); +} + +void * +becc_intr_establish(int irq, int ipl, int (*func)(void *), void *arg) +{ + struct intrq *iq; + struct intrhand *ih; + uint32_t oldirqstate; + + if (irq < 0 || irq > NIRQ) + panic("becc_intr_establish: IRQ %d out of range", irq); + + ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); + if (ih == NULL) + return (NULL); + + ih->ih_func = func; + ih->ih_arg = arg; + ih->ih_ipl = ipl; + ih->ih_irq = irq; + + iq = &intrq[irq]; + + /* All BECC interrupts are level-triggered. */ + iq->iq_ist = IST_LEVEL; + + oldirqstate = disable_interrupts(I32_bit); + + TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list); + + becc_intr_calculate_masks(); + + restore_interrupts(oldirqstate); + + return (ih); +} + +void +becc_intr_disestablish(void *cookie) +{ + struct intrhand *ih = cookie; + struct intrq *iq = &intrq[ih->ih_irq]; + uint32_t oldirqstate; + + oldirqstate = disable_interrupts(I32_bit); + + TAILQ_REMOVE(&iq->iq_list, ih, ih_list); + + becc_intr_calculate_masks(); + + restore_interrupts(oldirqstate); +} + +void +becc_intr_dispatch(struct clockframe *frame) +{ + struct intrq *iq; + struct intrhand *ih; + uint32_t oldirqstate, pcpl, irq, ibit, hwpend; + + pcpl = current_spl_level; + + hwpend = becc_icsr_read(); + + /* + * Disable all the interrupts that are pending. We will + * reenable them once they are processed and not masked. + */ + intr_enabled &= ~hwpend; + becc_set_intrmask(); + + while (hwpend != 0) { + irq = ffs(hwpend) - 1; + ibit = (1U << irq); + + hwpend &= ~ibit; + + if (pcpl & ibit) { + /* + * IRQ is masked; mark it as pending and check + * the next one. Note: the IRQ is already disabled. + */ + becc_ipending |= ibit; + continue; + } + + becc_ipending &= ~ibit; + + iq = &intrq[irq]; + iq->iq_ev.ev_count++; + uvmexp.intrs++; + current_spl_level |= iq->iq_mask; + oldirqstate = enable_interrupts(I32_bit); + for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; + ih = TAILQ_NEXT(ih, ih_list)) { + (void) (*ih->ih_func)(ih->ih_arg ? ih->ih_arg : frame); + } + restore_interrupts(oldirqstate); + + current_spl_level = pcpl; + + /* Re-enable this interrupt now that's it's cleared. */ + intr_enabled |= ibit; + becc_set_intrmask(); + } + + if (becc_ipending & ~pcpl) { + intr_enabled |= (becc_ipending & ~pcpl); + becc_set_intrmask(); + } +} diff --git a/sys/arch/arm/xscale/becc_intr.h b/sys/arch/arm/xscale/becc_intr.h new file mode 100644 index 000000000000..3b5be3459afa --- /dev/null +++ b/sys/arch/arm/xscale/becc_intr.h @@ -0,0 +1,136 @@ +/* $NetBSD: becc_intr.h,v 1.1 2003/01/25 01:57:18 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BECC_INTR_H_ +#define _BECC_INTR_H_ + +#include +#include + +#include +#include + +static __inline void __attribute__((__unused__)) +becc_set_intrmask(void) +{ + extern __volatile uint32_t intr_enabled; + + /* + * The bits in the ICMR indicate which interrupts are masked + * (disabled), so we must invert our intr_enabled mask. + */ + + BECC_CSR_WRITE(BECC_ICMR, ~intr_enabled & ICU_VALID_MASK); + (void) BECC_CSR_READ(BECC_ICMR); +} + +static __inline int __attribute__((__unused__)) +becc_splraise(int ipl) +{ + extern __volatile uint32_t current_spl_level; + extern uint32_t becc_imask[]; + uint32_t old; + + old = current_spl_level; + current_spl_level |= becc_imask[ipl]; + + return (old); +} + +static __inline void __attribute__((__unused__)) +becc_splx(int new) +{ + extern __volatile uint32_t intr_enabled, becc_ipending; + extern __volatile uint32_t current_spl_level; + uint32_t oldirqstate, hwpend; + + current_spl_level = new; + + /* + * If there are pending HW interrupts which are being + * unmasked, then enable them in the ICMR register. + * This will cause them to come flooding in. This + * includes soft interrupts. + */ + hwpend = becc_ipending & ~new; + if (hwpend != 0) { + oldirqstate = disable_interrupts(I32_bit); + intr_enabled |= hwpend; + becc_set_intrmask(); + restore_interrupts(oldirqstate); + } +} + +static __inline int __attribute__((__unused__)) +becc_spllower(int ipl) +{ + extern __volatile uint32_t current_spl_level; + extern uint32_t becc_imask[]; + uint32_t old = current_spl_level; + + becc_splx(becc_imask[ipl]); + return (old); +} + +static __inline void __attribute__((__unused__)) +becc_setsoftintr(int si) +{ + extern __volatile uint32_t becc_sipending; + + becc_sipending |= (1 << si); + BECC_CSR_WRITE(BECC_ICSR, (1U << ICU_SOFT)); +} + +int becc_softint(void *arg); + +#if !defined(EVBARM_SPL_NOINLINE) + +#define _splraise(ipl) becc_splraise(ipl) +#define splx(new) becc_splx(new) +#define _spllower(ipl) becc_spllower(ipl) +#define _setsoftintr(si) becc_setsoftintr(si) + +#else + +int _splraise(int); +void splx(int); +int _spllower(int); +void _setsoftintr(int); + +#endif /* ! EVBARM_SPL_NOINLINE */ + +#endif /* _BECC_INTR_H_ */ diff --git a/sys/arch/arm/xscale/becc_pci.c b/sys/arch/arm/xscale/becc_pci.c new file mode 100644 index 000000000000..70beddca2782 --- /dev/null +++ b/sys/arch/arm/xscale/becc_pci.c @@ -0,0 +1,383 @@ +/* $NetBSD: becc_pci.c,v 1.1 2003/01/25 01:57:19 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * PCI configuration support for the ADI Engineering Big Endian Companion + * Chip. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include + +#include "opt_pci.h" +#include "pci.h" + +void becc_pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int becc_pci_bus_maxdevs(void *, int); +pcitag_t becc_pci_make_tag(void *, int, int, int); +void becc_pci_decompose_tag(void *, pcitag_t, int *, int *, + int *); +pcireg_t becc_pci_conf_read(void *, pcitag_t, int); +void becc_pci_conf_write(void *, pcitag_t, int, pcireg_t); + +int becc_pci_intr_map(struct pci_attach_args *, + pci_intr_handle_t *); +const char *becc_pci_intr_string(void *, pci_intr_handle_t); +const struct evcnt *becc_pci_intr_evcnt(void *, pci_intr_handle_t); +void *becc_pci_intr_establish(void *, pci_intr_handle_t, + int, int (*)(void *), void *); +void becc_pci_intr_disestablish(void *, void *); + +#define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit) +#define PCI_CONF_UNLOCK(s) restore_interrupts((s)) + +#if 0 +#define DPRINTF(x) printf(x) +#else +#define DPRINTF(x) +#endif + +void +becc_pci_init(pci_chipset_tag_t pc, void *cookie) +{ +#if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) + struct becc_softc *sc = cookie; + struct extent *ioext, *memext; +#endif + + pc->pc_conf_v = cookie; + pc->pc_attach_hook = becc_pci_attach_hook; + pc->pc_bus_maxdevs = becc_pci_bus_maxdevs; + pc->pc_make_tag = becc_pci_make_tag; + pc->pc_decompose_tag = becc_pci_decompose_tag; + pc->pc_conf_read = becc_pci_conf_read; + pc->pc_conf_write = becc_pci_conf_write; + + pc->pc_intr_v = cookie; + pc->pc_intr_map = becc_pci_intr_map; + pc->pc_intr_string = becc_pci_intr_string; + pc->pc_intr_evcnt = becc_pci_intr_evcnt; + pc->pc_intr_establish = becc_pci_intr_establish; + pc->pc_intr_disestablish = becc_pci_intr_disestablish; + +#if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) + /* + * Configure the PCI bus. + * + * XXX We need to revisit this. We only configure the Secondary + * bus (and its children). The bus configure code needs changes + * to support how the busses are arranged on this chip. We also + * need to only configure devices in the private device space on + * the Secondary bus. + */ + + /* Reserve the bottom 32K of the PCI address space. */ + ioext = extent_create("pciio", sc->sc_ioout_xlate + (32 * 1024), + sc->sc_ioout_xlate + (64 * 1024) - 1, + M_DEVBUF, NULL, 0, EX_NOWAIT); + memext = extent_create("pcimem", sc->sc_owin_xlate[0], + sc->sc_owin_xlate[0] + BECC_PCI_MEM1_SIZE - 1, + M_DEVBUF, NULL, 0, EX_NOWAIT); + + printf("%s: configuring PCI bus\n", sc->sc_dev.dv_xname); + pci_configure_bus(pc, ioext, memext, NULL, 0, arm_dcache_align); + + extent_destroy(ioext); + extent_destroy(memext); +#endif +} + +void +pci_conf_interrupt(pci_chipset_tag_t pc, int a, int b, int c, int d, int *p) +{ +} + +void +becc_pci_attach_hook(struct device *parent, struct device *self, + struct pcibus_attach_args *pba) +{ + + /* Nothing to do. */ +} + +int +becc_pci_bus_maxdevs(void *v, int busno) +{ + + return (32); +} + +pcitag_t +becc_pci_make_tag(void *v, int b, int d, int f) +{ + + return ((b << 16) | (d << 11) | (f << 8)); +} + +void +becc_pci_decompose_tag(void *v, 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; +} + +struct pciconf_state { + uint32_t ps_offset; + + int ps_b, ps_d, ps_f; + int ps_type; +}; + +static int +becc_pci_conf_setup(struct becc_softc *sc, pcitag_t tag, int offset, + struct pciconf_state *ps) +{ + + becc_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); + + /* + * If the bus # is the same as our own, then use Type 0 cycles, + * else use Type 1. + */ + if (ps->ps_b == 0) { + /* XXX This is a platform-specific parameter. */ + if (ps->ps_d > (14 - BECC_IDSEL_BIT)) + return (1); + ps->ps_offset = (1U << (ps->ps_d + BECC_IDSEL_BIT)) | + (ps->ps_f << 8) | offset; + ps->ps_type = 0; + } else { + /* The tag is already in the correct format. */ + ps->ps_offset = tag | offset | 1; + ps->ps_type = 1; + } + + return (0); +} + +static int becc_pci_conf_cleanup(struct becc_softc *sc); +static int +becc_pci_conf_cleanup(struct becc_softc *sc) +{ + uint32_t reg; + int err=0; + + BECC_CSR_WRITE(BECC_POCR, 0); + + reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); + if (reg & 0xf9000000) { + DPRINTF((" ** pci status error: %08x (%08x) **\n", + reg, reg & 0xf9000000)); + + err = 1; + becc_pcicore_write(sc, PCI_COMMAND_STATUS_REG, + reg & 0xf900ffff); + reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); + + DPRINTF((" ** pci status after clearing: %08x (%08x) **\n", + reg, reg & 0xf9000000)); + } + reg = BECC_CSR_READ(BECC_PMISR); + if (reg & 0x000f000d) { + DPRINTF((" ** pci master isr: %08x (%08x) **\n", + reg, reg & 0x000f000d)); + + err = 1; + BECC_CSR_WRITE(BECC_PMISR, reg & 0x000f000d); + reg = BECC_CSR_READ(BECC_PMISR); + + DPRINTF((" ** pci master isr after clearing: %08x (%08x) **\n", + reg, reg & 0x000f000d)); + } + reg = BECC_CSR_READ(BECC_PSISR); + if (reg & 0x000f0210) { + DPRINTF((" ** pci slave isr: %08x (%08x) **\n", + reg, reg & 0x000f0210)); + + err = 1; + BECC_CSR_WRITE(BECC_PSISR, reg & 0x000f0210); + reg = BECC_CSR_READ(BECC_PSISR); + + DPRINTF((" ** pci slave isr after clearing: %08x (%08x) **\n", + reg, reg & 0x000f0210)); + } + + return err; +} + +pcireg_t +becc_pci_conf_read(void *v, pcitag_t tag, int offset) +{ + struct becc_softc *sc = v; + struct pciconf_state ps; + vaddr_t va; + pcireg_t rv; + u_int s; + + if (becc_pci_conf_setup(sc, tag, offset, &ps)) + return ((pcireg_t) -1); + + /* + * Skip device 0 (the BECC itself). We don't want it + * to appear as part of the PCI device space. + */ + if (ps.ps_b == 0 && ps.ps_d == 0) + return ((pcireg_t) -1); + + PCI_CONF_LOCK(s); + + va = sc->sc_pci_cfg_base + ps.ps_offset; + BECC_CSR_WRITE(BECC_POCR, ps.ps_type); + + if (badaddr_read((void *) va, sizeof(rv), &rv)) { + /* XXX Check master/target abort? */ +#if 0 + printf("conf_read: %d/%d/%d bad address\n", + ps.ps_b, ps.ps_d, ps.ps_f); +#endif + rv = (pcireg_t) -1; + } + + if (becc_pci_conf_cleanup(sc)) + rv = (pcireg_t) -1; + + PCI_CONF_UNLOCK(s); + + return (rv); +} + +void +becc_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) +{ + struct becc_softc *sc = v; + struct pciconf_state ps; + vaddr_t va; + u_int s; + + if (becc_pci_conf_setup(sc, tag, offset, &ps)) + return; + + PCI_CONF_LOCK(s); + BECC_CSR_WRITE(BECC_POCR, ps.ps_type); + + va = sc->sc_pci_cfg_base + ps.ps_offset; + + *(__volatile pcireg_t *)va = val; + + becc_pci_conf_cleanup(sc); + + PCI_CONF_UNLOCK(s); +} + +int +becc_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + int irq; + + if (pa->pa_bus == 0) { + switch (pa->pa_device) { + case 1: irq = ICU_PCI_INTB; break; /* Ethernet #0 */ + case 2: irq = ICU_PCI_INTC; break; /* Ethernet #1 */ + case 3: irq = ICU_PCI_INTA; break; /* Card slot? */ + default: + break; + } + } else { + switch (pa->pa_intrpin) { + case 1: irq = ICU_PCI_INTA; break; + case 2: irq = ICU_PCI_INTB; break; + case 3: irq = ICU_PCI_INTC; break; + case 4: irq = ICU_PCI_INTD; break; + default: + printf("becc_pci_intr_map: bogus pin: %d\n", + pa->pa_intrpin); + return (1); + } + } + + *ihp = irq; + return (0); +} + +const char * +becc_pci_intr_string(void *v, pci_intr_handle_t ih) +{ + + return (becc_irqnames[ih]); +} + +const struct evcnt * +becc_pci_intr_evcnt(void *v, pci_intr_handle_t ih) +{ + + /* XXX For now. */ + return (NULL); +} + +void * +becc_pci_intr_establish(void *v, pci_intr_handle_t ih, int ipl, + int (*func)(void *), void *arg) +{ + + return (becc_intr_establish(ih, ipl, func, arg)); +} + +void +becc_pci_intr_disestablish(void *v, void *cookie) +{ + + becc_intr_disestablish(cookie); +} diff --git a/sys/arch/arm/xscale/becc_space.c b/sys/arch/arm/xscale/becc_space.c new file mode 100644 index 000000000000..61702290b768 --- /dev/null +++ b/sys/arch/arm/xscale/becc_space.c @@ -0,0 +1,332 @@ +/* $NetBSD: becc_space.c,v 1.1 2003/01/25 01:57:19 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * bus_space functions for the ADI Engineering Big Endian Companion Chip. + */ + +#include +#include + +#include + +#include + +#include +#include + +/* Prototypes for all the bus_space structure functions */ +bs_protos(becc); +bs_protos(becc_io); +bs_protos(becc_mem); +bs_protos(generic); +bs_protos(generic_armv4); +bs_protos(bs_notimpl); + +/* + * Template bus_space -- copied, and the bits that are NULL are + * filled in. + */ +const struct bus_space becc_bs_tag_template = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + NULL, + NULL, + becc_bs_subregion, + + /* allocation/deallocation */ + NULL, + NULL, + + /* get kernel virtual address */ + becc_bs_vaddr, + + /* mmap */ + becc_bs_mmap, + + /* barrier */ + becc_bs_barrier, + + /* read (single) */ + generic_bs_r_1, + generic_armv4_bs_r_2, + generic_bs_r_4, + bs_notimpl_bs_r_8, + + /* read multiple */ + generic_bs_rm_1, + generic_armv4_bs_rm_2, + generic_bs_rm_4, + bs_notimpl_bs_rm_8, + + /* read region */ + bs_notimpl_bs_rr_1, + generic_armv4_bs_rr_2, + generic_bs_rr_4, + bs_notimpl_bs_rr_8, + + /* write (single) */ + generic_bs_w_1, + generic_armv4_bs_w_2, + generic_bs_w_4, + bs_notimpl_bs_w_8, + + /* write multiple */ + generic_bs_wm_1, + generic_armv4_bs_wm_2, + generic_bs_wm_4, + bs_notimpl_bs_wm_8, + + /* write region */ + bs_notimpl_bs_wr_1, + generic_armv4_bs_wr_2, + generic_bs_wr_4, + bs_notimpl_bs_wr_8, + + /* set multiple */ + bs_notimpl_bs_sm_1, + bs_notimpl_bs_sm_2, + bs_notimpl_bs_sm_4, + bs_notimpl_bs_sm_8, + + /* set region */ + bs_notimpl_bs_sr_1, + generic_armv4_bs_sr_2, + bs_notimpl_bs_sr_4, + bs_notimpl_bs_sr_8, + + /* copy */ + bs_notimpl_bs_c_1, + generic_armv4_bs_c_2, + bs_notimpl_bs_c_4, + bs_notimpl_bs_c_8, +}; + +void +becc_io_bs_init(bus_space_tag_t bs, void *cookie) +{ + + *bs = becc_bs_tag_template; + bs->bs_cookie = cookie; + + bs->bs_map = becc_io_bs_map; + bs->bs_unmap = becc_io_bs_unmap; + bs->bs_alloc = becc_io_bs_alloc; + bs->bs_free = becc_io_bs_free; + + bs->bs_vaddr = becc_io_bs_vaddr; +} + +void +becc_mem_bs_init(bus_space_tag_t bs, void *cookie) +{ + + *bs = becc_bs_tag_template; + bs->bs_cookie = cookie; + + bs->bs_map = becc_mem_bs_map; + bs->bs_unmap = becc_mem_bs_unmap; + bs->bs_alloc = becc_mem_bs_alloc; + bs->bs_free = becc_mem_bs_free; + + bs->bs_mmap = becc_mem_bs_mmap; +} + +/* *** Routines shared by becc, PCI IO, and PCI MEM. *** */ + +int +becc_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + + *nbshp = bsh + offset; + return (0); +} + +void +becc_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t len, int flags) +{ + + /* Nothing to do. */ +} + +void * +becc_bs_vaddr(void *t, bus_space_handle_t bsh) +{ + + return ((void *)bsh); +} + +paddr_t +becc_bs_mmap(void *t, bus_addr_t addr, off_t off, int prot, int flags) +{ + + /* Not supported. */ + return (-1); +} + +/* *** Routines for PCI IO. *** */ + +int +becc_io_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + struct becc_softc *sc = t; + vaddr_t winvaddr; + uint32_t busbase; + + if (bpa >= sc->sc_ioout_xlate && + bpa < (sc->sc_ioout_xlate + (64 * 1024))) { + busbase = sc->sc_ioout_xlate; + winvaddr = sc->sc_pci_io_base; + } else + return (EINVAL); + + if ((bpa + size) >= (busbase + (64 * 1024))) + return (EINVAL); + + /* + * Found the window -- PCI I/O space is mapped at a fixed + * virtual address by board-specific code. Translate the + * bus address to the virtual address. + */ + *bshp = winvaddr + (bpa - busbase); + + return (0); +} + +void +becc_io_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + /* Nothing to do. */ +} + +int +becc_io_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *bpap, bus_space_handle_t *bshp) +{ + + panic("becc_io_bs_alloc(): not implemented\n"); +} + +void +becc_io_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("becc_io_bs_free(): not implemented\n"); +} + +void * +becc_io_bs_vaddr(void *t, bus_space_handle_t bsh) +{ + + /* Not supported. */ + return (NULL); +} + +/* *** Routines for PCI MEM. *** */ + +int +becc_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + + struct becc_softc *sc = t; + vaddr_t winvaddr; + uint32_t busbase; + + /* + * The two memory windows have been configured to the same + * PCI base by board-specific code, so we only need to look + * at the first one. + */ + + if (bpa >= sc->sc_owin_xlate[0] && + bpa < (sc->sc_owin_xlate[0] + BECC_PCI_MEM1_SIZE)) { + busbase = sc->sc_owin_xlate[0]; + winvaddr = sc->sc_pci_mem_base[0]; + } else + return (EINVAL); + + if ((bpa + size) >= (busbase + BECC_PCI_MEM1_SIZE)) + return (EINVAL); + + /* + * Found the window -- PCI MEM space is mapped at a fixed + * virtual address by board-specific code. Translate the + * bus address to the virtual address. + */ + *bshp = winvaddr + (bpa - busbase); + + return (0); +} + +void +becc_mem_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + /* Nothing to do. */ +} + +int +becc_mem_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *bpap, bus_space_handle_t *bshp) +{ + + panic("becc_mem_bs_alloc(): not implemented\n"); +} + +void +becc_mem_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("becc_mem_bs_free(): not implemented\n"); +} + +paddr_t +becc_mem_bs_mmap(void *t, bus_addr_t addr, off_t off, int prot, int flags) +{ + + /* XXX */ + return (-1); +} diff --git a/sys/arch/arm/xscale/becc_timer.c b/sys/arch/arm/xscale/becc_timer.c new file mode 100644 index 000000000000..a056340c6fe6 --- /dev/null +++ b/sys/arch/arm/xscale/becc_timer.c @@ -0,0 +1,306 @@ +/* $NetBSD: becc_timer.c,v 1.1 2003/01/25 01:57:20 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Timer/clock support for the ADI Engineering Big Endian Companion Chip. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +void (*becc_hardclock_hook)(void); + +/* + * Note, since COUNTS_PER_USEC doesn't divide evenly, we round up. + */ +#define COUNTS_PER_SEC BECC_PERIPH_CLOCK +#define COUNTS_PER_USEC ((COUNTS_PER_SEC / 1000000) + 1) + +static void *clock_ih; + +/* + * Since the timer interrupts when the counter underflows, we need to + * subtract 1 from counts_per_hz when loading the preload register. + */ +static uint32_t counts_per_hz; + +int clockhandler(void *); + +/* + * becc_calibrate_delay: + * + * Calibrate the delay loop. + */ +void +becc_calibrate_delay(void) +{ + + /* + * Just use hz=100 for now -- we'll adjust it, if necessary, + * in cpu_initclocks(). + */ + counts_per_hz = COUNTS_PER_SEC / 100; + + /* Stop both timers, clear interrupts. */ + BECC_CSR_WRITE(BECC_TSCRA, TSCRx_TIF); + BECC_CSR_WRITE(BECC_TSCRB, TSCRx_TIF); + + /* Set the timer preload value. */ + BECC_CSR_WRITE(BECC_TPRA, counts_per_hz - 1); + + /* Start the timer. */ + BECC_CSR_WRITE(BECC_TSCRA, TSCRx_TE | TSCRx_CM); +} + +/* + * cpu_initclocks: + * + * Initialize the clock and get them going. + */ +void +cpu_initclocks(void) +{ + u_int oldirqstate; + +#if 0 + if (hz < 50 || COUNTS_PER_SEC % hz) { + printf("Cannot get %d Hz clock; using 100 Hz\n", hz); + hz = 100; + } +#endif + tick = 1000000 / hz; /* number of microseconds between interrupts */ + tickfix = 1000000 - (hz * tick); + if (tickfix) { + int ftp; + + ftp = min(ffs(tickfix), ffs(hz)); + tickfix >>= (ftp - 1); + tickfixinterval = hz >> (ftp - 1); + } + + /* + * We only have one timer available; stathz and profhz are + * always left as 0 (the upper-layer clock code deals with + * this situation). + */ + if (stathz != 0) + printf("Cannot get %d Hz statclock\n", stathz); + stathz = 0; + + if (profhz != 0) + printf("Cannot get %d Hz profclock\n", profhz); + profhz = 0; + + /* Report the clock frequency. */ + printf("clock: hz=%d stathz=%d profhz=%d\n", hz, stathz, profhz); + + oldirqstate = disable_interrupts(I32_bit); + + /* Hook up the clock interrupt handler. */ + clock_ih = becc_intr_establish(ICU_TIMERA, IPL_CLOCK, + clockhandler, NULL); + if (clock_ih == NULL) + panic("cpu_initclocks: unable to register timer interrupt"); + + /* Set up the new clock parameters. */ + + /* Stop timer, clear interrupt */ + BECC_CSR_WRITE(BECC_TSCRA, TSCRx_TIF); + + counts_per_hz = COUNTS_PER_SEC / hz; + + /* Set the timer preload value. */ + BECC_CSR_WRITE(BECC_TPRA, counts_per_hz - 1); + + /* ...and start it in motion. */ + BECC_CSR_WRITE(BECC_TSCRA, TSCRx_TE | TSCRx_CM); + + /* register soft interrupt handler as well */ + becc_intr_establish(ICU_SOFT, IPL_SOFT, becc_softint, NULL); + + restore_interrupts(oldirqstate); +} + +/* + * setstatclockrate: + * + * Set the rate of the statistics clock. + * + * We assume that hz is either stathz or profhz, and that neither + * will change after being set by cpu_initclocks(). We could + * recalculate the intervals here, but that would be a pain. + */ +void +setstatclockrate(int hz) +{ + + /* + * XXX Use TMR1? + */ +} + +/* + * microtime: + * + * Fill in the specified timeval struct with the current time + * accurate to the microsecond. + */ +void +microtime(struct timeval *tvp) +{ + static struct timeval lasttv; + u_int oldirqstate; + uint32_t counts; + + oldirqstate = disable_interrupts(I32_bit); + + /* + * XXX How do we compensate for the -1 behavior of the preload value? + */ + counts = counts_per_hz - BECC_CSR_READ(BECC_TCVRA); + + /* Fill in the timeval struct. */ + *tvp = time; + tvp->tv_usec += (counts / COUNTS_PER_USEC); + + /* Make sure microseconds doesn't overflow. */ + while (tvp->tv_usec >= 1000000) { + tvp->tv_usec -= 1000000; + tvp->tv_sec++; + } + + /* Make sure the time has advanced. */ + if (tvp->tv_sec == lasttv.tv_sec && + tvp->tv_usec <= lasttv.tv_usec) { + tvp->tv_usec = lasttv.tv_usec + 1; + if (tvp->tv_usec >= 1000000) { + tvp->tv_usec -= 1000000; + tvp->tv_sec++; + } + } + + lasttv = *tvp; + + restore_interrupts(oldirqstate); +} + +/* + * delay: + * + * Delay for at least N microseconds. + */ +void +delay(u_int n) +{ + uint32_t cur, last, delta, usecs; + + /* + * This works by polling the timer and counting the + * number of microseconds that go by. + */ + last = BECC_CSR_READ(BECC_TCVRA); + delta = usecs = 0; + + while (n > usecs) { + cur = BECC_CSR_READ(BECC_TCVRA); + + /* Check to see if the timer has wrapped around. */ + if (last < cur) + delta += (last + (counts_per_hz - cur)); + else + delta += (last - cur); + + last = cur; + + if (delta >= COUNTS_PER_USEC) { + usecs += delta / COUNTS_PER_USEC; + delta %= COUNTS_PER_USEC; + } + } +} + +/* + * inittodr: + * + * Initialize time from the time-of-day register. + */ +void +inittodr(time_t base) +{ + + time.tv_sec = base; + time.tv_usec = 0; +} + +/* + * resettodr: + * + * Reset the time-of-day register with the current time. + */ +void +resettodr(void) +{ +} + +/* + * clockhandler: + * + * Handle the hardclock interrupt. + */ +int +clockhandler(void *arg) +{ + struct clockframe *frame = arg; + + /* ACK the interrupt. */ + BECC_CSR_WRITE(BECC_TSCRA, TSCRx_TE | TSCRx_CM | TSCRx_TIF); + + hardclock(frame); + + if (becc_hardclock_hook != NULL) + (*becc_hardclock_hook)(); + + return (1); +} diff --git a/sys/arch/arm/xscale/beccreg.h b/sys/arch/arm/xscale/beccreg.h new file mode 100644 index 000000000000..4a7e7824f9b0 --- /dev/null +++ b/sys/arch/arm/xscale/beccreg.h @@ -0,0 +1,196 @@ +/* $NetBSD: beccreg.h,v 1.1 2003/01/25 01:57:20 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BECCREG_H_ +#define _BECCREG_H_ + +/* + * Register definitions for the ADI Engineering Big Endian Companion + * Chip for the Intel i80200. + */ + +/* Revision codes */ + +#define BECC_REV_V7 0x00 /* rev <= 7 */ +#define BECC_REV_V8 0x01 /* rev 8 */ +#define BECC_REV_V9 0x02 /* rev >= 9 */ + +/* Memory Map */ + +#define BECC_REG_BASE 0x04000000 +#define BECC_REG_SIZE 0x01000000 /* 16M */ + +#define BECC_PCI_CONF_BASE 0x08000000 +#define BECC_PCI_CONF_SIZE 0x02000000 /* 32M */ + +#define BECC_PCI_IO_BASE 0x0a000000 +#define BECC_PCI_IO_SIZE 0x02000000 /* 32M */ + +#define BECC_PCI_MEM1_BASE 0x0c000000 +#define BECC_PCI_MEM1_SIZE 0x02000000 /* 32M */ + +#define BECC_PCI_MEM2_BASE 0x0e000000 +#define BECC_PCI_MEM2_SIZE 0x02000000 /* 32M */ + +#define BECC_SDRAM_BASE 0xc0000000 + +/* Peripheral clock is 33.3MHz */ +#define BECC_PERIPH_CLOCK 33300000 + +/* BECC registers; offsets from BECC_REG_BASE */ + +#define BECC_PSISR 0x0000 /* PCI slave interrupt status */ +#define PSISR_SERR (1U << 4) /* system error */ +#define PSISR_PERR (1U << 9) /* parity error */ +#define PSISR_IFU (1U << 16) /* inbound FIFO uflow */ +#define PSISR_IFO (1U << 17) /* inbound FIFO oflow */ +#define PSISR_OFU (1U << 18) /* outbound FIFO uflow */ +#define PSISR_OFO (1U << 19) /* outbound FIFO oflow */ + +#define BECC_PSTR0 0x0010 /* PCI slave translation window #0 */ +#define BECC_PSTR1 0x0018 /* PCI slave translation window #1 */ +#define PSTRx_ADDRMASK (3U << 25) /* address mask */ +#define PSTRx_BEE (1U << 0) /* big-endian enable */ +#define BECC_PSTR2 0x0020 /* PCI slave translation window #2 */ +#define PSTR2_ADDRMASK (0U) /* address mask (all SDRAM) */ + +#define BECC_PMISR 0x0100 /* PCI master interrupt status */ +#define PMISR_PE (1U << 0) /* parity error */ +#define PMISR_TA (1U << 2) /* target abort */ +#define PMISR_MA (1U << 3) /* master abort */ +#define PMISR_IFU (1U << 16) /* inbound FIFO uflow */ +#define PMISR_IFO (1U << 17) /* inbound FIFO oflow */ +#define PMISR_OFU (1U << 18) /* outbound FIFO uflow */ +#define PMISR_OFO (1U << 19) /* outbound FIFO oflow */ + +#define BECC_IDSEL_BIT 11 /* first device on PCI bus */ + +#define BECC_POMR1 0x0110 /* PCI outbound memory window #1 */ +#define BECC_POMR2 0x0114 /* PCI outbound memory window #2 */ +#define POMRx_ADDRMASK 0xfe000000 /* address mask */ +#define POMRx_BEE (1U << 2) /* big-endian enable */ +#define POMRx_F32 (1U << 3) /* force 32-bit transfer */ +#define POMRx_BO(x) (x) /* busrt order (MBZ) */ +#define BECC_POMR3 0x0130 /* PCI outbound memory window #3 */ +#define POMR3_ADDRMASK 0xc0000000 /* address mask */ + +#define BECC_POIR 0x0118 /* PCI outbound I/O window */ +#define POIR_ADDRMASK 0xfe000000 /* address mask */ +#define POIR_BEE (1U << 2) /* big-endian enable */ + +#define BECC_POCR 0x0120 /* PCI outbound config window */ +#define POCR_BEE (1U << 2) /* big-endian enable */ +#define POCR_TYPE (1U << 0) /* for type 1 cycles */ + +#define BECC_DMACR 0x0200 /* DMA control register */ +#define DMACR_CE (1U << 0) /* channel enable */ + +#define BECC_DMASR 0x0204 /* DMA status register */ +#define DMASR_PEF (1U << 0) /* PCI parity error */ +#define DMASR_PTA (1U << 2) /* PCI target abort */ +#define DMASR_PMA (1U << 3) /* PCI master abort */ +#define DMASR_EOTI (1U << 8) /* end of transfer interrupt */ +#define DMASR_CA (1U << 9) /* channel active */ +#define DMASR_IFU (1U << 16) /* inbound FIFO uflow */ +#define DMASR_IFO (1U << 17) /* inbound FIFO oflow */ +#define DMASR_OFU (1U << 18) /* outbound FIFO uflow */ +#define DMASR_OFO (1U << 19) /* outbound FIFO oflow */ + +#define BECC_DMAPCIAR 0x0210 /* DMA PCI address */ + +#define BECC_DMALAR 0x021c /* DMA local address */ + +#define BECC_DMABCR 0x0220 /* DMA byte count */ + +#define BECC_DMADCR 0x0224 /* DMA descriptor control */ +#define DMADCR_F32 (1U << 6) /* force 32-bit */ +#define DMADCR_BEE (1U << 5) /* big-endian enable */ +#define DMADCR_PCICMD(x) (x) /* PCI command */ + +#define PCICMD_MR 0x6 /* memory read */ +#define PCICMD_MRL 0xe /* memory read line */ +#define PCICMD_MRM 0xc /* memory read multiple */ +#define PCICMD_MW 0x7 /* memory write */ + +#define BECC_TSCRA 0x0300 /* Timer status/control A */ +#define BECC_TSCRB 0x0320 /* Timer status/control B */ +#define TSCRx_TE (1U << 0) /* timer enable */ +#define TSCRx_CM (1U << 1) /* continuous mode */ +#define TSCRx_TIF (1U << 9) /* timer interrupt flag */ + +#define BECC_TPRA 0x0304 /* Timer preload A */ +#define BECC_TPRB 0x0324 /* Timer preload B */ + +#define BECC_TCVRA 0x0308 /* Timer current value A */ +#define BECC_TCVRB 0x0328 /* Timer current value B */ + +#define BECC_ICSR 0x0400 /* Interrupt control/status */ +#define BECC_ICMR 0x0404 /* Interrupt mask */ +#define BECC_ICSTR 0x0408 /* Interrupt steer */ + +#define ICU_SOFT 0 /* software interrupt */ +#define ICU_TIMERA 1 /* timer A */ +#define ICU_TIMERB 2 /* timer B */ +#define ICU_DIAGERR 7 /* diagnostic error */ +#define ICU_DMA_EOT 8 /* DMA end-of-transfer */ +#define ICU_DMA_PEF 9 /* DMA parity error */ +#define ICU_DMA_TA 10 /* DMA target abort */ +#define ICU_DMA_MA 11 /* DMA master abort */ +#define ICU_PCI_PERR 16 /* PCI parity error */ +#define ICU_PCI_SERR 19 /* PCI system error */ +#define ICU_PCI_POAPEI 20 /* PCI outbound ATU parity error */ +#define ICU_PCI_POATAI 21 /* PCI outbound ATU target abort */ +#define ICU_PCI_POAMAI 22 /* PCI outbound ATU master abort */ +#define ICU_UARTA 24 /* UART A */ +#define ICU_UARTB 25 /* UART B */ +#define ICU_PCI_INTA 26 /* PCI INTA# */ +#define ICU_PCI_INTB 27 /* PCI INTB# */ +#define ICU_PCI_INTC 28 /* PCI INTC# */ +#define ICU_PCI_INTD 29 /* PCI INTD# */ +#define ICU_PUSHBUTTON 30 /* push button pulse */ + +#define ICU_RESERVED_MASK ((1U << 3) | (1U << 4) | (1U << 5) | \ + (1U << 6) | (1U << 12) | (1U << 13) | \ + (1U << 14) | (1U << 15) | (1U << 17) | \ + (1U << 18) | (1U << 23) | (1U << 31)) +#define ICU_VALID_MASK (~ICU_RESERVED_MASK) + +#define BECC_RSSR 0x0500 /* rotary switch status */ +#define RSSR_POS 0x0000000f /* switch position */ +#define RSSR_BE (1U << 6) /* big-endian jumper */ + +#endif /* _BECCREG_H_ */ diff --git a/sys/arch/arm/xscale/beccvar.h b/sys/arch/arm/xscale/beccvar.h new file mode 100644 index 000000000000..f73b844a36a8 --- /dev/null +++ b/sys/arch/arm/xscale/beccvar.h @@ -0,0 +1,127 @@ +/* $NetBSD: beccvar.h,v 1.1 2003/01/25 01:57:20 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BECCVAR_H_ +#define _BECCVAR_H_ + +#include +#include + +/* + * There are roughly 32 interrupt sources. + */ +#define NIRQ 32 + +struct intrhand { + TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */ + int (*ih_func)(void *); /* handler */ + void *ih_arg; /* arg for handler */ + int ih_ipl; /* IPL_* */ + int ih_irq; /* IRQ number */ +}; + +struct intrq { + TAILQ_HEAD(, intrhand) iq_list; /* handler list */ + struct evcnt iq_ev; /* event counter */ + int iq_mask; /* IRQs to mask while handling */ + int iq_levels; /* IPL_*'s this IRQ has */ + int iq_ist; /* share type */ +}; + +struct becc_softc { + struct device sc_dev; /* generic device glue */ + + /* + * We expect the board-specific front-end to have already mapped + * the PCI I/O, memory, and configuration spaces. + */ + vaddr_t sc_pci_io_base; /* I/O window vaddr */ + vaddr_t sc_pci_mem_base[2]; /* MEM window vaddr */ + vaddr_t sc_pci_cfg_base; /* CFG window vaddr */ + + /* + * These define the 2 32M PCI Inbound windows and 1 128M (rev8 & up). + */ + struct { + uint32_t iwin_base; /* PCI address */ + uint32_t iwin_xlate; /* local address */ + } sc_iwin[3]; + + /* + * Variables that define the 2 32M PCI Outbound windows and + * 1 1G (rev8 & up). + */ + uint32_t sc_owin_xlate[3]; /* PCI address */ + + /* + * This is the PCI address that the Outbound I/O + * window maps to. + */ + uint32_t sc_ioout_xlate; + + /* Bus space, DMA, and PCI tags for the PCI bus. */ + struct bus_space sc_pci_iot; + struct bus_space sc_pci_memt; + struct arm32_bus_dma_tag sc_pci_dmat; + struct arm32_pci_chipset sc_pci_chipset; + + /* DMA window info for PCI DMA. */ + struct arm32_dma_range sc_pci_dma_range[3]; +}; + +extern int becc_rev; /* Set by early bootstrap code */ +extern const char *becc_revisions[]; +extern void (*becc_hardclock_hook)(void); + +void becc_calibrate_delay(void); + +void becc_icu_init(void); +void becc_intr_init(void); +void *becc_intr_establish(int, int, int (*)(void *), void *); +void becc_intr_disestablish(void *); + +void becc_io_bs_init(bus_space_tag_t, void *); +void becc_mem_bs_init(bus_space_tag_t, void *); + +void becc_pci_init(pci_chipset_tag_t, void *); + +void becc_attach(struct becc_softc *); + +uint32_t becc_pcicore_read(struct becc_softc *, bus_addr_t); +void becc_pcicore_write(struct becc_softc *, bus_addr_t, uint32_t); + +#endif /* _BECCVAR_H_ */ diff --git a/sys/arch/arm/xscale/files.becc b/sys/arch/arm/xscale/files.becc new file mode 100644 index 000000000000..ada8520b49c2 --- /dev/null +++ b/sys/arch/arm/xscale/files.becc @@ -0,0 +1,14 @@ +# $NetBSD: files.becc,v 1.1 2003/01/25 01:57:17 thorpej Exp $ +# +# Configuration info for the ADI Engineering Big Endian Companion Chip +# for the Intel i80200 processor +# + +file arch/arm/xscale/becc_icu.c +file arch/arm/xscale/becc_timer.c + +device becc {}: pcibus, bus_space_generic +# Board-specific front-end provides attachment. +file arch/arm/xscale/becc.c becc +file arch/arm/xscale/becc_pci.c becc +file arch/arm/xscale/becc_space.c becc diff --git a/sys/arch/arm/xscale/files.i80321 b/sys/arch/arm/xscale/files.i80321 index 26941bfd29f1..b34d49b6645c 100644 --- a/sys/arch/arm/xscale/files.i80321 +++ b/sys/arch/arm/xscale/files.i80321 @@ -1,4 +1,4 @@ -# $NetBSD: files.i80321,v 1.9 2003/01/03 00:41:19 thorpej Exp $ +# $NetBSD: files.i80321,v 1.10 2003/01/25 01:57:17 thorpej Exp $ # # Configuration info for Intel i80321 XScale I/O Processor support # @@ -22,6 +22,12 @@ attach iopaau at iopxs file arch/arm/xscale/i80321_aau.c iopaau file arch/arm/xscale/iopaau.c iopaau +# DMA controller unit +device iopdma: dmover_service +attach iopdma at iopxs +file arch/arm/xscale/i80321_dma.c iopdma +file arch/arm/xscale/iopdma.c iopdma + # Watchdog timer device iopwdog: sysmon_wdog attach iopwdog at iopxs