diff options
| author | matt <matt@NetBSD.org> | 2008-10-24 04:23:18 +0000 |
|---|---|---|
| committer | matt <matt@NetBSD.org> | 2008-10-24 04:23:18 +0000 |
| commit | f5d7ce3d2fc36b2965729a33eb02fb95c9fb56cd (patch) | |
| tree | 97515a04accc8a3749c198a32d3556d5f459848e /sys | |
| parent | bca83f03da86260cb81872198c5e4a7887f75572 (diff) | |
Add support for Cortina Systems SL3516 eval board.
Diffstat (limited to 'sys')
27 files changed, 5096 insertions, 0 deletions
diff --git a/sys/arch/arm/gemini/files.gemini b/sys/arch/arm/gemini/files.gemini new file mode 100644 index 00000000000..3b15dac43db --- /dev/null +++ b/sys/arch/arm/gemini/files.gemini @@ -0,0 +1,73 @@ +# $NetBSD: files.gemini,v 1.1 2008/10/24 04:23:18 matt Exp $ +# +# Configuration info for GEMINI CPU support +# Based on omap/files.omap2 +# + +include "arch/arm/pic/files.pic" + +file arch/arm/arm32/irq_dispatch.S + +# Memory size in megabytes +defparam opt_gemini.h MEMSIZE +defflag opt_gemini.h GEMINI +defflag opt_gemini.h SL3516: GEMINI + +# OBIO just an attach point +define obio { [addr=-1], [size=0], [intr=-1], [mult=1], [intrbase=-1], [nobyteacc=0] + } : bus_space_generic +device obio: obio, pcibus +attach obio at mainbus +file arch/arm/gemini/gemini_obio.c obio needs-count + +# OBIO files +file arch/arm/gemini/gemini_space.c obio +##file arch/arm/gemini/gemini_a2x_space.c obio +##file arch/arm/gemini/gemini_a2x_io.S obio +file arch/arm/gemini/gemini_a4x_space.c obio +file arch/arm/xscale/pxa2x0_a4x_io.S obio +file arch/arm/gemini/gemini_dma.c + +# these bus space methods are not bus-specific ... +# +##file arch/arm/gemini/gemini_nobyteacc_space.c obio +##file arch/arm/gemini/gemini_nobyteacc_io.S obio + +# GEMINI interrupt controller +device geminiicu: pic +attach geminiicu at obio with geminiicu +file arch/arm/gemini/gemini_icu.c geminiicu needs-flag + + + +# GEMINI GPIO controllers + +# GEMINI Timers +device geminitmr +file arch/arm/gemini/gemini_timer.c geminitmr +defparam opt_gemini.h GEMINI_TIMER_CLOCK_FREQ + +# OBIO/geminitmr +attach geminitmr at obio with obiotimer +file arch/arm/gemini/obio_timer.c obiotimer + +# Gemini Watchdog timer +device geminiwdt: sysmon_wdog +file arch/arm/gemini/gemini_wdt.c geminiwdt needs-flag +defparam opt_gemini.h GEMINI_WDT_CLOCK_FREQ + +attach geminiwdt at obio with obiowdt +file arch/arm/gemini/obio_wdt.c obiowdt + +# NS16550 compatible serial ports +attach com at obio with gemini_com +file arch/arm/gemini/gemini_com.c gemini_com +defparam opt_com.h CONSADDR CONSPEED CONMODE + +# GEMINI USB controller + + +# PCI +device gemini_pci: pcibus +attach gemini_pci at obio +file arch/arm/gemini/gemini_pci.c pci diff --git a/sys/arch/arm/gemini/gemini_a4x_space.c b/sys/arch/arm/gemini/gemini_a4x_space.c new file mode 100644 index 00000000000..f6436f865f2 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_a4x_space.c @@ -0,0 +1,137 @@ +/* $NetBSD: gemini_a4x_space.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: pxa2x0_a4x_space.c,v 1.4 2006/07/28 08:15:29 simonb Exp + */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * 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 + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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 tag for 8/16-bit devices on 32-bit bus. + * all registers are located at the address of multiple of 4. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_a4x_space.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(gemini); +bs_protos(a4x); +bs_protos(generic); +bs_protos(generic_armv4); +bs_protos(bs_notimpl); + +struct bus_space gemini_a4x_bs_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + gemini_bs_map, + gemini_bs_unmap, + gemini_bs_subregion, + + /* allocation/deallocation */ + gemini_bs_alloc, /* not implemented */ + gemini_bs_free, /* not implemented */ + + /* get kernel virtual address */ + gemini_bs_vaddr, + + /* mmap */ + bs_notimpl_bs_mmap, + + /* barrier */ + gemini_bs_barrier, + + /* read (single) */ + a4x_bs_r_1, + a4x_bs_r_2, + a4x_bs_r_4, + bs_notimpl_bs_r_8, + + /* read multiple */ + a4x_bs_rm_1, + a4x_bs_rm_2, + bs_notimpl_bs_rm_4, + bs_notimpl_bs_rm_8, + + /* read region */ + bs_notimpl_bs_rr_1, + bs_notimpl_bs_rr_2, + bs_notimpl_bs_rr_4, + bs_notimpl_bs_rr_8, + + /* write (single) */ + a4x_bs_w_1, + a4x_bs_w_2, + a4x_bs_w_4, + bs_notimpl_bs_w_8, + + /* write multiple */ + a4x_bs_wm_1, + a4x_bs_wm_2, + bs_notimpl_bs_wm_4, + bs_notimpl_bs_wm_8, + + /* write region */ + bs_notimpl_bs_wr_1, + bs_notimpl_bs_wr_2, + bs_notimpl_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, + bs_notimpl_bs_sr_2, + bs_notimpl_bs_sr_4, + bs_notimpl_bs_sr_8, + + /* copy */ + bs_notimpl_bs_c_1, + bs_notimpl_bs_c_2, + bs_notimpl_bs_c_4, + bs_notimpl_bs_c_8, +}; diff --git a/sys/arch/arm/gemini/gemini_com.c b/sys/arch/arm/gemini/gemini_com.c new file mode 100644 index 00000000000..c71bf548397 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_com.c @@ -0,0 +1,129 @@ +/* $NetBSD: gemini_com.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: omap_com.c,v 1.2 2008/03/14 15:09:09 cube Exp + */ + +/* + * Based on arch/arm/xscale/pxa2x0_com.c + * + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_com.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include "opt_com.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/termios.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <arm/pic/picvar.h> + +#include <dev/ic/comreg.h> +#include <dev/ic/comvar.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_obiovar.h> + +#include <arm/gemini/gemini_com.h> + +#include "locators.h" + +static int gemini_com_match(device_t, cfdata_t , void *); +static void gemini_com_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(gemini_com, sizeof(struct com_softc), + gemini_com_match, gemini_com_attach, NULL, NULL); + +static int +gemini_com_match(device_t parent, cfdata_t cf, void *aux) +{ + struct obio_attach_args *obio = aux; + bus_space_handle_t bh; + int rv; + + if (obio->obio_addr == -1 || obio->obio_intr == -1) + panic("gemini_com must have addr and intr specified in config."); + + if (obio->obio_size == 0) + obio->obio_size = GEMINI_UART_SIZE; + + if (com_is_console(obio->obio_iot, obio->obio_addr, NULL)) + return (1); + + if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size, + 0, &bh)) + return (0); + + rv = comprobe1(obio->obio_iot, bh); + + bus_space_unmap(obio->obio_iot, bh, obio->obio_size); + + return (rv); +} + +static void +gemini_com_attach(device_t parent, device_t self, void *aux) +{ + struct com_softc *sc = device_private(self); + struct obio_attach_args *obio = aux; + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_addr_t iobase; + + sc->sc_dev = self; + iot = obio->obio_iot; + iobase = obio->obio_addr; + sc->sc_frequency = GEMINI_COM_FREQ; + sc->sc_type = COM_TYPE_NORMAL; + + if (com_is_console(iot, iobase, &ioh) == 0 && + bus_space_map(iot, iobase, obio->obio_size, 0, &ioh)) { + panic(": can't map registers\n"); + return; + } + COM_INIT_REGS(sc->sc_regs, iot, ioh, iobase); + + com_attach_subr(sc); + aprint_naive("\n"); + + intr_establish(obio->obio_intr, IPL_SERIAL, IST_LEVEL_HIGH, + comintr, sc); +} diff --git a/sys/arch/arm/gemini/gemini_com.h b/sys/arch/arm/gemini/gemini_com.h new file mode 100644 index 00000000000..8bd3e770f7c --- /dev/null +++ b/sys/arch/arm/gemini/gemini_com.h @@ -0,0 +1,12 @@ +/* $NetBSD: gemini_com.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +#ifndef _ARM_GEMINI_COM_H_ +#define _ARM_GEMINI_COM_H_ + +#if defined(SL3516) +# define GEMINI_COM_FREQ (3000000L * 16) +#else +# error unknown gemini chip +#endif + +#endif /* _ARM_GEMINI_COM_H_ */ diff --git a/sys/arch/arm/gemini/gemini_dma.c b/sys/arch/arm/gemini/gemini_dma.c new file mode 100644 index 00000000000..f429bc3f01b --- /dev/null +++ b/sys/arch/arm/gemini/gemini_dma.c @@ -0,0 +1,78 @@ +/* $NetBSD: gemini_dma.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: pxa2x0_dma.c,v 1.4 2005/12/11 12:16:51 christos Exp + */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * 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 + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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 dma tag for PXA2[15]0 processor. + * (Currently used only for LCD frame buffer) + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_dma.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> + +#include <uvm/uvm_extern.h> + +#define _ARM32_BUS_DMA_PRIVATE +#include <machine/bus.h> + +struct arm32_bus_dma_tag gemini_bus_dma_tag = { + 0, + 0, + NULL, /* _cookie */ + _bus_dmamap_create, + _bus_dmamap_destroy, + _bus_dmamap_load, + _bus_dmamap_load_mbuf, + _bus_dmamap_load_uio, + _bus_dmamap_load_raw, + _bus_dmamap_unload, + _bus_dmamap_sync, + NULL, /* sync_post */ + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap +}; + diff --git a/sys/arch/arm/gemini/gemini_icu.c b/sys/arch/arm/gemini/gemini_icu.c new file mode 100644 index 00000000000..fbdda737d75 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_icu.c @@ -0,0 +1,260 @@ +/* $NetBSD */ + +/* adapted from: + * NetBSD: omap2_icu.c,v 1.4 2008/08/27 11:03:10 matt Exp + */ + +/* + * Define the SDP2430 specific information and then include the generic OMAP + * interrupt header. + */ + +/* + * 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 this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce this list of conditions + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``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 ANY + * CONTRIBUTORS 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. + */ +#include "opt_gemini.h" +#include "geminiicu.h" + +#define _INTR_PRIVATE + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_icu.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/param.h> +#include <sys/evcnt.h> + +#include <uvm/uvm_extern.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <arm/cpu.h> +#include <arm/armreg.h> +#include <arm/cpufunc.h> +#include <arm/atomic.h> + +#include <arm/pic/picvar.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_obiovar.h> + + +#define INTC_READ(sc, o) \ + bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (o)) +#define INTC_WRITE(sc, o, v) \ + bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (o), v) + +static int geminiicu_match(device_t, cfdata_t, void *); +static void geminiicu_attach(device_t, device_t, void *); + +static void geminiicu_unblock_irqs(struct pic_softc *, size_t, uint32_t); +static void geminiicu_block_irqs(struct pic_softc *, size_t, uint32_t); +static void geminiicu_establish_irq(struct pic_softc *, struct intrsource *); +#if 0 +static void geminiicu_source_name(struct pic_softc *, int, char *, size_t); +#endif + +static const struct pic_ops geminiicu_picops = { + .pic_unblock_irqs = geminiicu_unblock_irqs, + .pic_block_irqs = geminiicu_block_irqs, + .pic_establish_irq = geminiicu_establish_irq, +#if 0 + .pic_source_name = geminiicu_source_name, +#endif +}; + +#define PICTOSOFTC(pic) \ + ((void *)((uintptr_t)(pic) - offsetof(struct geminiicu_softc, sc_pic))) + +static struct geminiicu_softc { + device_t sc_dev; + bus_space_tag_t sc_memt; + bus_space_handle_t sc_memh; + struct pic_softc sc_pic; + uint32_t sc_enabled_mask; + uint32_t sc_edge_mask; + uint32_t sc_edge_rising_mask; + uint32_t sc_edge_falling_mask; + uint32_t sc_level_mask; + uint32_t sc_level_hi_mask; + uint32_t sc_level_lo_mask; +} geminiicu_softc = { + .sc_pic = { + .pic_ops = &geminiicu_picops, + .pic_maxsources = 32, + .pic_name = "geminiicu", + }, +}; + +static void +geminiicu_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask) +{ + struct geminiicu_softc * const sc = PICTOSOFTC(pic); + KASSERT(irqbase == 0 && (irq_mask & sc->sc_enabled_mask) == 0); + sc->sc_enabled_mask |= irq_mask; + INTC_WRITE(sc, GEMINI_ICU_IRQ_ENABLE, sc->sc_enabled_mask); + /* + * If this is a level source, ack it now. If it's still asserted + * it'll come back. + */ + if (irq_mask & sc->sc_level_mask) + INTC_WRITE(sc, GEMINI_ICU_IRQ_CLEAR, + irq_mask & sc->sc_level_mask); +} + +static void +geminiicu_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask) +{ + struct geminiicu_softc * const sc = PICTOSOFTC(pic); + KASSERT(irqbase == 0); + + sc->sc_enabled_mask &= ~irq_mask; + INTC_WRITE(sc, GEMINI_ICU_IRQ_ENABLE, sc->sc_enabled_mask); + /* + * If any of the source are edge triggered, ack them now so + * we won't lose them. + */ + if (irq_mask & sc->sc_edge_mask) + INTC_WRITE(sc, GEMINI_ICU_IRQ_CLEAR, + irq_mask & sc->sc_edge_mask); +} + +/* + * Called with interrupts disabled + */ +static int +find_pending_irqs(struct geminiicu_softc *sc) +{ + uint32_t pending = INTC_READ(sc, GEMINI_ICU_IRQ_STATUS); + + KASSERT((sc->sc_enabled_mask & pending) == pending); + + if (pending == 0) + return 0; + + return pic_mark_pending_sources(&sc->sc_pic, 0, pending); +} + +void +gemini_irq_handler(void *frame) +{ + struct cpu_info * const ci = curcpu(); + struct geminiicu_softc * const sc = &geminiicu_softc; + const int oldipl = ci->ci_cpl; + const uint32_t oldipl_mask = __BIT(oldipl); + int ipl_mask = 0; + + uvmexp.intrs++; + + KASSERT(sc->sc_enabled_mask != 0); + + ipl_mask = find_pending_irqs(sc); + + /* + * Record the pending_ipls and deliver them if we can. + */ + if ((ipl_mask & ~oldipl_mask) > oldipl_mask) + pic_do_pending_ints(I32_bit, oldipl, frame); +} + +void +geminiicu_establish_irq(struct pic_softc *pic, struct intrsource *is) +{ + struct geminiicu_softc * const sc = PICTOSOFTC(pic); + const uint32_t irq_mask = __BIT(is->is_irq); + + KASSERT(is->is_irq < 32); + + sc->sc_enabled_mask &= ~irq_mask; + /* Have to do with this interrupt disabled. */ + INTC_WRITE(sc, GEMINI_ICU_IRQ_ENABLE, sc->sc_enabled_mask); + INTC_WRITE(sc, GEMINI_ICU_IRQ_CLEAR, irq_mask); + + sc->sc_edge_rising_mask &= ~irq_mask; + sc->sc_edge_falling_mask &= ~irq_mask; + sc->sc_level_lo_mask &= ~irq_mask; + sc->sc_level_hi_mask &= ~irq_mask; + + switch (is->is_type) { + case IST_LEVEL_LOW: sc->sc_level_lo_mask |= irq_mask; break; + case IST_LEVEL_HIGH: sc->sc_level_hi_mask |= irq_mask; break; + case IST_EDGE_FALLING: sc->sc_edge_falling_mask |= irq_mask; break; + case IST_EDGE_RISING: sc->sc_edge_rising_mask |= irq_mask; break; + } + + sc->sc_edge_mask = sc->sc_edge_rising_mask | sc->sc_edge_falling_mask; + sc->sc_level_mask = sc->sc_level_hi_mask|sc->sc_level_lo_mask; + + /* + * Set the new interrupt mode. + */ + INTC_WRITE(sc, GEMINI_ICU_IRQ_TRIGMODE, sc->sc_edge_mask); + INTC_WRITE(sc, GEMINI_ICU_IRQ_TRIGLEVEL, + sc->sc_level_lo_mask | sc->sc_edge_falling_mask); +} + +int +geminiicu_match(device_t parent, cfdata_t cf, void *aux) +{ + struct obio_attach_args * const oa = aux; + +#if defined(SL3516) + if ((oa->obio_addr == GEMINI_IC0_BASE) + || (oa->obio_addr == GEMINI_IC1_BASE)) + return 1; + + return 0; +#else +#error unsupported GEMINI variant +#endif +} + +void +geminiicu_attach(device_t parent, device_t self, void *aux) +{ + struct obio_attach_args * const oa = aux; + struct geminiicu_softc * const sc = &geminiicu_softc; + int error; + + aprint_normal("\n"); + + sc->sc_memt = oa->obio_iot; + + error = bus_space_map(sc->sc_memt, oa->obio_addr, 0x1000, 0, + &sc->sc_memh); + if (error) + panic("failed to map interrupt registers: %d", error); + + INTC_WRITE(sc, GEMINI_ICU_IRQ_ENABLE, 0); + INTC_WRITE(sc, GEMINI_ICU_IRQ_CLEAR, 0xffffffff); + INTC_WRITE(sc, GEMINI_ICU_IRQ_TRIGMODE, 0); + INTC_WRITE(sc, GEMINI_ICU_IRQ_TRIGLEVEL, 0xffffffff); + + sc->sc_dev = self; + self->dv_private = sc; + + pic_add(&sc->sc_pic, 0); +} + +CFATTACH_DECL_NEW(geminiicu, + 0, + geminiicu_match, geminiicu_attach, + NULL, NULL); diff --git a/sys/arch/arm/gemini/gemini_intr.h b/sys/arch/arm/gemini/gemini_intr.h new file mode 100644 index 00000000000..68c6607347c --- /dev/null +++ b/sys/arch/arm/gemini/gemini_intr.h @@ -0,0 +1,32 @@ +/* $NetBSD: gemini_intr.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +#ifndef _ARM_GEMINI_INTR_H_ +#define _ARM_GEMINI_INTR_H_ + +#define ARM_IRQ_HANDLER _C_LABEL(gemini_irq_handler) + +#ifndef _LOCORE + +extern void gemini_splx(int); +extern int gemini_splraise(int); +extern int gemini_spllower(int); + +int _splraise(int); +int _spllower(int); +void splx(int); +void gemini_irq_handler(void *); + +#if !defined(EVBARM_SPL_NOINLINE) +#define splx(new) gemini_splx(new) +#define _spllower(ipl) gemini_spllower(ipl) +#define _splraise(ipl) gemini_splraise(ipl) +#ifdef __HAVE_FAST_SOFTINTS +# define _setsoftintr(si) omap_setsoftintr(si) +#endif +#endif /* !EVBARM_SPL_NOINTR */ + + + +#endif /* _LOCORE */ + +#endif /* _ARM_GEMINI_INTR_H_ */ diff --git a/sys/arch/arm/gemini/gemini_obio.c b/sys/arch/arm/gemini/gemini_obio.c new file mode 100644 index 00000000000..e456b067603 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_obio.c @@ -0,0 +1,383 @@ +/* $NetBSD: gemini_obio.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * $Id: gemini_obio.c,v 1.1 2008/10/24 04:23:18 matt Exp $ + */ + +/* + * Autoconfiguration support for the Texas Instruments OMAP "On Board" I/O. + * + * Based on arm/omap/omap_emifs.c which in turn was derived + * Based on arm/xscale/pxa2x0.c which in turn was derived + * from arm/sa11x0/sa11x0.c + * + * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * 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 + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + * + * Copyright (c) 1997,1998, 2001, The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro, Ichiro FUKUHARA and Paul Kranenburg. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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. + * + * Copyright (c) 1999 + * Shin Takemura and PocketBSD Project. All rights reserved. + * + * 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 by the PocketBSD project + * and its contributors. + * 4. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. + */ + +#include "opt_gemini.h" +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_obio.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include "locators.h" +#include "obio.h" +#include "geminiicu.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/reboot.h> + +#include <machine/cpu.h> +#include <machine/bus.h> + +#include <arm/cpufunc.h> +#include <arm/mainbus/mainbus.h> +#include <arm/gemini/gemini_var.h> +#include <arm/gemini/gemini_reg.h> + +#include <arm/gemini/gemini_obiovar.h> + +typedef struct { + boolean_t cs_valid; + ulong cs_addr; + ulong cs_size; +} obio_csconfig_t; + +/* prototypes */ +static int obio_match(device_t, cfdata_t, void *); +static void obio_attach(device_t, device_t, void *); +static int obio_search(device_t, cfdata_t, const int *, void *); +static int obio_find(device_t, cfdata_t, const int *, void *); +static int obio_print(void *, const char *); +static void obio_attach_critical(struct obio_softc *); + +/* attach structures */ +CFATTACH_DECL(obio, sizeof(struct obio_softc), + obio_match, obio_attach, NULL, NULL); + + +static int +obio_match(device_t parent, cfdata_t match, void *aux) +{ + return 1; +} + +static void +obio_attach(device_t parent, device_t self, void *aux) +{ + struct obio_softc *sc = device_private(self); + struct mainbus_attach_args *mb = (struct mainbus_attach_args *)aux; + struct pcibus_attach_args pba; + + sc->sc_iot = &gemini_bs_tag; + + aprint_normal(": On-Board IO\n"); + + sc->sc_ioh = 0; + sc->sc_dmat = &gemini_bus_dma_tag; + sc->sc_base = mb->mb_iobase; + sc->sc_size = mb->mb_iosize; + + /* + * Attach critical devices first. + */ + obio_attach_critical(sc); + + /* + * map PCI controller registers + */ + if (bus_space_map(sc->sc_iot, GEMINI_PCICFG_BASE, + GEMINI_PCI_CFG_DATA+4, 0, &sc->sc_pcicfg_ioh)) { + aprint_error("cannot map PCI controller at %#x\n", + GEMINI_PCICFG_BASE); + return; + } + /* + * initialize the PCI chipset tag + */ + gemini_pci_init(&sc->sc_pci_chipset, sc); + + /* + * attach the rest of our devices + */ + config_search_ia(obio_search, self, "obio", NULL); + + /* + * attach the PCI bus + */ + pba.pba_memt = sc->sc_iot; + pba.pba_iot = sc->sc_iot;; + pba.pba_dmat = sc->sc_dmat; + pba.pba_dmat64 = NULL; + 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_ia(&sc->sc_dev, "pcibus", &pba, pcibusprint); + +} + +static int +obio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) +{ + struct obio_softc * const sc = device_private(parent); + struct obio_attach_args oa; + + /* Set up the attach args. */ + if (cf->cf_loc[OBIOCF_NOBYTEACC] == 1) { +#if 0 + if (cf->cf_loc[OBIOCF_MULT] == 1) + oa.obio_iot = &nobyteacc_bs_tag; + else +#endif + panic("nobyteacc specified for device with " + "non-byte multiplier\n"); + } else { + switch (cf->cf_loc[OBIOCF_MULT]) { + case 1: + oa.obio_iot = &gemini_bs_tag; + break; +#if 0 + case 2: + oa.obio_iot = &gemini_a2x_bs_tag; + break; +#endif + case 4: + oa.obio_iot = &gemini_a4x_bs_tag; + break; + default: + panic("Unsupported obio bus multiplier."); + break; + } + } + + oa.obio_dmat = sc->sc_dmat; + oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; + oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; + oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; + oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; + + if (config_match(parent, cf, &oa)) { + config_attach(parent, cf, &oa, obio_print); + return 0; /* love it */ + } + + return UNCONF; /* NG */ +} + +static int +obio_find(device_t parent, cfdata_t cf, const int *ldesc, void *aux) +{ + struct obio_attach_args * const oa = aux; + + if (oa->obio_addr != OBIOCF_ADDR_DEFAULT + && oa->obio_addr != cf->cf_loc[OBIOCF_ADDR]) + return 0; + if (oa->obio_size != OBIOCF_SIZE_DEFAULT + && oa->obio_size != cf->cf_loc[OBIOCF_SIZE]) + return 0; + if (oa->obio_intr != OBIOCF_INTR_DEFAULT + && oa->obio_intr != cf->cf_loc[OBIOCF_INTR]) + return 0; + if (oa->obio_intrbase != OBIOCF_INTRBASE_DEFAULT + && oa->obio_intrbase != cf->cf_loc[OBIOCF_INTRBASE]) + return 0; + + /* Set up the attach args. */ + if (cf->cf_loc[OBIOCF_NOBYTEACC] == 1) { +#if 0 + if (cf->cf_loc[OBIOCF_MULT] == 1) + oa->obio_iot = &nobyteacc_bs_tag; + else +#endif + panic("nobyteacc specified for device with " + "non-byte multiplier\n"); + } else { + switch (cf->cf_loc[OBIOCF_MULT]) { + case 1: + oa->obio_iot = &gemini_bs_tag; + break; +#if 0 + case 2: + oa->obio_iot = &gemini_a2x_bs_tag; + break; +#endif + case 4: + oa->obio_iot = &gemini_a4x_bs_tag; + break; + default: + panic("Unsupported obio bus multiplier."); + break; + } + } + oa->obio_addr = cf->cf_loc[OBIOCF_ADDR]; + oa->obio_size = cf->cf_loc[OBIOCF_SIZE]; + oa->obio_intr = cf->cf_loc[OBIOCF_INTR]; + oa->obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; + + return config_match(parent, cf, oa); +} + +#if NGEMINIICU == 0 +#error no geminiicu present in config file +#endif + +static const struct { + const char *name; + bus_addr_t addr; + bool required; +} critical_devs[] = { + { .name = "geminiicu0", .addr = 0x48000000, .required = true }, + { .name = "geminiwdt0", .addr = 0x41000000, .required = true }, + { .name = "geminitmr0", .addr = 0x43000000, .required = true }, + { .name = "geminitmr1", .addr = 0x43000000, .required = true }, + { .name = "geminitmr2", .addr = 0x43000000, .required = true }, + { .name = "com0", .addr = 0x42000000, .required = true }, +}; + +static void +obio_attach_critical(struct obio_softc *sc) +{ + struct obio_attach_args oa; + cfdata_t cf; + size_t i; + + for (i = 0; i < __arraycount(critical_devs); i++) { + oa.obio_iot = sc->sc_iot; + oa.obio_dmat = sc->sc_dmat; + + oa.obio_addr = critical_devs[i].addr; + oa.obio_size = OBIOCF_SIZE_DEFAULT; + oa.obio_intr = OBIOCF_INTR_DEFAULT; + oa.obio_intrbase = OBIOCF_INTRBASE_DEFAULT; + +#if 0 + if (oa.obio_addr != OBIOCF_ADDR_DEFAULT + && (oa.obio_addr < sc->sc_base + || oa.obio_addr >= sc->sc_base + sc->sc_size)) + continue; +#endif + + cf = config_search_ia(obio_find, &sc->sc_dev, "obio", &oa); + if (cf == NULL && critical_devs[i].required) + panic("obio_attach_critical: failed to find %s!", + critical_devs[i].name); + + oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; + oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; + oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; + oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; + config_attach(&sc->sc_dev, cf, &oa, obio_print); + } +} + +static int +obio_print(void *aux, const char *name) +{ + struct obio_attach_args *oa = (struct obio_attach_args*)aux; + + if (oa->obio_addr != OBIOCF_ADDR_DEFAULT) { + aprint_normal(" addr 0x%08lx", oa->obio_addr); + if (oa->obio_size != OBIOCF_SIZE_DEFAULT) + aprint_normal("-0x%08lx", + oa->obio_addr + oa->obio_size-1); + } + if (oa->obio_intr != OBIOCF_INTR_DEFAULT) + aprint_normal(" intr %d", oa->obio_intr); + if (oa->obio_intrbase != OBIOCF_INTRBASE_DEFAULT) + aprint_normal(" intrbase %d", oa->obio_intrbase); + + return UNCONF; +} diff --git a/sys/arch/arm/gemini/gemini_obiovar.h b/sys/arch/arm/gemini/gemini_obiovar.h new file mode 100644 index 00000000000..fdddf3a722f --- /dev/null +++ b/sys/arch/arm/gemini/gemini_obiovar.h @@ -0,0 +1,67 @@ +/* $NetBSD: gemini_obiovar.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: omap2_obiovar.h,v 1.1 2008/08/27 11:03:10 matt Exp + */ + +/* + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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 _ARM_GEMINI_OBIOVAR_H_ +#define _ARM_GEMINI_OBIOVAR_H_ + +#include <dev/pci/pcivar.h> +#include <arm/pci_machdep.h> + +struct obio_attach_args { + bus_space_tag_t obio_iot; + bus_addr_t obio_addr; + bus_size_t obio_size; + int obio_intr; + bus_dma_tag_t obio_dmat; + unsigned int obio_mult; + unsigned int obio_intrbase; +}; + +typedef struct obio_softc { + struct device sc_dev; + bus_dma_tag_t sc_dmat; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_addr_t sc_base; + bus_size_t sc_size; + + /* Bus space, DMA, and PCI tags for the PCI bus. */ + bus_space_handle_t sc_pcicfg_ioh; + struct arm32_bus_dma_tag sc_pci_dmat; + struct arm32_pci_chipset sc_pci_chipset; +} obio_softc_t; + +extern void gemini_pci_init(pci_chipset_tag_t, void *); + +#endif /* _ARM_OMAP_GEMINI_OBIOVAR_H_ */ diff --git a/sys/arch/arm/gemini/gemini_pci.c b/sys/arch/arm/gemini/gemini_pci.c new file mode 100644 index 00000000000..913211eea35 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_pci.c @@ -0,0 +1,457 @@ +/* $NetBSD: gemini_pci.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: i80312_pci.c,v 1.9 2005/12/11 12:16:51 christos Exp + */ + +/* + * Copyright (c) 2001 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 i80312 Companion I/O chip. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_pci.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/extent.h> +#include <sys/malloc.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/pic/picvar.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_pcivar.h> +#include <arm/gemini/gemini_obiovar.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> +#include <dev/pci/pciconf.h> + +#include <machine/pci_machdep.h> + +#include "opt_pci.h" +#include "pci.h" + +void gemini_pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int gemini_pci_bus_maxdevs(void *, int); +pcitag_t gemini_pci_make_tag(void *, int, int, int); +void gemini_pci_decompose_tag(void *, pcitag_t, int *, int *, + int *); +pcireg_t gemini_pci_conf_read(void *, pcitag_t, int); +void gemini_pci_conf_write(void *, pcitag_t, int, pcireg_t); +int gemini_pci_conf_hook(pci_chipset_tag_t, int, int, int, + pcireg_t); + +int gemini_pci_intr_map(struct pci_attach_args *, + pci_intr_handle_t *); +const char *gemini_pci_intr_string(void *, pci_intr_handle_t); +const struct evcnt *gemini_pci_intr_evcnt(void *, pci_intr_handle_t); +void *gemini_pci_intr_establish(void *, pci_intr_handle_t, + int, int (*)(void *), void *); +void gemini_pci_intr_disestablish(void *, void *); +int gemini_pci_intr_handler(void *v); + +#define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit) +#define PCI_CONF_UNLOCK(s) restore_interrupts((s)) + +int gemini_pci_debug=0; + +struct gemini_pci_intrq { + SIMPLEQ_ENTRY(gemini_pci_intrq) iq_q; + int (*iq_func)(void *); + void *iq_arg; + void *iq_ih; +}; + +static SIMPLEQ_HEAD(, gemini_pci_intrq) gemini_pci_intrq = + SIMPLEQ_HEAD_INITIALIZER(gemini_pci_intrq); + +static inline int +gemini_pci_intrq_empty(void) +{ + return SIMPLEQ_EMPTY(&gemini_pci_intrq); +} + +static inline void * +gemini_pci_intrq_insert(void *ih, int (*func)(void *), void *arg) +{ + struct gemini_pci_intrq *iqp; + + iqp = malloc(sizeof(*iqp), M_DEVBUF, M_NOWAIT|M_ZERO); + if (iqp == NULL) { + printf("gemini_pci_intrq_insert: malloc failed\n"); + return NULL; + } + + iqp->iq_func = func; + iqp->iq_arg = arg; + iqp->iq_ih = ih; + SIMPLEQ_INSERT_TAIL(&gemini_pci_intrq, iqp, iq_q); + + return (void *)iqp; +} + +static inline void +gemini_pci_intrq_remove(void *cookie) +{ + struct gemini_pci_intrq *iqp; + + SIMPLEQ_FOREACH(iqp, &gemini_pci_intrq, iq_q) { + if ((void *)iqp == cookie) { + SIMPLEQ_REMOVE(&gemini_pci_intrq, + iqp, gemini_pci_intrq, iq_q); + free(iqp, M_DEVBUF); + return; + } + } +} + +static inline int +gemini_pci_intrq_dispatch(void) +{ + struct gemini_pci_intrq *iqp; + + SIMPLEQ_FOREACH(iqp, &gemini_pci_intrq, iq_q) { + (*iqp->iq_func)(iqp->iq_arg); + } + + return 1; +} + +void +gemini_pci_init(pci_chipset_tag_t pc, void *cookie) +{ +#if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) + struct obio_softc *sc = cookie; + struct extent *ioext, *memext; +#endif + + pc->pc_conf_v = cookie; + pc->pc_attach_hook = gemini_pci_attach_hook; + pc->pc_bus_maxdevs = gemini_pci_bus_maxdevs; + pc->pc_make_tag = gemini_pci_make_tag; + pc->pc_decompose_tag = gemini_pci_decompose_tag; + pc->pc_conf_read = gemini_pci_conf_read; + pc->pc_conf_write = gemini_pci_conf_write; + + pc->pc_intr_v = cookie; + pc->pc_intr_map = gemini_pci_intr_map; + pc->pc_intr_string = gemini_pci_intr_string; + pc->pc_intr_evcnt = gemini_pci_intr_evcnt; + pc->pc_intr_establish = gemini_pci_intr_establish; + pc->pc_intr_disestablish = gemini_pci_intr_disestablish; + + pc->pc_conf_hook = gemini_pci_conf_hook; + + /* + * initialize copy of CFG_CMD + */ + sc->sc_pci_chipset.pc_cfg_cmd = + gemini_pci_conf_read(sc, 0, GEMINI_PCI_CFG_CMD); + +#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. + */ + + aprint_normal("%s: configuring Secondary PCI bus\n", + sc->sc_dev.dv_xname); + + /* + * creating an BOGUS extent, don't use it! + */ + ioext = extent_create("pciio", + GEMINI_PCIIO_BASE, + GEMINI_PCIIO_BASE + GEMINI_PCIIO_SIZE - 1, + M_DEVBUF, NULL, 0, EX_NOWAIT); + + /* + * XXX PCI mem addr should be inherited ? + */ + memext = extent_create("pcimem", + GEMINI_PCIMEM_BASE, + GEMINI_PCIMEM_BASE + GEMINI_PCIMEM_SIZE - 1, + M_DEVBUF, NULL, 0, EX_NOWAIT); + + pci_configure_bus(pc, ioext, memext, NULL, 0, arm_dcache_align); + + gemini_pci_conf_write(sc, 0, GEMINI_PCI_CFG_REG_MEM1, + PCI_CFG_REG_MEM_BASE(GEMINI_DRAM_BASE) + | gemini_pci_cfg_reg_mem_size(GEMINI_DRAM_SIZE)); + + 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) +{ +} + +int +gemini_pci_conf_hook(pci_chipset_tag_t pc, int bus, int device, int function, pcireg_t id) +{ + int rv; + + rv = PCI_CONF_ALL; + + return rv; +} + +void +gemini_pci_attach_hook(struct device *parent, struct device *self, + struct pcibus_attach_args *pba) +{ + /* Nothing to do. */ +} + +int +gemini_pci_bus_maxdevs(void *v, int busno) +{ + return (32); +} + +pcitag_t +gemini_pci_make_tag(void *v, int b, int d, int f) +{ + return ((b << 16) | (d << 11) | (f << 8)); +} + +void +gemini_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_addr_val; + int ps_b, ps_d, ps_f; +}; + +static int +gemini_pci_conf_setup(struct obio_softc *sc, pcitag_t tag, int offset, + struct pciconf_state *ps) +{ + gemini_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); + + ps->ps_addr_val = + PCI_CFG_CMD_ENB + | PCI_CFG_CMD_BUSn(ps->ps_b) + | PCI_CFG_CMD_DEVn(ps->ps_d) + | PCI_CFG_CMD_FUNCn(ps->ps_f) + | PCI_CFG_CMD_REGn(offset); + + return (0); +} + +pcireg_t +gemini_pci_conf_read(void *v, pcitag_t tag, int offset) +{ + struct obio_softc *sc = v; + struct pciconf_state ps; + vaddr_t va; + pcireg_t rv; + u_int s; + + if (gemini_pci_conf_setup(sc, tag, offset, &ps)) + return ((pcireg_t) -1); + + PCI_CONF_LOCK(s); + + if (sc->sc_pci_chipset.pc_cfg_cmd != ps.ps_addr_val) { + sc->sc_pci_chipset.pc_cfg_cmd = ps.ps_addr_val; + bus_space_write_4(sc->sc_iot, sc->sc_pcicfg_ioh, + GEMINI_PCI_CFG_CMD, ps.ps_addr_val); + } + + va = (vaddr_t) bus_space_vaddr(sc->sc_iot, sc->sc_pcicfg_ioh); + if (badaddr_read((void *) (va + GEMINI_PCI_CFG_DATA), sizeof(rv), &rv)) { + /* + * XXX Clear the Master Abort + */ +#if 1 + printf("conf_read: %d/%d/%d bad address\n", + ps.ps_b, ps.ps_d, ps.ps_f); +#endif + rv = (pcireg_t) -1; + } + + PCI_CONF_UNLOCK(s); + + if (gemini_pci_debug) { + printf("conf_read: tag %#lx, %d/%d/%d, ps_addr_val %#x, rv %#x\n", + tag, ps.ps_b, ps.ps_d, ps.ps_f, ps.ps_addr_val, rv); + Debugger(); + } + + return (rv); +} + +void +gemini_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) +{ + struct obio_softc *sc = v; + struct pciconf_state ps; + u_int s; + + if (gemini_pci_conf_setup(sc, tag, offset, &ps)) + return; + + PCI_CONF_LOCK(s); + + if (sc->sc_pci_chipset.pc_cfg_cmd != ps.ps_addr_val) { + sc->sc_pci_chipset.pc_cfg_cmd = ps.ps_addr_val; + bus_space_write_4(sc->sc_iot, sc->sc_pcicfg_ioh, + GEMINI_PCI_CFG_CMD, ps.ps_addr_val); + } + + bus_space_write_4(sc->sc_iot, sc->sc_pcicfg_ioh, + GEMINI_PCI_CFG_DATA, val); + + PCI_CONF_UNLOCK(s); +} + +int +gemini_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + int irq; + + irq = 8; + + *ihp = irq; + return 0; +} + +const char * +gemini_pci_intr_string(void *v, pci_intr_handle_t ih) +{ + const char *name = "pci"; + + return (name); +} + +const struct evcnt * +gemini_pci_intr_evcnt(void *v, pci_intr_handle_t ih) +{ + return NULL; +} + +void * +gemini_pci_intr_establish(void *v, pci_intr_handle_t pci_ih, int ipl, + int (*func)(void *), void *arg) +{ + pcireg_t r; + void *ih=NULL; + int irq; + void *cookie; + + irq = (int)pci_ih; + + r = gemini_pci_conf_read(v, 0, GEMINI_PCI_CFG_REG_CTL2); + r |= CFG_REG_CTL2_INTMASK_INT_ABCD; + gemini_pci_conf_write(v, 0, GEMINI_PCI_CFG_REG_CTL2, r); + + if (gemini_pci_intrq_empty()) + ih = intr_establish(irq, ipl, IST_LEVEL_HIGH, + gemini_pci_intr_handler, v); + + cookie = gemini_pci_intrq_insert(ih, func, arg); + if (cookie == NULL) { + if (gemini_pci_intrq_empty()) + intr_disestablish(ih); + } + + return cookie; +} + +void +gemini_pci_intr_disestablish(void *v, void *cookie) +{ + pcireg_t r; + struct gemini_pci_intrq *iqp = (struct gemini_pci_intrq *)cookie;; + void *ih = iqp->iq_ih; + + gemini_pci_intrq_remove(cookie); + if (gemini_pci_intrq_empty()) { + r = gemini_pci_conf_read(v, 0, GEMINI_PCI_CFG_REG_CTL2); + r &= ~CFG_REG_CTL2_INTMASK_INT_ABCD; + gemini_pci_conf_write(v, 0, GEMINI_PCI_CFG_REG_CTL2, r); + intr_disestablish(ih); + } +} + +int +gemini_pci_intr_handler(void *v) +{ + pcireg_t r; + int rv; + + /* + * dispatch PCI device interrupt handlers + */ + rv = gemini_pci_intrq_dispatch(); + + /* + * ack Gemini PCI interrupts + */ + r = gemini_pci_conf_read(v, 0, GEMINI_PCI_CFG_REG_CTL2); + gemini_pci_conf_write(v, 0, GEMINI_PCI_CFG_REG_CTL2, r); + + return rv; +} + diff --git a/sys/arch/arm/gemini/gemini_pcivar.h b/sys/arch/arm/gemini/gemini_pcivar.h new file mode 100644 index 00000000000..dda16f1c734 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_pcivar.h @@ -0,0 +1,10 @@ +/* $NetBSD: gemini_pcivar.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +#ifndef _ARM_GEMINI_PCI_VAR_H_ +#define _ARM_GEMINI_PCI_VAR_H_ + +#include <dev/pci/pcivar.h> + +extern void gemini_pci_init(pci_chipset_tag_t, void *); + +#endif /* _ARM_GEMINI_PCI_VAR_H_ */ diff --git a/sys/arch/arm/gemini/gemini_reg.h b/sys/arch/arm/gemini/gemini_reg.h new file mode 100644 index 00000000000..37996733fcd --- /dev/null +++ b/sys/arch/arm/gemini/gemini_reg.h @@ -0,0 +1,280 @@ +/* $NetBSD: gemini_reg.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +#ifndef _ARM_GEMINI_REG_H_ +#define _ARM_GEMINI_REG_H_ + +/* + * Register definitions for Gemini SOC + */ + +#include "opt_gemini.h" +#include <machine/endian.h> +#include <sys/cdefs.h> + +#if defined(SL3516) +/* + * Gemini SL3516 memory map + */ +#define GEMINI_SRAM_BASE 0x00000000 /* Internal SRAM */ +#define GEMINI_SRAM_SIZE 0x10000000 /* 128 MB */ +#define GEMINI_DRAM_BASE 0x10000000 /* DRAM (via DDR Control Module) */ +#define GEMINI_DRAM_SIZE 0x20000000 /* 512 MB */ +#define GEMINI_FLASH_BASE 0x30000000 /* DRAM (via DDR Control Module) */ +#define GEMINI_FLASH_SIZE 0x10000000 /* 128 MB */ + +/* + * Gemini SL3516 device map + */ +#define GEMINI_GLOBAL_BASE 0x40000000 /* Global registers */ +#define GEMINI_WATCHDOG_BASE 0x41000000 /* Watch dog timer module */ +#define GEMINI_UART_BASE 0x42000000 /* UART control module */ +#define GEMINI_UART_SIZE 0x20 +#define GEMINI_TIMER_BASE 0x43000000 /* Timer module */ +#define GEMINI_LCD_BASE 0x44000000 /* LCD Interface module */ +#define GEMINI_RTC_BASE 0x45000000 /* Real Time Clock module */ +#define GEMINI_SATA_BASE 0x46000000 /* Serial ATA module */ +#define GEMINI_LPCHC_BASE 0x47000000 /* LPC Hosr Controller module */ +#define GEMINI_LPCP_BASE 0x47800000 /* LPC Peripherals IO space */ +#define GEMINI_IC0_BASE 0x48000000 /* Interrupt Control module #0 */ +#define GEMINI_IC1_BASE 0x49000000 /* Interrupt Control module #1 */ +#define GEMINI_SSPC_BASE 0x4a000000 /* Synchronous Serial Port Control module */ +#define GEMINI_PWRC_BASE 0x4b000000 /* Power Control module */ +#define GEMINI_CIR_BASE 0x4c000000 /* CIR Control module */ +#define GEMINI_GPIO0_BASE 0x4d000000 /* GPIO module #0 */ +#define GEMINI_GPIO1_BASE 0x4e000000 /* GPIO module #1 */ +#define GEMINI_GPIO2_BASE 0x4f000000 /* GPIO module #2 */ +#define GEMINI_PCICFG_BASE 0x50000000 /* PCI IO, configuration and control space */ +#define GEMINI_PCIIO_BASE 0x50001000 /* PCI IO space */ +#define GEMINI_PCIIO_SIZE 0x0007f000 /* PCI IO space size */ +#define GEMINI_PCIMEM_BASE 0x58000000 /* PCI Memory space */ +#define GEMINI_PCIMEM_SIZE 0x08000000 /* PCI Memory space size */ +#define GEMINI_NGC_BASE 0x60000000 /* NetEngine & GMAC Configuration registers */ +#define GEMINI_SDC_BASE 0x62000000 /* Security DMA and Configure registers */ +#define GEMINI_MIDE_BASE 0x63000000 /* Multi IDE registers */ +#define GEMINI_RXDC_BASE 0x64000000 /* RAID XOR DMA Configuration registers */ +#define GEMINI_FLASHC_BASE 0x65000000 /* Flash Controller registers */ +#define GEMINI_DRAMC_BASE 0x66000000 /* DRAM (DDR/SDR) Controller registers */ +#define GEMINI_GDMA_BASE 0x67000000 /* General DMA registers */ +#define GEMINI_USB0_BASE 0x68000000 /* USB #0 registers */ +#define GEMINI_USB1_BASE 0x69000000 /* USB #1 registers */ +#define GEMINI_TVE_BASE 0x6a000000 /* TVE registers */ +#define GEMINI_SRAM_SHADOW_BASE 0x70000000 /* Shadow of internal SRAM */ + +/* + * Gemini SL3516 Watchdog device register offsets and bits + */ +#define GEMINI_WDT_WDCOUNTER 0x0 /* Watchdog Timer Counter */ /* ro */ +#define GEMINI_WDT_WDLOAD 0x4 /* Watchdog Timer Load */ /* rw */ +#define WDT_WDLOAD_DFLT 0x3EF1480 /* default Load reg val */ +#define GEMINI_WDT_WDRESTART 0x8 /* Watchdog Timer Restart */ /* wo */ +#define WDT_WDRESTART_Resv __BITS(31,16) +#define WDT_WDRESTART_RST __BITS(15,0) +#define WDT_WDRESTART_MAGIC 0x5ab9 +#define GEMINI_WDT_WDCR 0xc /* Watchdog Timer Control */ /* rw */ +#define WDT_WDCR_Resv __BITS(31,5) +#define WDT_WDCR_CLKSRC __BIT(4) /* Timer Clock Source: 5 MHz clock */ +#define WDCR_CLKSRC_PCLK (0 << 4) /* Timer Clock Source: PCLK (APB CLK) */ +#define WDCR_CLKSRC_5MHZ (1 << 4) /* Timer Clock Source: 5 MHz clock */ +#define WDT_WDCR_EXTSIG_ENB __BIT(3) /* Timer External Signal Enable */ +#define WDT_WDCR_INTR_ENB __BIT(2) /* Timer System Interrupt Enable */ +#define WDT_WDCR_RESET_ENB __BIT(1) /* Timer System Reset Enable */ +#define WDT_WDCR_ENB __BIT(0) /* Timer Enable */ +#define GEMINI_WDT_WDSTATUS 0x10 /* Watchdog Timer Status */ /* ro */ +#define WDT_WDSTATUS_Resv __BITS(31,1) +#define WDT_WDSTATUS_ZERO __BIT(0) /* non-zero if timer counted down to zero! */ +#define GEMINI_WDT_WDCLEAR 0x14 /* Watchdog Timer Clear */ /* wo */ +#define WDT_WDCLEAR_Resv __BITS(31,1) +#define WDT_WDCLEAR_CLEAR __BIT(0) /* write this bit to clear Status */ +#define GEMINI_WDT_WDINTERLEN 0x18 /* Watchdog Timer Interrupt Length */ /* rw */ + /* duration of signal assertion, */ + /* in units of clock cycles */ +#define WDT_WDINTERLEN_DFLT 0xff /* default is 256 cycles */ + + +/* + * Gemini SL3516 Timer device register offsets and bits + * + * have 3 timers, here indexed 1<=(n)<=3 as in the doc + * each has 4 sequential 32bit rw regs + */ +#define GEMINI_NTIMERS 3 +#define GEMINI_TIMERn_REG(n, o) ((((n) - 1) * 0x10) + (o)) +#define GEMINI_TIMERn_COUNTER(n) GEMINI_TIMERn_REG((n), 0x0) /* rw */ +#define GEMINI_TIMERn_LOAD(n) GEMINI_TIMERn_REG((n), 0x4) /* rw */ +#define GEMINI_TIMERn_MATCH1(n) GEMINI_TIMERn_REG((n), 0x08) /* rw */ +#define GEMINI_TIMERn_MATCH2(n) GEMINI_TIMERn_REG((n), 0x0C) /* rw */ +#define GEMINI_TIMER_TMCR 0x30 /* rw */ +#define TIMER_TMCR_Resv __BITS(31,12) +#define TIMER_TMCR_TMnUPDOWN(n) __BIT(9 + (n) - 1) +#define TIMER_TMCR_TMnOFENABLE(n) __BIT((((n) - 1) * 3) + 2) +#define TIMER_TMCR_TMnCLOCK(n) __BIT((((n) - 1) * 3) + 1) +#define TIMER_TMCR_TMnENABLE(n) __BIT((((n) - 1) * 3) + 0) +#define GEMINI_TIMER_TMnCR_MASK(n) \ + ( TIMER_TMCR_TMnUPDOWN(n) \ + | TIMER_TMCR_TMnOFENABLE(n) \ + | TIMER_TMCR_TMnCLOCK(n) \ + | TIMER_TMCR_TMnENABLE(n) ) +#define GEMINI_TIMER_INTRSTATE 0x34 /* rw */ +#define TIMER_INTRSTATE_Resv __BITS(31,9) +#define TIMER_INTRSTATE_TMnOVFLOW(n) __BIT((((n) -1) * 3) + 2) +#define TIMER_INTRSTATE_TMnMATCH2(n) __BIT((((n) -1) * 3) + 1) +#define TIMER_INTRSTATE_TMnMATCH1(n) __BIT((((n) -1) * 3) + 0) +#define GEMINI_TIMER_INTRMASK 0x38 /* rw */ +#define TIMER_INTRMASK_Resv __BITS(31,9) +#define TIMER_INTRMASK_TMnOVFLOW(n) __BIT((((n) -1) * 3) + 2) +#define TIMER_INTRMASK_TMnMATCH2(n) __BIT((((n) -1) * 3) + 1) +#define TIMER_INTRMASK_TMnMATCH1(n) __BIT((((n) -1) * 3) + 0) +#define GEMINI_TIMERn_INTRMASK(n) \ + ( TIMER_INTRMASK_TMnOVFLOW(n) \ + | TIMER_INTRMASK_TMnMATCH2(n) \ + | TIMER_INTRMASK_TMnMATCH1(n) ) + +/* + * Gemini SL3516 Interrupt Controller device register offsets and bits + */ +#define GEMINI_ICU_IRQ_SOURCE 0x0 /* ro */ +#define GEMINI_ICU_IRQ_ENABLE 0x4 /* rw */ +#define GEMINI_ICU_IRQ_CLEAR 0x8 /* wo */ +#define GEMINI_ICU_IRQ_TRIGMODE 0xc /* rw */ +#define ICU_IRQ_TRIGMODE_EDGE 1 /* edge triggered */ +#define ICU_IRQ_TRIGMODE_LEVEL 0 /* level triggered */ +#define GEMINI_ICU_IRQ_TRIGLEVEL 0x10 /* rw */ +#define ICU_IRQ_TRIGLEVEL_LO 1 /* active low or falling edge */ +#define ICU_IRQ_TRIGLEVEL_HI 0 /* active high or rising edge */ +#define GEMINI_ICU_IRQ_STATUS 0x14 /* ro */ + +#define GEMINI_ICU_FIQ_SOURCE 0x20 /* ro */ +#define GEMINI_ICU_FIQ_ENABLE 0x24 /* rw */ +#define GEMINI_ICU_FIQ_CLEAR 0x28 /* wo */ +#define GEMINI_ICU_FIQ_TRIGMODE 0x2c /* rw */ +#define GEMINI_ICU_FIQ_TRIGLEVEL 0x30 /* rw */ +#define GEMINI_ICU_FIQ_STATUS 0x34 /* ro */ + +#define GEMINI_ICU_REVISION 0x50 /* ro */ +#define GEMINI_ICU_INPUT_NUM 0x54 /* ro */ +#define ICU_INPUT_NUM_RESV __BITS(31,16) +#define ICU_INPUT_NUM_IRQ __BITS(15,8) +#define ICU_INPUT_NUM_FIQ __BITS(7,0) +#define GEMINI_ICU_IRQ_DEBOUNCE 0x58 /* ro */ +#define GEMINI_ICU_FIQ_DEBOUNCE 0x5c /* ro */ + + +/* + * Gemini PCI controller register offsets and bits + */ +#define GEMINI_PCI_IOSIZE 0x00 /* I/O Space Size */ /* rw */ +#define GEMINI_PCI_PROT 0x04 /* AHB Protection */ /* rw */ +#define GEMINI_PCI_PCICTRL 0x08 /* PCI Control Signal */ /* rw */ +#define GEMINI_PCI_ERREN 0x0c /* Soft Reset Counter and + * Response Error Enable */ /* rw */ +#define GEMINI_PCI_SOFTRST 0x10 /* Soft Reset */ +#define GEMINI_PCI_CFG_CMD 0x28 /* PCI Configuration Command */ /* rw */ +#define PCI_CFG_CMD_ENB __BIT(31) /* Enable */ +#define PCI_CFG_CMD_RESa __BITS(30,24) +#define PCI_CFG_CMD_BUSNO __BITS(23,16) /* Bus Number */ +#define PCI_CFG_CMD_BUSn(n) (((n) << 16) & PCI_CFG_CMD_BUSNO) +#define PCI_CFG_CMD_DEVNO __BITS(15,11) /* Device Number */ +#define PCI_CFG_CMD_DEVn(n) (((n) << 11) & PCI_CFG_CMD_DEVNO) +#define PCI_CFG_CMD_FUNCNO __BITS(10,8) /* Function Number */ +#define PCI_CFG_CMD_FUNCn(n) (((n) << 8) & PCI_CFG_CMD_FUNCNO) +#define PCI_CFG_CMD_REGNO __BITS(7,2) /* Register Number */ +#define PCI_CFG_CMD_REGn(n) (((n) << 0) & PCI_CFG_CMD_REGNO) +#define PCI_CFG_CMD_RESb __BITS(1,0) +#define PCI_CFG_CMD_RESV \ + (PCI_CFG_CMD_RESa | PCI_CFG_CMD_RESb) +#define GEMINI_PCI_CFG_DATA 0x2c /* PCI Configuration Data */ /* rw */ + +/* + * Gemini machine dependent PCI config registers + */ +#define GEMINI_PCI_CFG_REG_PMR1 0x40 /* Power Management 1 */ /* rw */ +#define GEMINI_PCI_CFG_REG_PMR2 0x44 /* Power Management 2 */ /* rw */ +#define GEMINI_PCI_CFG_REG_CTL1 0x48 /* Control 1 */ /* rw */ +#define GEMINI_PCI_CFG_REG_CTL2 0x4c /* Control 2 */ /* rw */ +#define PCI_CFG_REG_CTL2_INTSTS __BITS(31,28) +#define CFG_REG_CTL2_INTSTS_INTD __BIT(28 + 3) +#define CFG_REG_CTL2_INTSTS_INTC __BIT(28 + 2) +#define CFG_REG_CTL2_INTSTS_INTB __BIT(28 + 1) +#define CFG_REG_CTL2_INTSTS_INTA __BIT(28 + 0) +#define PCI_CFG_REG_CTL2_INTMASK __BITS(27,16) +#define CFG_REG_CTL2_INTMASK_CMDERR __BIT(16 + 11) +#define CFG_REG_CTL2_INTMASK_PARERR __BIT(16 + 10) +#define CFG_REG_CTL2_INTMASK_INTD __BIT(16 + 9) +#define CFG_REG_CTL2_INTMASK_INTC __BIT(16 + 8) +#define CFG_REG_CTL2_INTMASK_INTB __BIT(16 + 7) +#define CFG_REG_CTL2_INTMASK_INTA __BIT(16 + 6) +#define CFG_REG_CTL2_INTMASK_INT_ABCD __BITS(16+9,16+6) +#define CFG_REG_CTL2_INTMASK_MABRT_RX __BIT(16 + 5) +#define CFG_REG_CTL2_INTMASK_TABRT_RX __BIT(16 + 4) +#define CFG_REG_CTL2_INTMASK_TABRT_TX __BIT(16 + 3) +#define CFG_REG_CTL2_INTMASK_RETRY4 __BIT(16 + 2) +#define CFG_REG_CTL2_INTMASK_SERR_RX __BIT(16 + 1) +#define CFG_REG_CTL2_INTMASK_PERR_RX __BIT(16 + 0) +#define PCI_CFG_REG_CTL2_RESa __BIT(15) +#define PCI_CFG_REG_CTL2_MSTPRI __BITS(14,8) +#define CFG_REG_CTL2_MSTPRI_REQn(n) __BIT(8 + (n)) +#define PCI_CFG_REG_CTL2_RESb __BITS(7,4) +#define PCI_CFG_REG_CTL2_TRDYW __BITS(3,0) +#define PCI_CFG_REG_CTL2_RESV \ + (PCI_CFG_REG_CTL2_RESa | PCI_CFG_REG_CTL2_RESb) +#define GEMINI_PCI_CFG_REG_MEM1 0x50 /* Memory 1 Base */ /* rw */ +#define GEMINI_PCI_CFG_REG_MEM2 0x54 /* Memory 2 Base */ /* rw */ +#define GEMINI_PCI_CFG_REG_MEM3 0x58 /* Memory 3 Base */ /* rw */ +#define PCI_CFG_REG_MEM_BASE_MASK __BITS(31,20) +#define PCI_CFG_REG_MEM_BASE(base) ((base) & PCI_CFG_REG_MEM_BASE_MASK) +#define PCI_CFG_REG_MEM_SIZE_MASK __BITS(19,16) +#define PCI_CFG_REG_MEM_SIZE_1MB (0x0 << 16) +#define PCI_CFG_REG_MEM_SIZE_2MB (0x1 << 16) +#define PCI_CFG_REG_MEM_SIZE_4MB (0x2 << 16) +#define PCI_CFG_REG_MEM_SIZE_8MB (0x3 << 16) +#define PCI_CFG_REG_MEM_SIZE_16MB (0x4 << 16) +#define PCI_CFG_REG_MEM_SIZE_32MB (0x5 << 16) +#define PCI_CFG_REG_MEM_SIZE_64MB (0x6 << 16) +#define PCI_CFG_REG_MEM_SIZE_128MB (0x7 << 16) +#define PCI_CFG_REG_MEM_SIZE_256MB (0x8 << 16) +#define PCI_CFG_REG_MEM_SIZE_512MB (0x9 << 16) +#define PCI_CFG_REG_MEM_SIZE_1GB (0xa << 16) +#define PCI_CFG_REG_MEM_SIZE_2GB (0xb << 16) +#define PCI_CFG_REG_MEM_RESV __BITS(19,16) + +#ifndef _LOCORE +static inline unsigned int +gemini_pci_cfg_reg_mem_size(size_t sz) +{ + switch (sz) { + case (1 << 20): + return PCI_CFG_REG_MEM_SIZE_1MB; + case (2 << 20): + return PCI_CFG_REG_MEM_SIZE_2MB; + case (4 << 20): + return PCI_CFG_REG_MEM_SIZE_4MB; + case (8 << 20): + return PCI_CFG_REG_MEM_SIZE_8MB; + case (16 << 20): + return PCI_CFG_REG_MEM_SIZE_16MB; + case (32 << 20): + return PCI_CFG_REG_MEM_SIZE_32MB; + case (64 << 20): + return PCI_CFG_REG_MEM_SIZE_64MB; + case (128 << 20): + return PCI_CFG_REG_MEM_SIZE_128MB; + case (256 << 20): + return PCI_CFG_REG_MEM_SIZE_256MB; + case (512 << 20): + return PCI_CFG_REG_MEM_SIZE_512MB; + case (1024 << 20): + return PCI_CFG_REG_MEM_SIZE_1GB; + case (2048 << 20): + return PCI_CFG_REG_MEM_SIZE_2GB; + default: + panic("gemini_pci_cfg_reg_mem_size: bad size %#lx\n", sz); + } + /* NOTREACHED */ +} +#endif /* _LOCORE */ + +#else +# error unknown gemini cpu type +#endif + +#endif /* _ARM_GEMINI_REG_H_ */ diff --git a/sys/arch/arm/gemini/gemini_space.c b/sys/arch/arm/gemini/gemini_space.c new file mode 100644 index 00000000000..b7dc7a9c450 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_space.c @@ -0,0 +1,277 @@ +/* $NetBSD: gemini_space.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: pxa2x0_space.c,v 1.8 2005/11/24 13:08:32 yamt 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. + */ +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ichiro FUKUHARA. + * + * 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 by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTORS 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 Gemini processor. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_space.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(gemini); +bs_protos(generic); +bs_protos(generic_armv4); +bs_protos(bs_notimpl); + +struct bus_space gemini_bs_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + gemini_bs_map, + gemini_bs_unmap, + gemini_bs_subregion, + + /* allocation/deallocation */ + gemini_bs_alloc, /* not implemented */ + gemini_bs_free, /* not implemented */ + + /* get kernel virtual address */ + gemini_bs_vaddr, + + /* mmap */ + bs_notimpl_bs_mmap, + + /* barrier */ + gemini_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 */ + generic_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 */ + generic_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 */ + generic_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, +}; + +int +gemini_bs_map(void *t, bus_addr_t bpa, bus_size_t size, + int flag, bus_space_handle_t *bshp) +{ + u_long startpa, endpa, pa; + vaddr_t va; + pt_entry_t *pte; + const struct pmap_devmap *pd; + + if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) { + /* Device was statically mapped. */ + *bshp = pd->pd_va + (bpa - pd->pd_pa); + return 0; + } + + startpa = trunc_page(bpa); + endpa = round_page(bpa + size); + + /* XXX use extent manager to check duplicate mapping */ + + va = uvm_km_alloc(kernel_map, endpa - startpa, 0, + UVM_KMF_VAONLY | UVM_KMF_NOWAIT); + if (! va) + return(ENOMEM); + + *bshp = (bus_space_handle_t)(va + (bpa - startpa)); + + for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { + pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE); + if ((flag & BUS_SPACE_MAP_CACHEABLE) == 0) { + pte = vtopte(va); + *pte &= ~L2_S_CACHE_MASK; + PTE_SYNC(pte); + /* XXX: pmap_kenter_pa() also does PTE_SYNC(). a bit of + * waste. + */ + } + } + pmap_update(pmap_kernel()); + + return(0); +} + +void +gemini_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + vaddr_t va; + vsize_t sz; + + if (pmap_devmap_find_va(bsh, size) != NULL) { + /* Device was statically mapped; nothing to do. */ + return; + } + + va = trunc_page(bsh); + sz = round_page(bsh + size) - va; + + pmap_kremove(va, sz); + pmap_update(pmap_kernel()); + uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY); +} + + +int +gemini_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 +gemini_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t len, int flags) +{ + + /* Nothing to do. */ +} + +void * +gemini_bs_vaddr(void *t, bus_space_handle_t bsh) +{ + + return ((void *)bsh); +} + + +int +gemini_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("gemini_io_bs_alloc(): not implemented\n"); +} + +void +gemini_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("gemini_io_bs_free(): not implemented\n"); +} + diff --git a/sys/arch/arm/gemini/gemini_timer.c b/sys/arch/arm/gemini/gemini_timer.c new file mode 100644 index 00000000000..1d9572646b1 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_timer.c @@ -0,0 +1,413 @@ +/* $NetBSD: gemini_timer.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: omap2_geminitmr.c,v 1.1 2008/08/27 11:03:10 matt Exp + */ + +/* + * GEMINI Timers + */ + +/* + * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c + * + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro and Ichiro FUKUHARA. + * + * 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 by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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. + * + * 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_timer.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include "opt_gemini.h" +#include "opt_cpuoptions.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/time.h> +#include <sys/timetc.h> +#include <sys/device.h> + +#include <dev/clock_subr.h> + +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/cpufunc.h> +#include <arm/pic/picvar.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_timervar.h> +#include <arm/gemini/gemini_timervar.h> + + +static const uint32_t counts_per_usec = (GEMINI_TIMER_CLOCK_FREQ / 1000000); +static uint32_t counts_per_hz = ~0; + +struct geminitmr_softc *clock_sc; +struct geminitmr_softc *stat_sc; +struct geminitmr_softc *ref_sc; +static uint32_t gemini_get_timecount(struct timecounter *); +static void timer_init(geminitmr_softc_t *, int, boolean_t, boolean_t); +static void timer_factors(geminitmr_softc_t *, int, boolean_t); + +#ifdef GEMINI_TIMER_DEBUG +static void tfprint(uint, timer_factors_t *); +#endif + +static struct timecounter gemini_timecounter = { + .tc_get_timecount = gemini_get_timecount, + .tc_counter_mask = 0xffffffff, + .tc_frequency = GEMINI_TIMER_CLOCK_FREQ, + .tc_name = "gpt", + .tc_quality = 100, + .tc_priv = NULL +}; + +static inline void +_timer_intr_dis(struct geminitmr_softc *sc) +{ + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK); + r |= GEMINI_TIMERn_INTRMASK(sc->sc_timerno); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK, r); +} + +static inline void +_timer_intr_enb(struct geminitmr_softc *sc) +{ + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK); + r &= ~TIMER_INTRMASK_TMnMATCH1(sc->sc_timerno); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRMASK, r); +} + +static inline void +_timer_intr_clr(struct geminitmr_softc *sc) +{ + uint32_t r; + int psw; + + psw = disable_interrupts(I32_bit); + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRSTATE); + r &= ~GEMINI_TIMERn_INTRMASK(sc->sc_timerno); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_INTRSTATE, r); + restore_interrupts(psw); +} + +static inline uint32_t +_timer_read(struct geminitmr_softc *sc) +{ + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_COUNTER(sc->sc_timerno)); + + return r; +} + +static inline void +_timer_stop(struct geminitmr_softc *sc) +{ + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR); + r &= ~GEMINI_TIMER_TMnCR_MASK(sc->sc_timerno); +} + +/* + * note: + * This function assumes the timer is enabled. + * If the timer is disabled, GEMINI_TIMERn_COUNTER(n) will hold the value. + */ +static inline void +_timer_reload(struct geminitmr_softc *sc, uint32_t val) +{ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_COUNTER(sc->sc_timerno), val); +} + +static inline void +_timer_start(struct geminitmr_softc *sc) +{ + uint32_t r; + uint n = sc->sc_timerno; + timer_factors_t *tfp = &sc->sc_tf; + + /* set Counter, TmLoad, Match1, Match2 */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_COUNTER(n), tfp->tf_counter); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_LOAD(n), tfp->tf_reload); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_MATCH1(n), tfp->tf_match1); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMERn_MATCH2(n), tfp->tf_match2); + + /* set TmCR */ + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR); + r &= ~GEMINI_TIMER_TMnCR_MASK(n); + r |= tfp->tf_tmcr & GEMINI_TIMER_TMnCR_MASK(n); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_TIMER_TMCR, r); + +} + +static uint32_t +gemini_get_timecount(struct timecounter *tc) +{ + uint32_t r; + + r = _timer_read(ref_sc); + + return -r; +} + +int +clockintr(void *frame) +{ + struct geminitmr_softc *sc = clock_sc;; + + _timer_intr_clr(sc); + _timer_reload(sc, sc->sc_tf.tf_counter); + hardclock(frame); + return 1; +} + +int +statintr(void *frame) +{ + struct geminitmr_softc *sc = stat_sc;; + + _timer_intr_clr(sc); + _timer_reload(sc, sc->sc_tf.tf_counter); + statclock(frame); + return 1; +} + +static void +timer_init(geminitmr_softc_t *sc, int schz, boolean_t autoload, boolean_t intr) +{ + int psw; + + psw = disable_interrupts(I32_bit); + timer_factors(sc, schz, autoload); + _timer_stop(sc); + _timer_intr_dis(sc); + _timer_intr_clr(sc); + if (intr) + _timer_intr_enb(sc); + _timer_start(sc); + psw = disable_interrupts(I32_bit); +} + +void +gemini_microtime_init() +{ + if (ref_sc == NULL) + panic("microtime reference timer was not configured."); + timer_init(ref_sc, 0, TRUE, FALSE); +} + +void +setstatclockrate(int schz) +{ + if (stat_sc == NULL) + panic("Statistics timer was not configured."); + timer_init(stat_sc, schz, FALSE, TRUE); +} + +/* + * clock_sc and stat_sc starts here + * ref_sc is initialized already by obiotimer_attach + */ +void +cpu_initclocks(void) +{ + if (clock_sc == NULL) + panic("Clock timer was not configured."); + if (stat_sc == NULL) + panic("Statistics timer was not configured."); + if (ref_sc == NULL) + panic("Microtime reference timer was not configured."); + + /* + * We already have the timers running, but not generating interrupts. + * In addition, we've set stathz and profhz. + */ + printf("clock: hz=%d stathz=%d\n", hz, stathz); + + /* + * The "cookie" parameter must be zero to pass the interrupt frame + * through to hardclock() and statclock(). + */ + intr_establish(clock_sc->sc_intr, IPL_CLOCK, IST_LEVEL_HIGH, + clockintr, 0); + + intr_establish(stat_sc->sc_intr, IPL_HIGH, IST_LEVEL_HIGH, + statintr, 0); + + timer_init(clock_sc, hz, FALSE, TRUE); + timer_init(stat_sc, stathz, FALSE, TRUE); + + tc_init(&gemini_timecounter); +} + +void +delay(u_int n) +{ + struct geminitmr_softc *sc = ref_sc; + uint32_t cur, last, delta, usecs; + + if (sc == NULL) + panic("The timer must be initialized sooner."); + + /* + * This works by polling the timer and counting the + * number of microseconds that go by. + */ + last = _timer_read(sc); + + delta = usecs = 0; + + while (n > usecs) { + cur = _timer_read(sc); + + /* 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; + } + } +} + +static void +timer_factors( + geminitmr_softc_t *sc, + int ints_per_sec, + boolean_t autoload) +{ + timer_factors_t *tfp = &sc->sc_tf; + uint n = sc->sc_timerno; + const uint32_t us_per_sec = 1000000; + + /* + * UPDOWN=0 (Down) + * OFENABLE=0 (no Irpt on overflow) + * CLOCK=0 (PCLK) + * ENABLE=1 + */ + tfp->tf_tmcr = TIMER_TMCR_TMnENABLE(n); + + if (ints_per_sec == 0) { + tfp->tf_counter = ~0U; + } else { + uint32_t count_freq; + + count_freq = GEMINI_TIMER_CLOCK_FREQ; + count_freq /= ints_per_sec; + tfp->tf_counter = count_freq; + } + tfp->tf_counts_per_usec = GEMINI_TIMER_CLOCK_FREQ / us_per_sec; + + if (autoload) + tfp->tf_reload = tfp->tf_counter; /* auto-reload */ + else + tfp->tf_reload = 0; /* no-auto_reload */ + + tfp->tf_match1 = 0; + tfp->tf_match2 = 0; + +#ifdef GEMINI_TIMER_DEBUG + tfprint(sc->sc_timerno, tfp); + Debugger(); +#endif +} + +#ifdef GEMINI_TIMER_DEBUG +void +tfprint(uint n, timer_factors_t *tfp) +{ + printf("%s: timer# %d\n", __FUNCTION__, n); + printf("\ttf_counts_per_usec: %#x\n", tfp->tf_counts_per_usec); + printf("\ttf_tmcr: %#x\n", tfp->tf_tmcr); + printf("\ttf_counter: %#x\n", tfp->tf_counter); + printf("\ttf_reload: %#x\n", tfp->tf_reload); + printf("\ttf_match1: %#x\n", tfp->tf_match1); + printf("\ttf_match2: %#x\n", tfp->tf_match2); +} +#endif diff --git a/sys/arch/arm/gemini/gemini_timervar.h b/sys/arch/arm/gemini/gemini_timervar.h new file mode 100644 index 00000000000..a5ca23559a9 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_timervar.h @@ -0,0 +1,78 @@ +/* $NetBSD: gemini_timervar.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + + +/* + * adapted from: + * NetBSD: omap2_mputmrvar.h,v 1.2 2008/04/27 18:58:45 matt Exp + */ + +/* + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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 _GEMINI_TIMER_H +#define _GEMINI_TIMER_H + +#ifndef STATHZ +# define STATHZ 64 +#endif + +typedef struct timer_factors { + uint32_t tf_counts_per_usec; + uint32_t tf_tmcr; + uint32_t tf_counter; + uint32_t tf_reload; + uint32_t tf_match1; + uint32_t tf_match2; +} timer_factors_t; + +typedef struct geminitmr_softc { + struct device sc_dev; + uint sc_timerno; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_addr_t sc_addr; + size_t sc_size; + int sc_intr; + timer_factors_t sc_tf; +} geminitmr_softc_t; + + + +extern uint32_t hardref; +extern struct timeval hardtime; +extern struct geminitmr_softc *clock_sc; +extern struct geminitmr_softc *stat_sc; +extern struct geminitmr_softc *ref_sc; + +extern void gemini_microtime_init(void); + +extern int clockintr(void *); +extern int statintr(void *); +extern void rtcinit(void); + +#endif /* _GEMINI_TIMER_H */ diff --git a/sys/arch/arm/gemini/gemini_var.h b/sys/arch/arm/gemini/gemini_var.h new file mode 100644 index 00000000000..7282e156ded --- /dev/null +++ b/sys/arch/arm/gemini/gemini_var.h @@ -0,0 +1,20 @@ +#ifndef _ARM_GEMINI_VAR_H_ +#define _ARM_GEMINI_VAR_H_ + +#include <sys/types.h> +#include <machine/bus.h> + +/* GEMINI generic */ + + +extern struct bus_space gemini_bs_tag; +extern struct arm32_bus_dma_tag gemini_bus_dma_tag; +extern struct bus_space gemini_a4x_bs_tag; +extern struct bus_space gemini_a2x_bs_tag; +extern struct bus_space nobyteacc_bs_tag; + + +/* platform needs to provide this */ +extern bus_dma_tag_t gemini_bus_dma_init(struct arm32_bus_dma_tag *); + +#endif /* _ARM_GEMINI_VAR_H_ */ diff --git a/sys/arch/arm/gemini/gemini_wdt.c b/sys/arch/arm/gemini/gemini_wdt.c new file mode 100644 index 00000000000..4d6e12d495d --- /dev/null +++ b/sys/arch/arm/gemini/gemini_wdt.c @@ -0,0 +1,211 @@ +/* $NetBSD: gemini_wdt.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* + * OMAP watchdog timers, common code + * + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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. + */ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/callout.h> +#include <sys/cdefs.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/wdog.h> + +#include <machine/param.h> +#include <machine/bus.h> +#include <dev/sysmon/sysmonvar.h> + +#include <arm/gemini/gemini_wdtvar.h> +#include <arm/gemini/gemini_reg.h> + +geminiwdt_softc_t *geminiwdt_sc; + +#define WATCHDOG_COUNT(nsec) \ + (GEMINI_WDT_CLOCK_FREQ * (nsec)) + + +static void +geminiwdt_start(void) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR); + r |= (WDT_WDCR_RESET_ENB + |WDT_WDCR_ENB); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR, r); +} + +static void +geminiwdt_stop(void) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + uint32_t r; + + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR); + r &= ~(WDT_WDCR_EXTSIG_ENB + |WDT_WDCR_RESET_ENB + |WDT_WDCR_INTR_ENB + |WDT_WDCR_ENB); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR, r); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_WDT_WDCLEAR, WDT_WDCLEAR_CLEAR); +} + +static void +geminiwdt_do_set_timeout(void) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + uint32_t r; + + /* + * Disable the watchdog timer + */ + if (sc->sc_armed) + geminiwdt_stop(); + + /* + * Set WdLoad register + */ + r = (sc->sc_smw.smw_period != 0) ? + WATCHDOG_COUNT(sc->sc_smw.smw_period) : WDT_WDLOAD_DFLT; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDLOAD, r); + + /* + * feed MAGIC treat to dog + */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_WDT_WDRESTART, WDT_WDRESTART_MAGIC); + + /* + * Select PCLK clock source + */ + r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR); + r &= ~WDCR_CLKSRC_5MHZ; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GEMINI_WDT_WDCR, r); + + /* + * Enable the timer + */ + if (sc->sc_armed) + geminiwdt_start(); +} + +void +geminiwdt_set_timeout(unsigned int period) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + int s = splhigh(); + + if (period != sc->sc_smw.smw_period) { + sc->sc_smw.smw_period = period; + geminiwdt_do_set_timeout(); + } + + splx(s); +} + +int +geminiwdt_enable(int enable) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + int s; + int prev_state = geminiwdt_sc->sc_armed; + + /* Normalize the int to a boolean so we can compare values directly. + */ + enable = !!enable; + + s = splhigh(); + + if (enable != sc->sc_armed) { + if (enable) { + /* Make sure that the watchdog timeout is up to date. + */ + geminiwdt_do_set_timeout(); + geminiwdt_start(); + } else { + geminiwdt_stop(); + } + sc->sc_armed = enable; + } + + splx(s); + return prev_state; +} + +int +geminiwdt_setmode(struct sysmon_wdog *smw) +{ + geminiwdt_softc_t *sc = smw->smw_cookie; + int error = 0; + + if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { + geminiwdt_enable(0); + } else { + if (smw->smw_period == WDOG_PERIOD_DEFAULT) + sc->sc_smw.smw_period = WDT_WDLOAD_DFLT; + else + sc->sc_smw.smw_period = smw->smw_period; + geminiwdt_set_timeout(sc->sc_smw.smw_period); + geminiwdt_enable(1); + } + return error; +} + +int +geminiwdt_tickle(struct sysmon_wdog *smw) +{ + geminiwdt_softc_t *sc = geminiwdt_sc; + int s = splhigh(); + + /* + * feed the dog a MAGIC treat + */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_WDT_WDRESTART, WDT_WDRESTART_MAGIC); + + splx(s); + return 0; +} + +void +geminiwdt_reboot(void) +{ + int s = splhigh(); + + geminiwdt_set_timeout(30); + geminiwdt_start(); + delay(100); + splx(s); +} diff --git a/sys/arch/arm/gemini/gemini_wdtvar.h b/sys/arch/arm/gemini/gemini_wdtvar.h new file mode 100644 index 00000000000..5585c685456 --- /dev/null +++ b/sys/arch/arm/gemini/gemini_wdtvar.h @@ -0,0 +1,60 @@ +/* $NetBSD: gemini_wdtvar.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* + * adapted/extracted from omap_wdt.c + * + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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 _ARM_GEMINI_WDTVAR_H +#define _ARM_GEMINI_WDTVAR_H + +#include <sys/device.h> +#include <machine/bus.h> +#include <dev/sysmon/sysmonvar.h> + +typedef struct geminiwdt_softc { + struct device sc_dev; + bus_addr_t sc_addr; + bus_size_t sc_size; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + struct sysmon_wdog sc_smw; + int sc_armed; +} geminiwdt_softc_t; + +extern struct geminiwdt_softc *geminiwdt_sc; +extern int omapwdt_sysconfig; + +int geminiwdt_setmode(struct sysmon_wdog *); +int geminiwdt_tickle(struct sysmon_wdog *); + +void geminiwdt_set_timeout(unsigned int period); +int geminiwdt_enable(int enable); +void geminiwdt_reboot(void); + +#endif /* _ARM_GEMINI_WDTVAR_H */ diff --git a/sys/arch/arm/gemini/obio_timer.c b/sys/arch/arm/gemini/obio_timer.c new file mode 100644 index 00000000000..7b29844d982 --- /dev/null +++ b/sys/arch/arm/gemini/obio_timer.c @@ -0,0 +1,286 @@ +/* $NetBSD: obio_timer.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: obio_mputmr.c,v 1.3 2008/08/27 11:03:10 matt Exp + */ + +/* + * Based on omap_mputmr.c + * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c + * + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro and Ichiro FUKUHARA. + * + * 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 by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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. + * + * 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. + * + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: obio_timer.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include "opt_cpuoptions.h" +#include "opt_gemini.h" +#include "locators.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/time.h> +#include <sys/device.h> + +#include <dev/clock_subr.h> + +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_obiovar.h> +#include <arm/gemini/gemini_timervar.h> + + +#ifndef GEMINI_TIMER_CLOCK_FREQ +# error Specify the timer frequency in Hz with the GEMINI_TIMER_CLOCK_FREQ option. +#endif + +static int obiotimer_match(device_t, struct cfdata *, void *); +static void obiotimer_attach(device_t, device_t, void *); + +struct geminitmr_softc xsc; + + + +typedef struct { + uint timerno; + bus_addr_t addr; + uint intr; +} obiotimer_instance_t; + +/* XXX + * this table can be used to match the GP Timers + * until we use config(8) locators to distinguish between + * gemini "sub-timers". + */ +#define GPT_ENTRY(n, i) { \ + .timerno = (n), \ + .addr = GEMINI_TIMER_BASE, \ + .intr = i, \ + } +static const obiotimer_instance_t obiotimer_instance_tab[] = { + GPT_ENTRY(1, 14), + GPT_ENTRY(2, 15), + GPT_ENTRY(3, 16), +}; +#undef GPT_ENTRY +#define GPTIMER_INSTANCE_CNT __arraycount(obiotimer_instance_tab) + +static const obiotimer_instance_t * + obiotimer_lookup(struct obio_attach_args *); +static void obiotimer_enable(struct geminitmr_softc *, + struct obio_attach_args *, + const obiotimer_instance_t *); + +static int obiotimer_match(device_t, struct cfdata *, void *); +static void obiotimer_attach(device_t, device_t, void *); + + +CFATTACH_DECL_NEW(obiotimer, sizeof(struct geminitmr_softc), + obiotimer_match, obiotimer_attach, NULL, NULL); + + +static int +obiotimer_match(device_t parent, struct cfdata *match, void *aux) +{ + struct obio_attach_args *obio = aux; + + if ((obio->obio_addr == IICCF_ADDR_DEFAULT) + || (obio->obio_intr == OBIOCF_INTR_DEFAULT)) + panic("geminitmr must have addr and intr specified in config."); + + if (obiotimer_lookup(obio) == NULL) + return 0; + + return 1; +} + +void +obiotimer_attach(device_t parent, device_t self, void *aux) +{ + struct geminitmr_softc *sc = device_private(self); + struct obio_attach_args *obio = aux; + const obiotimer_instance_t *ip; + static int once=1; + + ip = obiotimer_lookup(obio); + if (ip == NULL) + panic("%s: bad lookup", device_xname(self)); + /* should not fail since we already matched */ + + sc->sc_timerno = ip->timerno; + sc->sc_iot = obio->obio_iot; + sc->sc_intr = obio->obio_intr; + sc->sc_addr = obio->obio_addr; + sc->sc_size = (obio->obio_size == IICCF_SIZE_DEFAULT) + ? (GEMINI_TIMER_INTRMASK + 4) + : obio->obio_size; + + if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh)) + panic("%s: Cannot map registers", device_xname(self)); + + obiotimer_enable(sc, obio, obiotimer_lookup(obio)); + aprint_normal("\n"); + aprint_naive("\n"); + + if (once) { + once = 0; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMER_TMCR, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMER_INTRMASK, (uint32_t)~TIMER_INTRMASK_Resv); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + GEMINI_TIMER_INTRSTATE, 0); + } + + switch (sc->sc_timerno) { + case 1: + /* + * timer #1 is the system clock + * it gets started later + */ + clock_sc = sc; + break; + case 2: + /* + * timer #2 is the stat clock + * it gets started later + */ + profhz = stathz = STATHZ; + stat_sc = sc; + break; + case 3: + /* + * Timer #3 is used for microtime reference clock and for delay() + * autoloading, non-interrupting, just wraps around as an unsigned int. + * we start it now to make delay() available + */ + ref_sc = sc; + gemini_microtime_init(); + break; + default: + panic("bad gemini timer number %d\n", sc->sc_timerno); + break; + } +} + +static const obiotimer_instance_t * +obiotimer_lookup(struct obio_attach_args *obio) +{ + const obiotimer_instance_t *ip; + uint i; + + for (i = 0, ip = obiotimer_instance_tab; + i < GPTIMER_INSTANCE_CNT; i++, ip++) { + if (ip->addr == obio->obio_addr && ip->intr == obio->obio_intr) + return ip; + } + + return NULL; +} + +void +obiotimer_enable( + struct geminitmr_softc *sc, + struct obio_attach_args *obio, + const obiotimer_instance_t *ip) +{ + /* nothing to do */ +} diff --git a/sys/arch/arm/gemini/obio_wdt.c b/sys/arch/arm/gemini/obio_wdt.c new file mode 100644 index 00000000000..89ac2290f6e --- /dev/null +++ b/sys/arch/arm/gemini/obio_wdt.c @@ -0,0 +1,111 @@ +/* $NetBSD: obio_wdt.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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. + */ + +/* + * obio attachment for GEMINI watchdog timers + */ +#include "opt_gemini.h" +#include "locators.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: obio_wdt.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include <sys/param.h> +#include <sys/callout.h> +#include <sys/cdefs.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/wdog.h> + +#include <machine/param.h> +#include <machine/bus.h> +#include <dev/sysmon/sysmonvar.h> + +#include <arm/gemini/gemini_obiovar.h> +#include <arm/gemini/gemini_wdtvar.h> +#include <arm/gemini/gemini_reg.h> + +static int geminiwdt_match(struct device *, struct cfdata *, void *); +static void geminiwdt_attach(struct device *, struct device *, void *); + +CFATTACH_DECL(obiowdt, sizeof(struct geminiwdt_softc), + geminiwdt_match, geminiwdt_attach, NULL, NULL); + +static int +geminiwdt_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct obio_attach_args *obio = aux; + + if (obio->obio_addr == IICCF_ADDR_DEFAULT) + panic("geminiwdt must have addr specified in config."); + + if (obio->obio_addr == GEMINI_WATCHDOG_BASE) + return 1; + + return 0; +} + +static void +geminiwdt_attach(struct device *parent, struct device *self, void *aux) +{ + geminiwdt_softc_t *sc = (geminiwdt_softc_t *)self; + struct obio_attach_args *obio = aux; + + sc->sc_addr = obio->obio_addr; + sc->sc_size = (obio->obio_size == IICCF_SIZE_DEFAULT) + ? GEMINI_WDT_WDINTERLEN + 4 + : obio->obio_size; + + sc->sc_smw.smw_name = device_xname(&sc->sc_dev); + sc->sc_smw.smw_cookie = sc; + sc->sc_smw.smw_setmode = geminiwdt_setmode; + sc->sc_smw.smw_tickle = geminiwdt_tickle; + sc->sc_smw.smw_period = 0; + sc->sc_iot = obio->obio_iot; + + if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh)) + panic("%s: Cannot map registers", device_xname(self)); + + geminiwdt_sc = sc; + + aprint_normal("\n"); + aprint_naive("\n"); + +#if 0 + Debugger(); /* can try reboot function here to test wdt */ +#endif +#if 0 + geminiwdt_set_timeout(30); /* test 30 sec reset */ + geminiwdt_enable(1); +#endif + +} diff --git a/sys/arch/evbarm/conf/GEMINI b/sys/arch/evbarm/conf/GEMINI new file mode 100644 index 00000000000..f895561970b --- /dev/null +++ b/sys/arch/evbarm/conf/GEMINI @@ -0,0 +1,228 @@ +# +# GEMINI -- +# + +include "arch/evbarm/conf/std.gemini" + +# estimated number of users + +maxusers 32 + +# Standard system options + +options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT +#options NTP # NTP phase/frequency locked loop + +# CPU options + +options CPU_FA526 +options SL3516 + +# Architecture options + +# File systems + +file-system FFS # UFS +#file-system LFS # log-structured file system +file-system MFS # memory file system +file-system NFS # Network file system +#file-system ADOSFS # AmigaDOS-compatible file system +#file-system EXT2FS # second extended file system (linux) +#file-system CD9660 # ISO 9660 + Rock Ridge file system +file-system MSDOSFS # MS-DOS file system +#file-system FDESC # /dev/fd +#file-system KERNFS # /kern +#file-system NULLFS # loopback file system +#file-system PORTAL # portal filesystem (still experimental) +#file-system PROCFS # /proc +#file-system UMAPFS # NULLFS + uid and gid remapping +#file-system UNION # union file system +file-system PTYFS # /dev/pts/N support + +# File system options +#options QUOTA # UFS quotas +#options FFS_EI # FFS Endian Independant support +#options NFSSERVER +#options SOFTDEP +#options WAPBL # File system journaling support - Experimental +#options FFS_NO_SNAPSHOT # No FFS snapshot support + +# Networking options + +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +options INET6 # IPV6 +#options IPSEC # IP security +#options IPSEC_ESP # IP security (encryption part; define w/ IPSEC) +#options IPSEC_NAT_T # IPsec NAT traversal (NAT-T) +#options IPSEC_DEBUG # debug for IP security +#options MROUTING # IP multicast routing +#options PIM # Protocol Independent Multicast +#options NS # XNS +#options NSIP # XNS tunneling over IP +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 +#options NETATALK # AppleTalk networking +#options PFIL_HOOKS # pfil(9) packet filter hooks +#options PPP_BSDCOMP # BSD-Compress compression support for PPP +#options PPP_DEFLATE # Deflate compression support for PPP +#options PPP_FILTER # Active filter support for PPP (requires bpf) +#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG + +options NFS_BOOT_BOOTP +options NFS_BOOT_DHCP +options NFS_BOOT_RWSIZE=1024 + +# Compatibility options + +#options COMPAT_43 # 4.3BSD compatibility. +#options COMPAT_40 # NetBSD 4.0 compatibility. +#options COMPAT_30 # NetBSD 3.0 compatibility. +#options COMPAT_20 # NetBSD 2.0 compatibility. +#options COMPAT_16 # NetBSD 1.6 compatibility. +#options COMPAT_15 # NetBSD 1.5 compatibility. +#options COMPAT_14 # NetBSD 1.4 compatibility. +#options COMPAT_13 # NetBSD 1.3 compatibility. +#options COMPAT_12 # NetBSD 1.2 compatibility. +#options COMPAT_11 # NetBSD 1.1 compatibility. +#options COMPAT_10 # NetBSD 1.0 compatibility. +#options COMPAT_09 # NetBSD 0.9 compatibility. +#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended. +#options COMPAT_BSDPTY # /dev/[pt]ty?? ptys. + +# Shared memory options + +options SYSVMSG # System V-like message queues +options SYSVSEM # System V-like semaphores +#options SEMMNI=10 # number of semaphore identifiers +#options SEMMNS=60 # number of semaphores in system +#options SEMUME=10 # max number of undo entries per process +#options SEMMNU=30 # number of undo structures in system +options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +#options MEMORY_DISK_HOOKS # boottime setup of ramdisk +#options MEMORY_DISK_ROOT_SIZE=8192 # Size in blocks +#options MEMORY_DISK_DYNAMIC +#options MINIROOTSIZE=1000 # Size in blocks +#options MEMORY_DISK_IS_ROOT # use memory disk as root + +# Miscellaneous kernel options +options KTRACE # system call tracing, a la ktrace(1) +#options LKM # loadable kernel modules +#options KMEMSTATS # kernel memory statistics +#options SCSIVERBOSE # Verbose SCSI errors +#options MIIVERBOSE # Verbose MII autoconfuration messages +#options DDB_KEYCODE=0x40 +#options USERCONF # userconf(4) support +#options PIPE_SOCKETPAIR # smaller, but slower pipe(2) + +# Development and Debugging options + +#options PERFCTRS # performance counters +options DIAGNOSTIC # internally consistency checks +#options DEBUG +#options PMAP_DEBUG # Enable pmap_debug_level code +options VERBOSE_INIT_ARM # verbose bootstraping messages +options DDB # in-kernel debugger +options DDB_ONPANIC=1 +options DDB_HISTORY_SIZE=100 # Enable history editing in DDB +#options KGDB +#makeoptions DEBUG="-g" # compile full symbol table +##options SYMTAB_SPACE=280000 + +# Valid options for BOOT_ARGS: +# single Boot to single user only +# kdb Give control to kernel debugger +# ask Ask for file name to reboot from +# pmapdebug=<n> If PMAP_DEBUG, set pmap_debug_level to <n> +# memorydisk=<n> Set memorydisk size to <n> KB +# quiet Show aprint_naive output +# verbose Show aprint_normal and aprint_verbose output +options BOOT_ARGS="\"\"" + +config netbsd root on ? type ? +##config netbsd-sm0 root on sm0 type nfs + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# Specify the memory size in megabytes. +options MEMSIZE=128 + +# On-board IO +obio0 at mainbus? + +# On-board 16550 UART(s) +com0 at obio? addr 0x42000000 intr 18 mult 4 +options CONSADDR=0x42000000, CONSPEED=19200 + +# Interrupt controller +geminiicu0 at obio0 addr 0x48000000 intrbase 0 +##geminiicu1 at obio0 addr 0x49000000 intrbase 0 + +# Watchdog timer +geminiwdt0 at obio0 addr 0x41000000 size 0x1c +# Internal PCLK is AHB bus freq, +# which is 1/6 of APB bus freq, +# which is 150MHz` +options GEMINI_WDT_CLOCK_FREQ=25000000 # 25 MHz + +# Operating System Timer +geminitmr0 at obio? addr 0x43000000 size 0x3c intr 14 +# Statistics Timer +geminitmr1 at obio? addr 0x43000000 size 0x3c intr 15 +# Microtime Reference Timer +geminitmr2 at obio? addr 0x43000000 size 0x3c intr 16 +# +# Internal PCLK is AHB bus freq, +# which is 1/6 of APB bus freq, +# which is 150MHz` +options GEMINI_TIMER_CLOCK_FREQ=25000000 # 25 MHz + + +# On-board GPIO controllers + + +# Real Time Clock + + +# PCI +pci0 at obio? bus ? +options PCI_NETBSD_CONFIGURE # set up the PCI bus +options PCIVERBOSE +options PCI_CONFIG_DUMP + +# PCI Ethernet +ex* at pci? dev ? function ? # 3Com 90x[BC] + +# MII/PHY support +exphy* at mii? phy ? # 3Com internal PHYs +ukphy* at mii? phy ? # generic unknown PHYs + + +# Pseudo-Devices + +# disk/mass storage pseudo-devices +pseudo-device md 1 # memory disk device (ramdisk) +#pseudo-device vnd # disk-like interface to files +#pseudo-device fss 4 # file system snapshot device + +# network pseudo-devices +pseudo-device bpfilter # Berkeley packet filter +pseudo-device loop # network loopback +#pseudo-device kttcp # network loopback + +# miscellaneous pseudo-devices +pseudo-device pty # pseudo-terminals +pseudo-device rnd # /dev/random and in-kernel generator +#options RND_COM +#pseudo-device clockctl # user control of clock subsystem +pseudo-device ksyms # /dev/ksyms + diff --git a/sys/arch/evbarm/conf/files.gemini b/sys/arch/evbarm/conf/files.gemini new file mode 100644 index 00000000000..3a504b92719 --- /dev/null +++ b/sys/arch/evbarm/conf/files.gemini @@ -0,0 +1,12 @@ +# $NetBSD: files.gemini,v 1.1 2008/10/24 04:23:18 matt Exp $ +# +# GEMINI evaluation board configuration info +# + +file arch/evbarm/gemini/gemini_machdep.c + +# Kernel boot arguments +defparam opt_machdep.h BOOT_ARGS + +# CPU support and integrated peripherals +include "arch/arm/gemini/files.gemini" diff --git a/sys/arch/evbarm/conf/mk.gemini b/sys/arch/evbarm/conf/mk.gemini new file mode 100644 index 00000000000..bb51d4df627 --- /dev/null +++ b/sys/arch/evbarm/conf/mk.gemini @@ -0,0 +1,17 @@ +# $NetBSD: mk.gemini,v 1.1 2008/10/24 04:23:18 matt Exp $ + + +CPUFLAGS+=-march=armv4 +CPUFLAGS+=-mlittle-endian + +SYSTEM_FIRST_OBJ= gemini_start.o +SYSTEM_FIRST_SFILE= ${THISARM}/gemini/gemini_start.S + +KERNEL_BASE_PHYS=0x10200000 +KERNEL_BASE_VIRT=0x80200000 + +SYSTEM_LD_TAIL_EXTRA+=; \ + echo ${OBJCOPY} -S -O binary $@ $@.bin; \ + ${OBJCOPY} -S -O binary $@ $@.bin; \ + +EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@} diff --git a/sys/arch/evbarm/conf/std.gemini b/sys/arch/evbarm/conf/std.gemini new file mode 100644 index 00000000000..1d19edc744c --- /dev/null +++ b/sys/arch/evbarm/conf/std.gemini @@ -0,0 +1,29 @@ +# $NetBSD: std.gemini,v 1.1 2008/10/24 04:23:18 matt Exp $ +# +# standard NetBSD/evbarm for GEMINI options + +machine evbarm arm +include "conf/std" # MI standard options + +# Pull in GEMINI config definitions. +include "arch/evbarm/conf/files.gemini" + +options EXEC_ELF32 +options EXEC_SCRIPT + +# To support easy transit to ../arch/arm/arm32 +options ARM32 +options ARM9 +#options __HAVE_FAST_SOFTINTS # should be in types.h +options __HAVE_PCI_CONF_HOOK # should be in types.h +#options KERNEL_BASE_EXT=0x80000000 + +makeoptions LOADADDRESS="0x10200000" +makeoptions BOARDTYPE="gemini" +makeoptions BOARDMKFRAG="${THISARM}/conf/mk.gemini" +makeoptions CPPFLAGS+="-I$S/../../../include" + +options EVBARM_BOARDTYPE=gemini +options ARM_INTR_IMPL="<arch/arm/gemini/gemini_intr.h>" +#options ARM_GENERIC_TODR + diff --git a/sys/arch/evbarm/gemini/gemini.h b/sys/arch/evbarm/gemini/gemini.h new file mode 100644 index 00000000000..96230c14d4a --- /dev/null +++ b/sys/arch/evbarm/gemini/gemini.h @@ -0,0 +1,56 @@ +/* $NetBSD: gemini.h,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: sdp24xx.h,v 1.3 2008/08/27 11:03:10 matt Exp + */ + +/* + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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 _EVBARM_GEMINI_GEMINI_H +#define _EVBARM_GEMINI_GEMINI_H + +#include <arm/gemini/gemini_reg.h> + +/* + * Kernel VM space: 192MB at KERNEL_VM_BASE + */ +#define KERNEL_VM_BASE ((KERNEL_BASE + 0x01000000) & ~(0x400000-1)) +#define KERNEL_VM_SIZE 0x0C000000 + +/* + * We devmap IO starting at KERNEL_VM_BASE + KERNEL_VM_SIZE + */ +#define GEMINI_KERNEL_IO_VBASE (KERNEL_VM_BASE + KERNEL_VM_SIZE) +#define GEMINI_WATCHDOG_VBASE GEMINI_KERNEL_IO_VBASE +#define GEMINI_CONSOLE_VBASE (GEMINI_WATCHDOG_VBASE + L1_S_SIZE) +#define GEMINI_TIMER_VBASE (GEMINI_CONSOLE_VBASE + L1_S_SIZE) + + +#endif /* _EVBARM_GEMINI_GEMINI_H */ diff --git a/sys/arch/evbarm/gemini/gemini_machdep.c b/sys/arch/evbarm/gemini/gemini_machdep.c new file mode 100644 index 00000000000..a2746b1aba9 --- /dev/null +++ b/sys/arch/evbarm/gemini/gemini_machdep.c @@ -0,0 +1,1002 @@ +/* $NetBSD: gemini_machdep.c,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* adapted from: + * NetBSD: sdp24xx_machdep.c,v 1.4 2008/08/27 11:03:10 matt Exp + */ + +/* + * Machine dependent functions for kernel setup for TI OSK5912 board. + * Based on lubbock_machdep.c which in turn was based on iq80310_machhdep.c + * + * Copyright (c) 2002, 2003, 2005 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * 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. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + * + * Copyright (c) 2001 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. + * + * Copyright (c) 1997,1998 Mark Brinicombe. + * Copyright (c) 1997,1998 Causality Limited. + * All rights reserved. + * + * 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 by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTORS 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. + * + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gemini_machdep.c,v 1.1 2008/10/24 04:23:18 matt Exp $"); + +#include "opt_machdep.h" +#include "opt_ddb.h" +#include "opt_kgdb.h" +#include "opt_ipkdb.h" +#include "opt_md.h" +#include "opt_com.h" +#include "opt_gemini.h" +#include "geminiwdt.h" +#include "md.h" + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/exec.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> +#include <sys/reboot.h> +#include <sys/termios.h> +#include <sys/ksyms.h> + +#include <uvm/uvm_extern.h> + +#include <sys/conf.h> +#include <dev/cons.h> +#include <dev/md.h> + +#include <machine/db_machdep.h> +#include <ddb/db_sym.h> +#include <ddb/db_extern.h> +#ifdef KGDB +#include <sys/kgdb.h> +#endif + +#include <machine/bootconfig.h> +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <arm/armreg.h> +#include <arm/undefined.h> + +#include <arm/arm32/machdep.h> + +#include <arm/gemini/gemini_reg.h> +#include <arm/gemini/gemini_var.h> +#include <arm/gemini/gemini_wdtvar.h> +#include <arm/gemini/gemini_com.h> + +#include <evbarm/gemini/gemini.h> + +/* + * Address to call from cpu_reset() to reset the machine. + * This is machine architecture dependant as it varies depending + * on where the ROM appears when you turn the MMU off. + */ + +u_int cpu_reset_address = 0; + +/* Define various stack sizes in pages */ +#define IRQ_STACK_SIZE 1 +#define FIQ_STACK_SIZE 1 +#define ABT_STACK_SIZE 1 +#ifdef IPKDB +#define UND_STACK_SIZE 2 +#else +#define UND_STACK_SIZE 1 +#endif + +BootConfig bootconfig; /* Boot config storage */ +char *boot_args = NULL; +char *boot_file = NULL; + +/* Physical address of the beginning of SDRAM. */ +paddr_t physical_start; +/* Physical address of the first byte after the end of SDRAM. */ +paddr_t physical_end; +/* Number of pages of memory. */ +int physmem = 0; + +/* Same things, but for the free (unused by the kernel) memory. */ +static paddr_t physical_freestart, physical_freeend; +static u_int free_pages; + +/* Physical and virtual addresses for some global pages */ +pv_addr_t fiqstack; +pv_addr_t irqstack; +pv_addr_t undstack; +pv_addr_t abtstack; +pv_addr_t kernelstack; /* stack for SVC mode */ + +/* Physical address of the message buffer. */ +paddr_t msgbufphys; + +extern u_int data_abort_handler_address; +extern u_int prefetch_abort_handler_address; +extern u_int undefined_handler_address; +extern char KERNEL_BASE_phys[]; +extern char KERNEL_BASE_virt[]; +extern char etext[], __data_start[], _edata[], __bss_start[], __bss_end__[]; +extern char _end[]; + +#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ +#define KERNEL_PT_KERNEL 1 /* Page table for mapping kernel */ +#define KERNEL_PT_KERNEL_NUM 4 +#define KERNEL_PT_VMDATA (KERNEL_PT_KERNEL+KERNEL_PT_KERNEL_NUM) + /* Page tables for mapping kernel VM */ +#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ +#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) + +pv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; + +extern struct user *proc0paddr; + +/* + * Macros to translate between physical and virtual for a subset of the + * kernel address space. *Not* for general use. + */ +#define KERNEL_BASE_PHYS ((paddr_t)&KERNEL_BASE_phys) + +#define KERN_VTOPHYS(va) \ + ((paddr_t)((vaddr_t)va - KERNEL_BASE + GEMINI_DRAM_BASE)) +#define KERN_PHYSTOV(pa) \ + ((vaddr_t)((paddr_t)pa - GEMINI_DRAM_BASE + KERNEL_BASE)) + +/* Prototypes */ + +void gemini_intr_init(bus_space_tag_t); +void consinit(void); +#ifdef KGDB +static void kgdb_port_init(void); +#endif + +static void setup_real_page_tables(void); +static void init_clocks(void); + +bs_protos(bs_notimpl); + +#include "com.h" +#if NCOM > 0 +#include <dev/ic/comreg.h> +#include <dev/ic/comvar.h> +#endif + +/* + * void cpu_reboot(int howto, char *bootstr) + * + * Reboots the system + * + * Deal with any syncing, unmounting, dumping and shutdown hooks, + * then reset the CPU. + */ +void +cpu_reboot(int howto, char *bootstr) +{ +#ifdef DIAGNOSTIC + /* info */ + printf("boot: howto=%08x curproc=%p\n", howto, curproc); +#endif + + /* + * If we are still cold then hit the air brakes + * and crash to earth fast + */ + if (cold) { + doshutdownhooks(); + printf("The operating system has halted.\n"); + printf("Please press any key to reboot.\n\n"); + cngetc(); + printf("rebooting...\n"); +#if NGEMINIWDT > 0 + geminiwdt_reboot(); +#endif + cpu_reset(); + /*NOTREACHED*/ + } + + /* Disable console buffering */ +/* cnpollc(1);*/ + + /* + * If RB_NOSYNC was not specified sync the discs. + * Note: Unless cold is set to 1 here, syslogd will die during the + * unmount. It looks like syslogd is getting woken up only to find + * that it cannot page part of the binary in as the filesystem has + * been unmounted. + */ + if (!(howto & RB_NOSYNC)) + bootsync(); + + /* Say NO to interrupts */ + splhigh(); + + /* Do a dump if requested. */ + if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) + dumpsys(); + + /* Run any shutdown hooks */ + doshutdownhooks(); + + /* Make sure IRQ's are disabled */ + IRQdisable; + + if (howto & RB_HALT) { + printf("The operating system has halted.\n"); + printf("Please press any key to reboot.\n\n"); + cngetc(); + } + + printf("rebooting...\n"); +#if NGEMINIWDT > 0 + geminiwdt_reboot(); +#endif + cpu_reset(); + /*NOTREACHED*/ +} + +/* + * Static device mappings. These peripheral registers are mapped at + * fixed virtual addresses very early in initarm() so that we can use + * them while booting the kernel, and stay at the same address + * throughout whole kernel's life time. + * + * We use this table twice; once with bootstrap page table, and once + * with kernel's page table which we build up in initarm(). + * + * Since we map these registers into the bootstrap page table using + * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map + * registers segment-aligned and segment-rounded in order to avoid + * using the 2nd page tables. + */ + +#define _A(a) ((a) & ~L1_S_OFFSET) +#define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) + +static const struct pmap_devmap devmap[] = { + /* Watchdog */ + { + .pd_va = _A(GEMINI_WATCHDOG_VBASE), + .pd_pa = _A(GEMINI_WATCHDOG_BASE), + .pd_size = _S(L1_S_SIZE), + .pd_prot = VM_PROT_READ|VM_PROT_WRITE, + .pd_cache = PTE_NOCACHE + }, + + /* UART */ + { + .pd_va = _A(GEMINI_CONSOLE_VBASE), + .pd_pa = _A(CONSADDR), + .pd_size = _S(L1_S_SIZE), + .pd_prot = VM_PROT_READ|VM_PROT_WRITE, + .pd_cache = PTE_NOCACHE + }, + + /* Timers */ + { + .pd_va = _A(GEMINI_TIMER_VBASE), + .pd_pa = _A(GEMINI_TIMER_BASE), + .pd_size = _S(L1_S_SIZE), + .pd_prot = VM_PROT_READ|VM_PROT_WRITE, + .pd_cache = PTE_NOCACHE + }, + + {0} /* list terminator */ +}; + +#undef _A +#undef _S + +#ifdef DDB +static void gemini_db_trap(int where) +{ +#if NGEMINIWDT > 0 + static int oldwatchdogstate; + + if (where) { + oldwatchdogstate = geminiwdt_enable(0); + } else { + geminiwdt_enable(oldwatchdogstate); + } +#endif +} +#endif + +void gemini_putchar(char c); +void +gemini_putchar(char c) +{ + unsigned char *com0addr = (char *)GEMINI_CONSOLE_VBASE; + int timo = 150000; + + while ((com0addr[COM_REG_LSR * 4] & LSR_TXRDY) == 0) + if (--timo == 0) + break; + + com0addr[COM_REG_TXDATA] = c; + + while ((com0addr[COM_REG_LSR * 4] & LSR_TSRE) == 0) + if (--timo == 0) + break; +} + +void gemini_putchar_xxx(bus_space_tag_t, bus_space_handle_t, char); +void +gemini_putchar_xxx(bus_space_tag_t bst, bus_space_handle_t bsh, char c) +{ + int timo = 150000; + + + while ((bus_space_read_1(bst, bsh, 5) & 0x20) == 0) + if (--timo == 0) + break; + + bus_space_write_1(bst, bsh, 0, c); + + while ((bus_space_read_1(bst, bsh, 5) & 0x40) == 0) + if (--timo == 0) + break; +} + +void gemini_puthex(unsigned int); +void +gemini_puthex(unsigned int val) +{ + char hexc[] = "0123456789abcdef"; + + gemini_putchar('0'); + gemini_putchar('x'); + gemini_putchar(hexc[(val >> 28) & 0xf]); + gemini_putchar(hexc[(val >> 24) & 0xf]); + gemini_putchar(hexc[(val >> 20) & 0xf]); + gemini_putchar(hexc[(val >> 16) & 0xf]); + gemini_putchar(hexc[(val >> 12) & 0xf]); + gemini_putchar(hexc[(val >> 8) & 0xf]); + gemini_putchar(hexc[(val >> 4) & 0xf]); + gemini_putchar(hexc[(val >> 0) & 0xf]); +} + +/* + * u_int initarm(...) + * + * Initial entry point on startup. This gets called before main() is + * entered. + * It should be responsible for setting up everything that must be + * in place when main is called. + * This includes + * Taking a copy of the boot configuration structure. + * Initialising the physical console so characters can be printed. + * Setting up page tables for the kernel + * Relocating the kernel to the bottom of physical memory + */ +u_int +initarm(void *arg) +{ +#if 1 + gemini_putchar('0'); +#endif + /* + * When we enter here, we are using a temporary first level + * translation table with section entries in it to cover the OBIO + * peripherals and SDRAM. The temporary first level translation table + * is at the end of SDRAM. + */ + + /* Heads up ... Setup the CPU / MMU / TLB functions. */ +gemini_putchar('1'); + if (set_cpufuncs()) + panic("cpu not recognized!"); + +gemini_putchar('2'); + init_clocks(); +gemini_putchar('3'); + + /* The console is going to try to map things. Give pmap a devmap. */ + pmap_devmap_register(devmap); +gemini_putchar('4'); + consinit(); +#if 1 + gemini_putchar('5'); +#endif +#ifdef KGDB + kgdb_port_init(); +#endif + +#ifdef VERBOSE_INIT_ARM + /* Talk to the user */ + printf("\nNetBSD/evbarm (gemini) booting ...\n"); +#endif + +#ifdef BOOT_ARGS + char mi_bootargs[] = BOOT_ARGS; + parse_mi_bootargs(mi_bootargs); +#endif + +#ifdef VERBOSE_INIT_ARM + printf("initarm: Configuring system ...\n"); +#endif + + /* + * Set up the variables that define the availability of physical + * memory. + */ + physical_start = GEMINI_DRAM_BASE; +#define MEMSIZE_BYTES (MEMSIZE * 1024 * 1024) + physical_end = (physical_start & ~(0x400000-1)) + MEMSIZE_BYTES; + physmem = (physical_end - physical_start) / PAGE_SIZE; + + /* Fake bootconfig structure for the benefit of pmap.c. */ + bootconfig.dramblocks = 1; + bootconfig.dram[0].address = physical_start; + bootconfig.dram[0].pages = physmem; + + /* + * Our kernel is at the beginning of memory, so set our free space to + * all the memory after the kernel. + */ + physical_freestart = KERN_VTOPHYS(round_page((vaddr_t) _end)); + physical_freeend = physical_end; + free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; + + /* + * This is going to do all the hard work of setting up the first and + * and second level page tables. Pages of memory will be allocated + * and mapped for other structures that are required for system + * operation. When it returns, physical_freestart and free_pages will + * have been updated to reflect the allocations that were made. In + * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack, + * abtstack, undstack, kernelstack, msgbufphys will be set to point to + * the memory that was allocated for them. + */ + setup_real_page_tables(); + + /* + * Moved from cpu_startup() as data_abort_handler() references + * this during uvm init. + */ + proc0paddr = (struct user *)kernelstack.pv_va; + lwp0.l_addr = proc0paddr; + +#ifdef VERBOSE_INIT_ARM + printf("bootstrap done.\n"); +#endif + + arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); + + /* + * Pages were allocated during the secondary bootstrap for the + * stacks for different CPU modes. + * We must now set the r13 registers in the different CPU modes to + * point to these stacks. + * Since the ARM stacks use STMFD etc. we must set r13 to the top end + * of the stack memory. + */ +#ifdef VERBOSE_INIT_ARM + printf("init subsystems: stacks "); +#endif + + set_stackptr(PSR_FIQ32_MODE, fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); + + /* + * Well we should set a data abort handler. + * Once things get going this will change as we will need a proper + * handler. + * Until then we will use a handler that just panics but tells us + * why. + * Initialisation of the vectors will just panic on a data abort. + * This just fills in a slightly better one. + */ +#ifdef VERBOSE_INIT_ARM + printf("vectors "); +#endif + data_abort_handler_address = (u_int)data_abort_handler; + prefetch_abort_handler_address = (u_int)prefetch_abort_handler; + undefined_handler_address = (u_int)undefinedinstruction_bounce; + + /* Initialise the undefined instruction handlers */ +#ifdef VERBOSE_INIT_ARM + printf("undefined "); +#endif + undefined_init(); + + /* Load memory into UVM. */ +#ifdef VERBOSE_INIT_ARM + printf("page "); +#endif + uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ + uvm_page_physload(atop(physical_freestart), atop(physical_freeend), + atop(physical_freestart), atop(physical_freeend), + VM_FREELIST_DEFAULT); + + /* Boot strap pmap telling it where the kernel page table is */ +#ifdef VERBOSE_INIT_ARM + printf("pmap "); +#endif + pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); + +#ifdef VERBOSE_INIT_ARM + printf("done.\n"); +#endif + +#ifdef IPKDB + /* Initialise ipkdb */ + ipkdb_init(); + if (boothowto & RB_KDB) + ipkdb_connect(0); +#endif + +#ifdef KGDB + if (boothowto & RB_KDB) { + kgdb_debug_init = 1; + kgdb_connect(1); + } +#endif + +#ifdef DDB + db_trap_callback = gemini_db_trap; + db_machine_init(); + + /* Firmware doesn't load symbols. */ + ddb_init(0, NULL, NULL); + + if (boothowto & RB_KDB) + Debugger(); +#endif + printf("initarm done.\n"); + + /* We return the new stack pointer address */ + return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); +} + +static void +init_clocks(void) +{ +} + +#ifndef CONSADDR +#error Specify the address of the console UART with the CONSADDR option. +#endif +#ifndef CONSPEED +#define CONSPEED 19200 +#endif +#ifndef CONMODE +#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +#endif + +static const bus_addr_t consaddr = CONSADDR; +static const int conspeed = CONSPEED; +static const int conmode = CONMODE; + +void +consinit(void) +{ + bus_space_handle_t bh; + static int consinit_called = 0; + + if (consinit_called != 0) + return; + + consinit_called = 1; + + if (bus_space_map(&gemini_a4x_bs_tag, consaddr, + GEMINI_UART_SIZE, 0, &bh)) + panic("Serial console can not be mapped."); + + if (comcnattach(&gemini_a4x_bs_tag, consaddr, conspeed, + GEMINI_COM_FREQ, COM_TYPE_16550_NOERS, conmode)) + panic("Serial console can not be initialized."); + + bus_space_unmap(&gemini_a4x_bs_tag, bh, GEMINI_UART_SIZE); +} + +#ifdef KGDB +#ifndef KGDB_DEVADDR +#error Specify the address of the kgdb UART with the KGDB_DEVADDR option. +#endif +#ifndef KGDB_DEVRATE +#define KGDB_DEVRATE 19200 +#endif + +#ifndef KGDB_DEVMODE +#define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +#endif +static const vaddr_t comkgdbaddr = KGDB_DEVADDR; +static const int comkgdbspeed = KGDB_DEVRATE; +static const int comkgdbmode = KGDB_DEVMODE; + +void +static kgdb_port_init(void) +{ + static int kgdbsinit_called = 0; + + if (kgdbsinit_called != 0) + return; + + kgdbsinit_called = 1; + + bus_space_handle_t bh; + if (bus_space_map(&gemini_a4x_bs_tag, comkgdbaddr, + GEMINI_UART_SIZE, 0, &bh)) + panic("kgdb port can not be mapped."); + + if (com_kgdb_attach(&gemini_a4x_bs_tag, comkgdbaddr, comkgdbspeed, + GEMINI_UART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode)) + panic("KGDB uart can not be initialized."); + + bus_space_unmap(&gemini_a4x_bs_tag, bh, GEMINI_UART_SIZE); +} +#endif + +static void +setup_real_page_tables(void) +{ + /* + * We need to allocate some fixed page tables to get the kernel going. + * + * We are going to allocate our bootstrap pages from the beginning of + * the free space that we just calculated. We allocate one page + * directory and a number of page tables and store the physical + * addresses in the kernel_pt_table array. + * + * The kernel page directory must be on a 16K boundary. The page + * tables must be on 4K boundaries. What we do is allocate the + * page directory on the first 16K boundary that we encounter, and + * the page tables on 4K boundaries otherwise. Since we allocate + * at least 3 L2 page tables, we are guaranteed to encounter at + * least one 16K aligned region. + */ + +#ifdef VERBOSE_INIT_ARM + printf("Allocating page tables\n"); +#endif + + /* + * Define a macro to simplify memory allocation. As we allocate the + * memory, make sure that we don't walk over our temporary first level + * translation table. + */ +#define valloc_pages(var, np) \ + (var).pv_pa = physical_freestart; \ + physical_freestart += ((np) * PAGE_SIZE); \ + if (physical_freestart > (physical_freeend - L1_TABLE_SIZE)) \ + panic("initarm: out of memory"); \ + free_pages -= (np); \ + (var).pv_va = KERN_PHYSTOV((var).pv_pa); \ + memset((char *)(var).pv_va, 0, ((np) * PAGE_SIZE)); + + int loop, pt_index; + + pt_index = 0; + kernel_l1pt.pv_pa = 0; + kernel_l1pt.pv_va = 0; +printf("%s: physical_freestart %#lx\n", __func__, physical_freestart); + for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { + /* Are we 16KB aligned for an L1 ? */ + if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0 + && kernel_l1pt.pv_pa == 0) { + valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + } else { + valloc_pages(kernel_pt_table[pt_index], + L2_TABLE_SIZE / PAGE_SIZE); + ++pt_index; + } + } +pt_index=0; +printf("%s: kernel_l1pt: %#lx:%#lx\n", __func__, kernel_l1pt.pv_va, kernel_l1pt.pv_pa); +printf("%s: kernel_pt_table:\n", __func__); +for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { +printf("\t%#lx:%#lx\n", kernel_pt_table[pt_index].pv_va, kernel_pt_table[pt_index].pv_pa); +++pt_index; +} + + /* This should never be able to happen but better confirm that. */ + if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) + panic("initarm: Failed to align the kernel page directory"); + + /* + * Allocate a page for the system page mapped to V0x00000000 + * This page will just contain the system vectors and can be + * shared by all processes. + */ + valloc_pages(systempage, 1); + systempage.pv_va = ARM_VECTORS_HIGH; + + /* Allocate stacks for all modes */ + valloc_pages(fiqstack, FIQ_STACK_SIZE); + valloc_pages(irqstack, IRQ_STACK_SIZE); + valloc_pages(abtstack, ABT_STACK_SIZE); + valloc_pages(undstack, UND_STACK_SIZE); + valloc_pages(kernelstack, UPAGES); + + /* Allocate the message buffer. */ + pv_addr_t msgbuf; + int msgbuf_pgs = round_page(MSGBUFSIZE) / PAGE_SIZE; + valloc_pages(msgbuf, msgbuf_pgs); + msgbufphys = msgbuf.pv_pa; + + /* + * Ok we have allocated physical pages for the primary kernel + * page tables + */ + +#ifdef VERBOSE_INIT_ARM + printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); +#endif + + /* + * Now we start construction of the L1 page table + * We start by mapping the L2 page tables into the L1. + * This means that we can replace L1 mappings later on if necessary + */ + vaddr_t l1_va = kernel_l1pt.pv_va; + paddr_t l1_pa = kernel_l1pt.pv_pa; + + /* Map the L2 pages tables in the L1 page table */ + pmap_link_l2pt(l1_va, ARM_VECTORS_HIGH & ~(0x00400000 - 1), + &kernel_pt_table[KERNEL_PT_SYS]); + for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) + pmap_link_l2pt(l1_va, KERNEL_BASE + loop * 0x00400000, + &kernel_pt_table[KERNEL_PT_KERNEL + loop]); + for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) + pmap_link_l2pt(l1_va, KERNEL_VM_BASE + loop * 0x00400000, + &kernel_pt_table[KERNEL_PT_VMDATA + loop]); + + /* update the top of the kernel VM */ + pmap_curmaxkvaddr = + KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); + +#ifdef VERBOSE_INIT_ARM + printf("Mapping kernel\n"); +#endif + + /* Now we fill in the L2 pagetable for the kernel static code/data */ +#define round_L_page(x) (((x) + L2_L_OFFSET) & L2_L_FRAME) + size_t textsize = round_L_page(etext - KERNEL_BASE_virt); + size_t totalsize = round_L_page(_end - KERNEL_BASE_virt); + /* offset of kernel in RAM */ + u_int offset = (u_int)KERNEL_BASE_virt - KERNEL_BASE; + + /* Map text section read-only. */ + offset += pmap_map_chunk(l1_va, + (vaddr_t)KERNEL_BASE + offset, + physical_start + offset, textsize, + VM_PROT_READ|VM_PROT_EXECUTE, PTE_CACHE); + /* Map data and bss sections read-write. */ + offset += pmap_map_chunk(l1_va, + (vaddr_t)KERNEL_BASE + offset, + physical_start + offset, totalsize - textsize, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + +#ifdef VERBOSE_INIT_ARM + printf("Constructing L2 page tables\n"); +#endif + + /* Map the stack pages */ + pmap_map_chunk(l1_va, fiqstack.pv_va, fiqstack.pv_pa, + FIQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1_va, irqstack.pv_va, irqstack.pv_pa, + IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1_va, abtstack.pv_va, abtstack.pv_pa, + ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1_va, undstack.pv_va, undstack.pv_pa, + UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1_va, kernelstack.pv_va, kernelstack.pv_pa, + UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE); + + pmap_map_chunk(l1_va, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, + L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE); + + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + pmap_map_chunk(l1_va, kernel_pt_table[loop].pv_va, + kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, + VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + } + + /* Map the vector page. */ + pmap_map_entry(l1_va, ARM_VECTORS_HIGH, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + /* + * Map integrated peripherals at same address in first level page + * table so that we can continue to use console. + */ + pmap_devmap_bootstrap(l1_va, devmap); + + +#ifdef VERBOSE_INIT_ARM + /* Tell the user about where all the bits and pieces live. */ + printf("%22s Physical Virtual Num\n", " "); + printf("%22s Starting Ending Starting Ending Pages\n", " "); + + static const char mem_fmt[] = + "%20s: 0x%08lx 0x%08lx 0x%08lx 0x%08lx %d\n"; + static const char mem_fmt_nov[] = + "%20s: 0x%08lx 0x%08lx %d\n"; + + printf(mem_fmt, "SDRAM", physical_start, physical_end-1, + KERN_PHYSTOV(physical_start), KERN_PHYSTOV(physical_end-1), + physmem); + printf(mem_fmt, "text section", + KERN_VTOPHYS(KERNEL_BASE_virt), KERN_VTOPHYS(etext-1), + (vaddr_t)KERNEL_BASE_virt, (vaddr_t)etext-1, + (int)(textsize / PAGE_SIZE)); + printf(mem_fmt, "data section", + KERN_VTOPHYS(__data_start), KERN_VTOPHYS(_edata), + (vaddr_t)__data_start, (vaddr_t)_edata, + (int)((round_page((vaddr_t)_edata) + - trunc_page((vaddr_t)__data_start)) / PAGE_SIZE)); + printf(mem_fmt, "bss section", + KERN_VTOPHYS(__bss_start), KERN_VTOPHYS(__bss_end__), + (vaddr_t)__bss_start, (vaddr_t)__bss_end__, + (int)((round_page((vaddr_t)__bss_end__) + - trunc_page((vaddr_t)__bss_start)) / PAGE_SIZE)); + printf(mem_fmt, "L1 page directory", + kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1, + kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1, + L1_TABLE_SIZE / PAGE_SIZE); + printf(mem_fmt, "Exception Vectors", + systempage.pv_pa, systempage.pv_pa + PAGE_SIZE - 1, + (vaddr_t)ARM_VECTORS_HIGH, (vaddr_t)ARM_VECTORS_HIGH + PAGE_SIZE - 1, + 1); + printf(mem_fmt, "FIQ stack", + fiqstack.pv_pa, fiqstack.pv_pa + (FIQ_STACK_SIZE * PAGE_SIZE) - 1, + fiqstack.pv_va, fiqstack.pv_va + (FIQ_STACK_SIZE * PAGE_SIZE) - 1, + FIQ_STACK_SIZE); + printf(mem_fmt, "IRQ stack", + irqstack.pv_pa, irqstack.pv_pa + (IRQ_STACK_SIZE * PAGE_SIZE) - 1, + irqstack.pv_va, irqstack.pv_va + (IRQ_STACK_SIZE * PAGE_SIZE) - 1, + IRQ_STACK_SIZE); + printf(mem_fmt, "ABT stack", + abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1, + abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1, + ABT_STACK_SIZE); + printf(mem_fmt, "UND stack", + undstack.pv_pa, undstack.pv_pa + (UND_STACK_SIZE * PAGE_SIZE) - 1, + undstack.pv_va, undstack.pv_va + (UND_STACK_SIZE * PAGE_SIZE) - 1, + UND_STACK_SIZE); + printf(mem_fmt, "SVC stack", + kernelstack.pv_pa, kernelstack.pv_pa + (UPAGES * PAGE_SIZE) - 1, + kernelstack.pv_va, kernelstack.pv_va + (UPAGES * PAGE_SIZE) - 1, + UPAGES); + printf(mem_fmt_nov, "Message Buffer", + msgbufphys, msgbufphys + msgbuf_pgs * PAGE_SIZE - 1, msgbuf_pgs); + printf(mem_fmt, "Free Memory", physical_freestart, physical_freeend-1, + KERN_PHYSTOV(physical_freestart), KERN_PHYSTOV(physical_freeend-1), + free_pages); +#endif + + /* + * Now we have the real page tables in place so we can switch to them. + * Once this is done we will be running with the REAL kernel page + * tables. + */ + + /* Switch tables */ +#ifdef VERBOSE_INIT_ARM + printf("switching to new L1 page table @%#lx...", l1_pa); +#endif + + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); + setttb(l1_pa); + cpu_tlb_flushID(); + cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); + +#ifdef VERBOSE_INIT_ARM + printf("OK.\n"); +#endif +} diff --git a/sys/arch/evbarm/gemini/gemini_start.S b/sys/arch/evbarm/gemini/gemini_start.S new file mode 100644 index 00000000000..fab5d9010f1 --- /dev/null +++ b/sys/arch/evbarm/gemini/gemini_start.S @@ -0,0 +1,378 @@ +/* $NetBSD: gemini_start.S,v 1.1 2008/10/24 04:23:18 matt Exp $ */ + +/* + * Machine dependant startup code for GEMINI boards. + * Based on omap_start.S + * + * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * 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. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + * + * Copyright (c) 2003 + * Ichiro FUKUHARA <ichiro@ichiro.org>. + * All rights reserved. + * + * 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 by Ichiro FUKUHARA. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``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 ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD 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. + * + * Copyright (c) 2007 Microsoft + * All rights reserved. + * + * 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 by Microsoft + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTERS 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. + */ + +#include "opt_gemini.h" +#include "opt_com.h" +#include "assym.h" + +#include <machine/asm.h> +#include <arm/armreg.h> +#undef DOMAIN_CLIENT /* assym.h defines as 1, but pte.h defines as 0x01 */ +#include <arm/arm32/pmap.h> +#include <arm/gemini/gemini_reg.h> +#include <evbarm/gemini/gemini.h> + +RCSID("$NetBSD: gemini_start.S,v 1.1 2008/10/24 04:23:18 matt Exp $") + + +#define _PUTCHAR(addr, areg, breg, c) \ + ldr areg, addr; \ +1: \ + ldr breg, [ areg, #0x14 ]; /* LSR */ \ + tst breg, #0x20; /* TXRDY? */ \ + beq 1b; \ + mov breg, #(c); /* c */ \ + str breg, [ areg ]; /* TXDATA */ \ +2: \ + ldr breg, [ areg, #0x14 ]; /* LSR */ \ + tst breg, #0x40; /* TSRE? */ \ + beq 2b; + + +/* + * Kernel start routine for GEMINI Eval board. + * At this point, this code has been loaded into SDRAM + * and the MMU is off + */ + .section .start,"ax",%progbits + + .global _C_LABEL(gemini_start) +_C_LABEL(gemini_start): + /* Move into supervisor mode and disable IRQs/FIQs. */ + mrs r0, cpsr + bic r0, r0, #PSR_MODE + orr r0, r0, #(I32_bit | F32_bit | PSR_SVC32_MODE) + msr cpsr, r0 + + _PUTCHAR(Lconsole_pbase, r4, r3, 'a') + + /* + * Set up a preliminary mapping in the MMU to allow us to run + * at KERNEL_BASE with caches on. + */ + /* Build page table from scratch */ + ldr r0, Ltemp_l1_table + mov r1, r0 /* Save the page table address. */ + /* Zero the entire table so all virtual addresses are invalid. */ + mov r2, #L1_TABLE_SIZE /* in bytes */ + mov r3, #0 + mov r4, r3 + mov r5, r3 + mov r6, r3 + mov r7, r3 + mov r8, r3 + mov r10, r3 + mov r11, r3 +1: stmia r1!, {r3-r8,r10-r11} + stmia r1!, {r3-r8,r10-r11} + stmia r1!, {r3-r8,r10-r11} + stmia r1!, {r3-r8,r10-r11} + subs r2, r2, #(4 * 4 * 8) /* bytes per loop */ + bne 1b + + _PUTCHAR(Lconsole_pbase, r4, r3, 'b') + + /* Now create our entries per the mmu_init_table. */ + l1table .req r0 + va .req r1 + pa .req r2 + n_sec .req r3 + attr .req r4 + itable .req r5 + l1sfrm .req r6 + ldr l1table, Ltemp_l1_table + adr itable, mmu_init_table + ldr l1sfrm, Ll1_s_frame + b 3f +2: str pa, [l1table, va] + add va, va, #4 + add pa, pa, #(L1_S_SIZE) + adds n_sec, n_sec, #-1 + bhi 2b +3: ldmia itable!, {va,pa,n_sec,attr} + /* Convert va to l1 offset: va = 4 * (va >> L1_S_SHIFT) */ + mov va, va, LSR #L1_S_SHIFT + mov va, va, LSL #2 + /* Convert pa to l1 entry: pa = (pa & L1_S_FRAME) | attr */ + and pa, pa, l1sfrm + orr pa, pa, attr + cmp n_sec, #0 + bne 2b + mov r5, r0 /* l1table */ + .unreq va + .unreq pa + .unreq n_sec + .unreq attr + .unreq itable + .unreq l1table + .unreq l1sfrm + + _PUTCHAR(Lconsole_pbase, r4, r3, 'c') + + /* + * using FA526 -specific cache ops here... + */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* Invalidate Entire I cache */ + mcr p15, 0, r0, c7, c14, 0 /* Clean & Invalidate Entire D cache */ + + ldr r2, Lctl_ID_dis /* Disable I+D caches */ + mrc p15, 0, r1, c1, c0, 0 /* " " " */ + and r1, r1, r2 /* " " " */ + mcr p15, 0, r1, c1, c0, 0 /* " " " */ + + _PUTCHAR(Lconsole_pbase, r4, r3, 'd') + + mcr p15, 0, r0, c7, c5, 6 /* invalidate BTB all */ + mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffers. */ + mcr p15, 0, r5, c2, c0, 0 /* Set Translation Table Base */ + mcr p15, 0, r0, c8, c7, 0 /* Invalidate TLBs */ + + /* Set the Domain Access register */ + mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) + mcr p15, 0, r0, c3, c0, 0 + + /* + * set Extension Control Enable in ECR, so we can use BTB + */ + ldr r0, Lecr_set + mcr p15, 0, r0, c1, c1, 0 + + /* + * Enable the MMU, etc. + */ + mrc p15, 0, r0, c1, c0, 0 + ldr r1, Lcontrol_wax + and r0, r0, r1 + ldr r1, Lcontrol_clr + mvn r1, r1 + and r0, r0, r1 + ldr r1, Lcontrol_set + orr r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + /* + * Ensure that the coprocessor has finished turning on the MMU. + */ + mrc p15, 0, r0, c2, c0, 0 /* Read an arbitrary value. */ + mov r0, r0 /* Stall until read completes. */ + + _PUTCHAR(Lconsole_vbase, r4, r3, 'e') + + /* + * Zero .bss + */ + ldr r0, L_edata + ldr r1, L_end + mov r2, #0 +1: + str r2, [r0], #0x04 /* *r0++ = r2 */ + cmp r0, r1 + bne 1b + +#if 0 + /* + * Jump to start in locore.S, which in turn will call initarm and main. + */ + adr r0, Ltestjmp + ldr pc, [r0] + nop + nop + nop + nop +testjmp: +#endif + + _PUTCHAR(Lconsole_vbase, r4, r3, 'f') + + adr r0, Lstart + ldr pc, [r0] + nop + nop + nop + nop + + /* NOTREACHED */ + +L_edata: + .word _C_LABEL(_edata) +L_end: + .word _C_LABEL(_end) + +#if 0 +Ltestjmp: + .word testjmp +#endif + +Lstart: + .word start +Ll1_s_frame: + .word L1_S_FRAME +Ltemp_l1_table: + /* Put the temporary L1 translation table at the end of SDRAM. */ + .word 0x10000000 + MEMSIZE * 0x100000 - L1_TABLE_SIZE + +/* + * Coprocessor register initialization values + */ +#if !defined(CPU_ECR_ECE) +# define CPU_ECR_ECE 1 +#endif + /* bits to set in the Extension Control Register */ +Lecr_set: + .word CPU_ECR_ECE + +#if !defined(CPU_CONTROL_BTB_ENABLE) +# define CPU_CONTROL_BTB_ENABLE (1 << 11) +#endif + /* bits to set in the Control Register */ + /* bits 6..4 SB1 */ +Lcontrol_set: + .word CPU_CONTROL_MMU_ENABLE | \ + CPU_CONTROL_AFLT_ENABLE | \ + CPU_CONTROL_DC_ENABLE | \ + CPU_CONTROL_WBUF_ENABLE | \ + CPU_CONTROL_32BP_ENABLE | \ + CPU_CONTROL_32BD_ENABLE | \ + CPU_CONTROL_LABT_ENABLE | \ + CPU_CONTROL_SYST_ENABLE | \ + CPU_CONTROL_IC_ENABLE | \ + CPU_CONTROL_DC_ENABLE | \ + CPU_CONTROL_BTB_ENABLE + + /* bits to clear in the Control Register */ + /* bits 31..14, 10, SBZ */ +Lcontrol_clr: + .word ((~0) << 14) | \ + (1 << 10) + + /* bits to "write as existing" in the Control Register */ +Lcontrol_wax: + .word CPU_CONTROL_BEND_ENABLE + + /* bits to disable the caches */ +Lctl_ID_dis: + .word ~(CPU_CONTROL_IC_ENABLE|CPU_CONTROL_DC_ENABLE) + + /* console addressing */ +Lconsole_pbase: + .word CONSADDR +Lconsole_vbase: + .word GEMINI_CONSOLE_VBASE + + +/* We'll modify va and pa at run time so we can use relocatable addresses. */ +#define MMU_INIT(va,pa,n_sec,attr) \ + .word va ; \ + .word pa ; \ + .word n_sec ; \ + .word attr ; + +mmu_init_table: + /* Maintain current 1:1 addressability */ + MMU_INIT(KERNEL_BASE_phys, KERNEL_BASE_phys, + (MEMSIZE * L1_S_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, + L1_S_PROTO | L1_S_AP(AP_KRW) | L1_S_B | L1_S_C) + + /* Map Kernel base VA:PA, write-back cacheable */ + MMU_INIT(KERNEL_BASE_virt, KERNEL_BASE_phys, + (MEMSIZE * L1_S_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, + L1_S_PROTO | L1_S_AP(AP_KRW) | L1_S_B | L1_S_C) + + /* Map console UART */ + MMU_INIT(GEMINI_CONSOLE_VBASE, CONSADDR, + 1, + L1_S_PROTO | L1_S_AP(AP_KRW)) + + /* end of table */ + MMU_INIT(0, 0, 0, 0) + |
