diff options
author | Warner Losh <imp@FreeBSD.org> | 2018-07-27 21:25:01 +0000 |
---|---|---|
committer | Warner Losh <imp@FreeBSD.org> | 2018-07-27 21:25:01 +0000 |
commit | c81b12e0d76c114c5c10ab1e164fd42dae6512d9 (patch) | |
tree | a00bbc800435c300d74c362b5dce8c495c43c222 /sys/arm/xscale | |
parent | 520c80f1b26d74f0d8b06b9818e36b8438fc6f7d (diff) | |
download | src-c81b12e0d76c114c5c10ab1e164fd42dae6512d9.tar.gz src-c81b12e0d76c114c5c10ab1e164fd42dae6512d9.zip |
Revert r336773: it removed too much.
r336773 removed all things xscale. However, some things xscale are
really armv5. Revert that entirely. A more modest removal will follow.
Noticed by: andrew@
Notes
Notes:
svn path=/head/; revision=336783
Diffstat (limited to 'sys/arm/xscale')
37 files changed, 7775 insertions, 0 deletions
diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c new file mode 100644 index 000000000000..93687efd7e13 --- /dev/null +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -0,0 +1,333 @@ +/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 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 BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * machdep.c + * + * Machine dependent functions for kernel setup + * + * This file needs a lot of work. + * + * Created : 17/09/94 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_kstack_pages.h" + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/imgact.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/linker.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/cons.h> +#include <sys/bio.h> +#include <sys/bus.h> +#include <sys/buf.h> +#include <sys/exec.h> +#include <sys/kdb.h> +#include <sys/msgbuf.h> +#include <sys/devmap.h> +#include <machine/reg.h> +#include <machine/cpu.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <machine/vmparam.h> +#include <machine/pcb.h> +#include <machine/undefined.h> +#include <machine/machdep.h> +#include <machine/metadata.h> +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/physmem.h> +#include <sys/reboot.h> + + +#include <arm/xscale/i8134x/i80321var.h> /* For i80321_calibrate_delay() */ + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/i81342var.h> +#include <arm/xscale/i8134x/obiovar.h> + + +#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ +#define KERNEL_PT_IOPXS 1 +#define KERNEL_PT_BEFOREKERN 2 +#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ +#define KERNEL_PT_AFKERNEL_NUM 9 + +/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ +#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) + +struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; + +/* Physical and virtual addresses for some global pages */ + +struct pv_addr systempage; +struct pv_addr msgbufpv; +struct pv_addr irqstack; +struct pv_addr undstack; +struct pv_addr abtstack; +struct pv_addr kernelstack; + +/* Static device mappings. */ +static const struct devmap_entry iq81342_devmap[] = { + { + IOP34X_VADDR, + IOP34X_HWADDR, + IOP34X_SIZE, + }, + { + /* + * Cheat and map a whole section, this will bring + * both PCI-X and PCI-E outbound I/O + */ + rounddown2(IOP34X_PCIX_OIOBAR_VADDR, 0x100000), + rounddown2(IOP34X_PCIX_OIOBAR, 0x100000), + 0x100000, + }, + { + IOP34X_PCE1_VADDR, + IOP34X_PCE1, + IOP34X_PCE1_SIZE, + }, + { + 0, + 0, + 0, + } +}; + +#define SDRAM_START 0x00000000 + +extern vm_offset_t xscale_cache_clean_addr; + +void * +initarm(struct arm_boot_params *abp) +{ + struct pv_addr kernel_l1pt; + struct pv_addr dpcpu; + int loop, i; + u_int l1pagetable; + vm_offset_t freemempos; + vm_offset_t freemem_pt; + vm_offset_t afterkern; + vm_offset_t freemem_after; + vm_offset_t lastaddr; + uint32_t memsize, memstart; + + lastaddr = parse_boot_param(abp); + arm_physmem_kernaddr = abp->abp_physaddr; + set_cpufuncs(); + pcpu_init(pcpup, 0, sizeof(struct pcpu)); + PCPU_SET(curthread, &thread0); + + /* Do basic tuning, hz etc */ + init_param1(); + + freemempos = 0x00200000; + /* Define a macro to simplify memory allocation */ +#define valloc_pages(var, np) \ + alloc_pages((var).pv_pa, (np)); \ + (var).pv_va = (var).pv_pa + 0xc0000000; + +#define alloc_pages(var, np) \ + freemempos -= (np * PAGE_SIZE); \ + (var) = freemempos; \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + + while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) + freemempos -= PAGE_SIZE; + valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { + valloc_pages(kernel_pt_table[loop], + L2_TABLE_SIZE / PAGE_SIZE); + } else { + kernel_pt_table[loop].pv_pa = freemempos + + (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * + L2_TABLE_SIZE_REAL; + kernel_pt_table[loop].pv_va = + kernel_pt_table[loop].pv_pa + 0xc0000000; + } + } + freemem_pt = freemempos; + freemempos = 0x00100000; + /* + * 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); + + /* Allocate dynamic per-cpu area. */ + valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); + dpcpu_init((void *)dpcpu.pv_va, 0); + + /* Allocate stacks for all modes */ + valloc_pages(irqstack, IRQ_STACK_SIZE); + valloc_pages(abtstack, ABT_STACK_SIZE); + valloc_pages(undstack, UND_STACK_SIZE); + valloc_pages(kernelstack, kstack_pages); + valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); + /* + * 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 + */ + l1pagetable = kernel_l1pt.pv_va; + + /* Map the L2 pages tables in the L1 page table */ + pmap_link_l2pt(l1pagetable, rounddown2(ARM_VECTORS_HIGH, 0x00100000), + &kernel_pt_table[KERNEL_PT_SYS]); + pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000, + 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + + pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000, + rounddown2(((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE, L1_S_SIZE), + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + freemem_after = rounddown2((int)lastaddr + PAGE_SIZE, PAGE_SIZE); + afterkern = round_page(rounddown2((vm_offset_t)lastaddr + L1_S_SIZE, L1_S_SIZE)); + for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { + pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, + &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); + } + + + /* Map the vector page. */ + pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + devmap_bootstrap(l1pagetable, iq81342_devmap); + /* + * Give the XScale global cache clean code an appropriately + * sized chunk of unmapped VA space starting at 0xff000000 + * (our device mappings end before this address). + */ + xscale_cache_clean_addr = 0xff000000U; + + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); + cpu_setttb(kernel_l1pt.pv_pa); + cpu_tlb_flushID(); + cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); + /* + * 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. + */ + + set_stackptrs(0); + + /* + * We must now clean the cache again.... + * Cleaning may be done by reading new data to displace any + * dirty data in the cache. This will have happened in cpu_setttb() + * but since we are boot strapping the addresses used for the read + * may have just been remapped and thus the cache could be out + * of sync. A re-clean after the switch will cure this. + * After booting there are no gross relocations of the kernel thus + * this problem will not occur after initarm(). + */ + cpu_idcache_wbinv_all(); + cpu_setup(); + + i80321_calibrate_delay(); + i81342_sdram_bounds(arm_base_bs_tag, IOP34X_VADDR, &memstart, &memsize); + physmem = memsize / PAGE_SIZE; + cninit(); + /* Set stack for exception handlers */ + + undefined_init(); + + init_proc0(kernelstack.pv_va); + + arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); + + pmap_curmaxkvaddr = afterkern + PAGE_SIZE; + + vm_max_kernel_address = 0xe0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); + msgbufp = (void*)msgbufpv.pv_va; + msgbufinit(msgbufp, msgbufsize); + mutex_init(); + + /* + * Add the physical ram we have available. + * + * Exclude the kernel (and all the things we allocated which immediately + * follow the kernel) from the VM allocation pool but not from crash + * dumps. virtual_avail is a global variable which tracks the kva we've + * "allocated" while setting up pmaps. + * + * Prepare the list of physical memory available to the vm subsystem. + */ + arm_physmem_hardware_region(SDRAM_START, memsize); + arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - + freemem_pt, EXFLAG_NOALLOC); + arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - + freemempos, EXFLAG_NOALLOC); + arm_physmem_exclude_region(abp->abp_physaddr, + virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); + arm_physmem_init_kernel_globals(); + + init_param2(physmem); + kdb_init(); + return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - + sizeof(struct pcb))); +} diff --git a/sys/arm/xscale/i8134x/files.crb b/sys/arm/xscale/i8134x/files.crb new file mode 100644 index 000000000000..25398af60f95 --- /dev/null +++ b/sys/arm/xscale/i8134x/files.crb @@ -0,0 +1,3 @@ +# $FreeBSD$ +arm/xscale/i8134x/crb_machdep.c standard +arm/xscale/i8134x/iq81342_7seg.c optional 7seg diff --git a/sys/arm/xscale/i8134x/files.i81342 b/sys/arm/xscale/i8134x/files.i81342 new file mode 100644 index 000000000000..63c715cb4be7 --- /dev/null +++ b/sys/arm/xscale/i8134x/files.i81342 @@ -0,0 +1,12 @@ +# $FreeBSD$ +arm/arm/bus_space_base.c standard +arm/xscale/i8134x/i80321_timer.c standard +arm/xscale/i8134x/i80321_wdog.c optional iopwdog +arm/xscale/i8134x/i81342.c standard +arm/xscale/i8134x/i81342_mcu.c standard +arm/xscale/i8134x/i81342_pci.c optional pci +arm/xscale/i8134x/i81342_space.c standard +arm/xscale/i8134x/obio.c standard +arm/xscale/i8134x/uart_bus_i81342.c optional uart +arm/xscale/i8134x/uart_cpu_i81342.c optional uart +dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/xscale/i8134x/i80321_timer.c b/sys/arm/xscale/i8134x/i80321_timer.c new file mode 100644 index 000000000000..5dc650568c0a --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321_timer.c @@ -0,0 +1,486 @@ +/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */ + +/*- + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Timer/clock support for the Intel i80321 I/O processor. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/time.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/timetc.h> + +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <machine/resource.h> +#include <machine/intr.h> +#include <arm/xscale/i8134x/i80321reg.h> +#include <arm/xscale/i8134x/i80321var.h> + +#ifdef CPU_XSCALE_81342 +#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because + definitions overrides the ones from i80321reg.h + */ +#endif +#include "opt_timer.h" + +void (*i80321_hardclock_hook)(void) = NULL; +struct i80321_timer_softc { + device_t dev; +} timer_softc; + + +static unsigned i80321_timer_get_timecount(struct timecounter *tc); + + +static uint32_t counts_per_hz; + +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) +static uint32_t offset; +static uint32_t last = -1; +#endif + +static int ticked = 0; + +#ifndef COUNTS_PER_SEC +#define COUNTS_PER_SEC 200000000 /* 200MHz */ +#endif + +#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000) + +static struct timecounter i80321_timer_timecounter = { + i80321_timer_get_timecount, /* get_timecount */ + NULL, /* no poll_pps */ + ~0u, /* counter_mask */ +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) + COUNTS_PER_SEC, +#else + COUNTS_PER_SEC * 3, /* frequency */ +#endif + "i80321 timer", /* name */ + 1000 /* quality */ +}; + +static int +i80321_timer_probe(device_t dev) +{ + + device_set_desc(dev, "i80321 timer"); + return (0); +} + +static int +i80321_timer_attach(device_t dev) +{ + timer_softc.dev = dev; + + return (0); +} + +static device_method_t i80321_timer_methods[] = { + DEVMETHOD(device_probe, i80321_timer_probe), + DEVMETHOD(device_attach, i80321_timer_attach), + {0, 0}, +}; + +static driver_t i80321_timer_driver = { + "itimer", + i80321_timer_methods, + sizeof(struct i80321_timer_softc), +}; +static devclass_t i80321_timer_devclass; + +DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0); + +int clockhandler(void *); + + +static __inline uint32_t +tmr1_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c1, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c1, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} + +static __inline void +tmr1_write(uint32_t val) +{ + + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c1, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c1, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tcr1_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c3, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c3, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} +static __inline void +tcr1_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c3, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c3, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +trr1_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c5, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c5, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tmr0_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c0, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c0, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} + +static __inline void +tmr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c0, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c0, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tcr0_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c2, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c2, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} +static __inline void +tcr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c2, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c2, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +trr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c4, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c4, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +tisr_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c6, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c6, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tisr_read(void) +{ + int ret; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c6, c9, 0" : "=r" (ret)); +#else + __asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret)); +#endif + return (ret); +} + +static unsigned +i80321_timer_get_timecount(struct timecounter *tc) +{ +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) + uint32_t cur = tcr0_read(); + + if (cur > last && last != -1) { + offset += counts_per_hz; + if (ticked > 0) + ticked--; + } + if (ticked) { + offset += ticked * counts_per_hz; + ticked = 0; + } + return (counts_per_hz - cur + offset); +#else + uint32_t ret; + + __asm __volatile("mrc p14, 0, %0, c1, c0, 0\n" + : "=r" (ret)); + return (ret); +#endif +} + +/* + * i80321_calibrate_delay: + * + * Calibrate the delay loop. + */ +void +i80321_calibrate_delay(void) +{ + + /* + * Just use hz=100 for now -- we'll adjust it, if necessary, + * in cpu_initclocks(). + */ + counts_per_hz = COUNTS_PER_SEC / 100; + + tmr0_write(0); /* stop timer */ + tisr_write(TISR_TMR0); /* clear interrupt */ + trr0_write(counts_per_hz); /* reload value */ + tcr0_write(counts_per_hz); /* current value */ + + tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); +} + +/* + * cpu_initclocks: + * + * Initialize the clock and get them going. + */ +void +cpu_initclocks(void) +{ + u_int oldirqstate; + struct resource *irq; + int rid = 0; + void *ihl; + device_t dev = timer_softc.dev; + + if (hz < 50 || COUNTS_PER_SEC % hz) { + printf("Cannot get %d Hz clock; using 100 Hz\n", hz); + hz = 100; + } + tick = 1000000 / hz; /* number of microseconds between interrupts */ + + /* + * We only have one timer available; stathz and profhz are + * always left as 0 (the upper-layer clock code deals with + * this situation). + */ + if (stathz != 0) + printf("Cannot get %d Hz statclock\n", stathz); + stathz = 0; + + if (profhz != 0) + printf("Cannot get %d Hz profclock\n", profhz); + profhz = 0; + + /* Report the clock frequency. */ + + oldirqstate = disable_interrupts(PSR_I); + + irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, +#ifdef CPU_XSCALE_81342 + ICU_INT_TIMER0, ICU_INT_TIMER0, +#else + ICU_INT_TMR0, ICU_INT_TMR0, +#endif + 1, RF_ACTIVE); + if (!irq) + panic("Unable to setup the clock irq handler.\n"); + else + bus_setup_intr(dev, irq, INTR_TYPE_CLK, clockhandler, NULL, + NULL, &ihl); + tmr0_write(0); /* stop timer */ + tisr_write(TISR_TMR0); /* clear interrupt */ + + counts_per_hz = COUNTS_PER_SEC / hz; + + trr0_write(counts_per_hz); /* reload value */ + tcr0_write(counts_per_hz); /* current value */ + tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); + + tc_init(&i80321_timer_timecounter); + restore_interrupts(oldirqstate); + rid = 0; +#if !defined(XSCALE_DISABLE_CCNT) && !defined(CPU_XSCALE_81342) + /* Enable the clock count register. */ + __asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid)); + rid &= ~(1 << 3); + rid |= (1 << 2) | 1; + __asm __volatile("mcr p14, 0, %0, c0, c0, 0\n" + : : "r" (rid)); +#endif +} + + +/* + * DELAY: + * + * Delay for at least N microseconds. + */ +void +DELAY(int n) +{ + uint32_t cur, last, delta, usecs; + + TSENTER(); + /* + * This works by polling the timer and counting the + * number of microseconds that go by. + */ + last = tcr0_read(); + delta = usecs = 0; + + while (n > usecs) { + cur = tcr0_read(); + + /* 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; + } + } + TSEXIT(); +} + +/* + * clockhandler: + * + * Handle the hardclock interrupt. + */ +int +clockhandler(void *arg) +{ + struct trapframe *frame = arg; + + ticked++; + tisr_write(TISR_TMR0); + hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); + + if (i80321_hardclock_hook != NULL) + (*i80321_hardclock_hook)(); + return (FILTER_HANDLED); +} + +void +cpu_startprofclock(void) +{ +} + +void +cpu_stopprofclock(void) +{ + +} diff --git a/sys/arm/xscale/i8134x/i80321_wdog.c b/sys/arm/xscale/i8134x/i80321_wdog.c new file mode 100644 index 000000000000..72f0fd8511af --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321_wdog.c @@ -0,0 +1,153 @@ +/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */ + +/*- + * Copyright (c) 2005 Olivier Houchard + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Watchdog timer support for the Intel i80321 I/O processor. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/watchdog.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> +#include <machine/machdep.h> + +#include <arm/xscale/i8134x/i80321reg.h> +#include <arm/xscale/i8134x/i80321var.h> + + +struct iopwdog_softc { + device_t dev; + int armed; + int wdog_period; +}; + +static __inline void +wdtcr_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c7, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c7, c1, 0" +#endif + : + : "r" (val)); +} + +static void +iopwdog_tickle(void *arg) +{ + struct iopwdog_softc *sc = arg; + + if (!sc->armed) + return; + wdtcr_write(WDTCR_ENABLE1); + wdtcr_write(WDTCR_ENABLE2); +} + +static int +iopwdog_probe(device_t dev) +{ + struct iopwdog_softc *sc = device_get_softc(dev); + char buf[128]; + + /* + * XXX Should compute the period based on processor speed. + * For a 600MHz XScale core, the wdog must be tickled approx. + * every 7 seconds. + */ + + sc->wdog_period = 7; + sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds", + sc->wdog_period); + device_set_desc_copy(dev, buf); + + return (0); +} + +static void +iopwdog_watchdog_fn(void *private, u_int cmd, int *error) +{ + struct iopwdog_softc *sc = private; + + cmd &= WD_INTERVAL; + if (cmd > 0 && cmd <= 63 + && (uint64_t)1<<cmd <= (uint64_t)sc->wdog_period * 1000000000) { + /* Valid value -> Enable watchdog */ + iopwdog_tickle(sc); + sc->armed = 1; + *error = 0; + } else { + /* Can't disable this watchdog! */ + if (sc->armed) + *error = EOPNOTSUPP; + } +} + +static int +iopwdog_attach(device_t dev) +{ + struct iopwdog_softc *sc = device_get_softc(dev); + + sc->dev = dev; + sc->armed = 0; + EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0); + return (0); +} + +static device_method_t iopwdog_methods[] = { + DEVMETHOD(device_probe, iopwdog_probe), + DEVMETHOD(device_attach, iopwdog_attach), + {0, 0}, +}; + +static driver_t iopwdog_driver = { + "iopwdog", + iopwdog_methods, + sizeof(struct iopwdog_softc), +}; +static devclass_t iopwdog_devclass; + +DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h new file mode 100644 index 000000000000..b6dd4fea14da --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321reg.h @@ -0,0 +1,455 @@ +/* $NetBSD: i80321reg.h,v 1.14 2003/12/19 10:08:11 gavan Exp $ */ + +/*- + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef _ARM_XSCALE_I80321REG_H_ +#define _ARM_XSCALE_I80321REG_H_ + +/* + * Register definitions for the Intel 80321 (``Verde'') I/O processor, + * based on the XScale core. + */ + +/* + * Base i80321 memory map: + * + * 0x0000.0000 - 0x7fff.ffff ATU Outbound Direct Addressing Window + * 0x8000.0000 - 0x9001.ffff ATU Outbound Translation Windows + * 0x9002.0000 - 0xffff.dfff External Memory + * 0xffff.e000 - 0xffff.e8ff Peripheral Memory Mapped Registers + * 0xffff.e900 - 0xffff.ffff Reserved + */ + +#define VERDE_OUT_DIRECT_WIN_BASE 0x00000000UL +#define VERDE_OUT_DIRECT_WIN_SIZE 0x80000000UL + +#define VERDE_OUT_XLATE_MEM_WIN_SIZE 0x04000000UL +#define VERDE_OUT_XLATE_IO_WIN_SIZE 0x00010000UL + +#define VERDE_OUT_XLATE_MEM_WIN0_BASE 0x80000000UL +#define VERDE_OUT_XLATE_MEM_WIN1_BASE 0x84000000UL + +#define VERDE_OUT_XLATE_IO_WIN0_BASE 0x90000000UL + +#define VERDE_EXTMEM_BASE 0x90020000UL + +#define VERDE_PMMR_BASE 0xffffe000UL +#define VERDE_PMMR_SIZE 0x00001700UL + +/* + * Peripheral Memory Mapped Registers. Defined as offsets + * from the VERDE_PMMR_BASE. + */ +#define VERDE_ATU_BASE 0x0100 +#define VERDE_ATU_SIZE 0x0100 + +#define VERDE_MU_BASE 0x0300 +#define VERDE_MU_SIZE 0x0100 + +#define VERDE_DMA_BASE 0x0400 +#define VERDE_DMA_BASE0 (VERDE_DMA_BASE + 0x00) +#define VERDE_DMA_BASE1 (VERDE_DMA_BASE + 0x40) +#define VERDE_DMA_SIZE 0x0100 +#define VERDE_DMA_CHSIZE 0x0040 + +#define VERDE_MCU_BASE 0x0500 +#define VERDE_MCU_SIZE 0x0100 + +#define VERDE_PBIU_BASE 0x0680 +#define VERDE_PBIU_SIZE 0x0080 + +#define VERDE_I2C_BASE 0x1680 +#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00) +#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20) +#define VERDE_I2C_SIZE 0x0080 +#define VERDE_I2C_CHSIZE 0x0020 + +/* + * Address Translation Unit + */ + /* 0x00 - 0x38 -- PCI configuration space header */ +#define ATU_IALR0 0x40 /* Inbound ATU Limit 0 */ +#define ATU_IATVR0 0x44 /* Inbound ATU Xlate Value 0 */ +#define ATU_ERLR 0x48 /* Expansion ROM Limit */ +#define ATU_ERTVR 0x4c /* Expansion ROM Xlate Value */ +#define ATU_IALR1 0x50 /* Inbound ATU Limit 1 */ +#define ATU_IALR2 0x54 /* Inbound ATU Limit 2 */ +#define ATU_IATVR2 0x58 /* Inbound ATU Xlate Value 2 */ +#define ATU_OIOWTVR 0x5c /* Outbound I/O Window Xlate Value */ +#define ATU_OMWTVR0 0x60 /* Outbound Mem Window Xlate Value 0 */ +#define ATU_OUMWTVR0 0x64 /* Outbound Mem Window Xlate Value 0 Upper */ +#define ATU_OMWTVR1 0x68 /* Outbound Mem Window Xlate Value 1 */ +#define ATU_OUMWTVR1 0x6c /* Outbound Mem Window Xlate Value 1 Upper */ +#define ATU_OUDWTVR 0x78 /* Outbound Mem Direct Xlate Value Upper */ +#define ATU_ATUCR 0x80 /* ATU Configuration */ +#define ATU_PCSR 0x84 /* PCI Configuration and Status */ +#define ATU_ATUISR 0x88 /* ATU Interrupt Status */ +#define ATU_ATUIMR 0x8c /* ATU Interrupt Mask */ +#define ATU_IABAR3 0x90 /* Inbound ATU Base Address 3 */ +#define ATU_IAUBAR3 0x94 /* Inbound ATU Base Address 3 Upper */ +#define ATU_IALR3 0x98 /* Inbound ATU Limit 3 */ +#define ATU_IATVR3 0x9c /* Inbound ATU Xlate Value 3 */ +#define ATU_OCCAR 0xa4 /* Outbound Configuration Cycle Address */ +#define ATU_OCCDR 0xac /* Outbound Configuration Cycle Data */ +#define ATU_MSI_PORT 0xb4 /* MSI port */ +#define ATU_PDSCR 0xbc /* PCI Bus Drive Strength Control */ +#define ATU_PCI_X_CAP_ID 0xe0 /* (1) */ +#define ATU_PCI_X_NEXT 0xe1 /* (1) */ +#define ATU_PCIXCMD 0xe2 /* PCI-X Command Register (2) */ +#define ATU_PCIXSR 0xe4 /* PCI-X Status Register */ + +#define ATUCR_DRC_ALIAS (1U << 19) +#define ATUCR_DAU2GXEN (1U << 18) +#define ATUCR_P_SERR_MA (1U << 16) +#define ATUCR_DTS (1U << 15) +#define ATUCR_P_SERR_DIE (1U << 9) +#define ATUCR_DAE (1U << 8) +#define ATUCR_BIST_IE (1U << 3) +#define ATUCR_OUT_EN (1U << 1) + +#define PCSR_DAAAPE (1U << 18) +#define PCSR_PCI_X_CAP (3U << 16) +#define PCSR_PCI_X_CAP_BORING (0 << 16) +#define PCSR_PCI_X_CAP_66 (1U << 16) +#define PCSR_PCI_X_CAP_100 (2U << 16) +#define PCSR_PCI_X_CAP_133 (3U << 16) +#define PCSR_OTQB (1U << 15) +#define PCSR_IRTQB (1U << 14) +#define PCSR_DTV (1U << 12) +#define PCSR_BUS66 (1U << 10) +#define PCSR_BUS64 (1U << 8) +#define PCSR_RIB (1U << 5) +#define PCSR_RPB (1U << 4) +#define PCSR_CCR (1U << 2) +#define PCSR_CPR (1U << 1) + +#define ATUISR_IMW1BU (1U << 14) +#define ATUISR_ISCEM (1U << 13) +#define ATUISR_RSCEM (1U << 12) +#define ATUISR_PST (1U << 11) +#define ATUISR_P_SERR_ASRT (1U << 10) +#define ATUISR_DPE (1U << 9) +#define ATUISR_BIST (1U << 8) +#define ATUISR_IBMA (1U << 7) +#define ATUISR_P_SERR_DET (1U << 4) +#define ATUISR_PMA (1U << 3) +#define ATUISR_PTAM (1U << 2) +#define ATUISR_PTAT (1U << 1) +#define ATUISR_PMPE (1U << 0) + +#define ATUIMR_IMW1BU (1U << 11) +#define ATUIMR_ISCEM (1U << 10) +#define ATUIMR_RSCEM (1U << 9) +#define ATUIMR_PST (1U << 8) +#define ATUIMR_DPE (1U << 7) +#define ATUIMR_P_SERR_ASRT (1U << 6) +#define ATUIMR_PMA (1U << 5) +#define ATUIMR_PTAM (1U << 4) +#define ATUIMR_PTAT (1U << 3) +#define ATUIMR_PMPE (1U << 2) +#define ATUIMR_IE_SERR_EN (1U << 1) +#define ATUIMR_ECC_TAE (1U << 0) + +#define PCIXCMD_MOST_1 (0 << 4) +#define PCIXCMD_MOST_2 (1 << 4) +#define PCIXCMD_MOST_3 (2 << 4) +#define PCIXCMD_MOST_4 (3 << 4) +#define PCIXCMD_MOST_8 (4 << 4) +#define PCIXCMD_MOST_12 (5 << 4) +#define PCIXCMD_MOST_16 (6 << 4) +#define PCIXCMD_MOST_32 (7 << 4) +#define PCIXCMD_MOST_MASK (7 << 4) +#define PCIXCMD_MMRBC_512 (0 << 2) +#define PCIXCMD_MMRBC_1024 (1 << 2) +#define PCIXCMD_MMRBC_2048 (2 << 2) +#define PCIXCMD_MMRBC_4096 (3 << 2) +#define PCIXCMD_MMRBC_MASK (3 << 2) +#define PCIXCMD_ERO (1U << 1) +#define PCIXCMD_DPERE (1U << 0) + +#define PCIXSR_RSCEM (1U << 29) +#define PCIXSR_DMCRS_MASK (7 << 26) +#define PCIXSR_DMOST_MASK (7 << 23) +#define PCIXSR_COMPLEX (1U << 20) +#define PCIXSR_USC (1U << 19) +#define PCIXSR_SCD (1U << 18) +#define PCIXSR_133_CAP (1U << 17) +#define PCIXSR_32PCI (1U << 16) /* 0 = 32, 1 = 64 */ +#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8) +#define PCIXSR_DEVNO(x) (((x) & 0xf8) >> 3) +#define PCIXSR_FUNCNO(x) ((x) & 0x7) + +/* + * Memory Controller Unit + */ +#define MCU_SDIR 0x00 /* DDR SDRAM Init. Register */ +#define MCU_SDCR 0x04 /* DDR SDRAM Control Register */ +#define MCU_SDBR 0x08 /* SDRAM Base Register */ +#define MCU_SBR0 0x0c /* SDRAM Boundary 0 */ +#define MCU_SBR1 0x10 /* SDRAM Boundary 1 */ +#define MCU_ECCR 0x34 /* ECC Control Register */ +#define MCU_ELOG0 0x38 /* ECC Log 0 */ +#define MCU_ELOG1 0x3c /* ECC Log 1 */ +#define MCU_ECAR0 0x40 /* ECC address 0 */ +#define MCU_ECAR1 0x44 /* ECC address 1 */ +#define MCU_ECTST 0x48 /* ECC test register */ +#define MCU_MCISR 0x4c /* MCU Interrupt Status Register */ +#define MCU_RFR 0x50 /* Refresh Frequency Register */ +#define MCU_DBUDSR 0x54 /* Data Bus Pull-up Drive Strength */ +#define MCU_DBDDSR 0x58 /* Data Bus Pull-down Drive Strength */ +#define MCU_CUDSR 0x5c /* Clock Pull-up Drive Strength */ +#define MCU_CDDSR 0x60 /* Clock Pull-down Drive Strength */ +#define MCU_CEUDSR 0x64 /* Clock En Pull-up Drive Strength */ +#define MCU_CEDDSR 0x68 /* Clock En Pull-down Drive Strength */ +#define MCU_CSUDSR 0x6c /* Chip Sel Pull-up Drive Strength */ +#define MCU_CSDDSR 0x70 /* Chip Sel Pull-down Drive Strength */ +#define MCU_REUDSR 0x74 /* Rx En Pull-up Drive Strength */ +#define MCU_REDDSR 0x78 /* Rx En Pull-down Drive Strength */ +#define MCU_ABUDSR 0x7c /* Addr Bus Pull-up Drive Strength */ +#define MCU_ABDDSR 0x80 /* Addr Bus Pull-down Drive Strength */ +#define MCU_DSDR 0x84 /* Data Strobe Delay Register */ +#define MCU_REDR 0x88 /* Rx Enable Delay Register */ + +#define SDCR_DIMMTYPE (1U << 1) /* 0 = unbuf, 1 = reg */ +#define SDCR_BUSWIDTH (1U << 2) /* 0 = 64, 1 = 32 */ + +#define SBRx_TECH (1U << 31) +#define SBRx_BOUND 0x0000003f + +#define ECCR_SBERE (1U << 0) +#define ECCR_MBERE (1U << 1) +#define ECCR_SBECE (1U << 2) +#define ECCR_ECCEN (1U << 3) + +#define ELOGx_SYNDROME 0x000000ff +#define ELOGx_ERRTYPE (1U << 8) /* 1 = multi-bit */ +#define ELOGx_RW (1U << 12) /* 1 = write error */ + /* + * Dev ID Func Requester + * 2 0 XScale core + * 2 1 ATU + * 13 0 DMA channel 0 + * 13 1 DMA channel 1 + * 26 0 ATU + */ +#define ELOGx_REQ_DEV(x) (((x) >> 19) & 0x1f) +#define ELOGx_REQ_FUNC(x) (((x) >> 16) & 0x3) + +#define MCISR_ECC_ERR0 (1U << 0) +#define MCISR_ECC_ERR1 (1U << 1) +#define MCISR_ECC_ERRN (1U << 2) + +/* + * Timers + * + * The i80321 timer registers are available in both memory-mapped + * and coprocessor spaces. Most of the registers are read-only + * if memory-mapped, so we access them via coprocessor space. + * + * TMR0 cp6 c0,1 0xffffe7e0 + * TMR1 cp6 c1,1 0xffffe7e4 + * TCR0 cp6 c2,1 0xffffe7e8 + * TCR1 cp6 c3,1 0xffffe7ec + * TRR0 cp6 c4,1 0xffffe7f0 + * TRR1 cp6 c5,1 0xffffe7f4 + * TISR cp6 c6,1 0xffffe7f8 + * WDTCR cp6 c7,1 0xffffe7fc + */ + +#define TMRx_TC (1U << 0) +#define TMRx_ENABLE (1U << 1) +#define TMRx_RELOAD (1U << 2) +#define TMRx_CSEL_CORE (0 << 4) +#define TMRx_CSEL_CORE_div4 (1 << 4) +#define TMRx_CSEL_CORE_div8 (2 << 4) +#define TMRx_CSEL_CORE_div16 (3 << 4) + +#define TISR_TMR0 (1U << 0) +#define TISR_TMR1 (1U << 1) + +#define WDTCR_ENABLE1 0x1e1e1e1e +#define WDTCR_ENABLE2 0xe1e1e1e1 + +/* + * Interrupt Controller Unit. + * + * INTCTL cp6 c0,0 0xffffe7d0 + * INTSTR cp6 c4,0 0xffffe7d4 + * IINTSRC cp6 c8,0 0xffffe7d8 + * FINTSRC cp6 c9,0 0xffffe7dc + * PIRSR 0xffffe1ec + */ + +#define ICU_PIRSR 0x01ec +#define ICU_GPOE 0x07c4 +#define ICU_GPID 0x07c8 +#define ICU_GPOD 0x07cc + +/* + * NOTE: WE USE THE `bitXX' BITS TO INDICATE PENDING SOFTWARE + * INTERRUPTS. See i80321_icu.c + */ +#define ICU_INT_HPI 31 /* high priority interrupt */ +#define ICU_INT_XINT0 27 /* external interrupts */ +#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0) +#define ICU_INT_bit26 26 + +/* CPU_XSCALE_80321 */ +#define ICU_INT_SSP 25 /* SSP serial port */ + +#define ICU_INT_MUE 24 /* msg unit error */ + +/* CPU_XSCALE_80321 */ +#define ICU_INT_AAUE 23 /* AAU error */ + +#define ICU_INT_bit22 22 +#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ +#define ICU_INT_DMA0E 20 /* DMA Ch 0 error */ +#define ICU_INT_MCUE 19 /* memory controller error */ +#define ICU_INT_ATUE 18 /* ATU error */ +#define ICU_INT_BIUE 17 /* bus interface unit error */ +#define ICU_INT_PMU 16 /* XScale PMU */ +#define ICU_INT_PPM 15 /* peripheral PMU */ +#define ICU_INT_BIST 14 /* ATU Start BIST */ +#define ICU_INT_MU 13 /* messaging unit */ +#define ICU_INT_I2C1 12 /* i2c unit 1 */ +#define ICU_INT_I2C0 11 /* i2c unit 0 */ +#define ICU_INT_TMR1 10 /* timer 1 */ +#define ICU_INT_TMR0 9 /* timer 0 */ +#define ICU_INT_CPPM 8 /* core processor PMU */ + +/* CPU_XSCALE_80321 */ +#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ +#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ + +#define ICU_INT_bit5 5 +#define ICU_INT_bit4 4 +#define ICU_INT_DMA1_EOC 3 /* DMA1 end-of-chain */ +#define ICU_INT_DMA1_EOT 2 /* DMA1 end-of-transfer */ +#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */ +#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ + +/* CPU_XSCALE_80321 */ +#define ICU_INT_HWMASK (0xffffffff & \ + ~((1 << ICU_INT_bit26) | \ + (1 << ICU_INT_bit22) | \ + (1 << ICU_INT_bit5) | \ + (1 << ICU_INT_bit4))) + +/* + * Peripheral Bus Interface Unit + */ + +#define PBIU_PBCR 0x00 /* PBIU Control Register */ +#define PBIU_PBBAR0 0x08 /* PBIU Base Address Register 0 */ +#define PBIU_PBLR0 0x0c /* PBIU Limit Register 0 */ +#define PBIU_PBBAR1 0x10 /* PBIU Base Address Register 1 */ +#define PBIU_PBLR1 0x14 /* PBIU Limit Register 1 */ +#define PBIU_PBBAR2 0x18 /* PBIU Base Address Register 2 */ +#define PBIU_PBLR2 0x1c /* PBIU Limit Register 2 */ +#define PBIU_PBBAR3 0x20 /* PBIU Base Address Register 3 */ +#define PBIU_PBLR3 0x24 /* PBIU Limit Register 3 */ +#define PBIU_PBBAR4 0x28 /* PBIU Base Address Register 4 */ +#define PBIU_PBLR4 0x2c /* PBIU Limit Register 4 */ +#define PBIU_PBBAR5 0x30 /* PBIU Base Address Register 5 */ +#define PBIU_PBLR5 0x34 /* PBIU Limit Register 5 */ +#define PBIU_DSCR 0x38 /* PBIU Drive Strength Control Reg. */ +#define PBIU_MBR0 0x40 /* PBIU Memory-less Boot Reg. 0 */ +#define PBIU_MBR1 0x60 /* PBIU Memory-less Boot Reg. 1 */ +#define PBIU_MBR2 0x64 /* PBIU Memory-less Boot Reg. 2 */ + +#define PBIU_PBCR_PBIEN (1 << 0) +#define PBIU_PBCR_PBI100 (1 << 1) +#define PBIU_PBCR_PBI66 (2 << 1) +#define PBIU_PBCR_PBI33 (3 << 1) +#define PBIU_PBCR_PBBEN (1 << 3) + +#define PBIU_PBARx_WIDTH8 (0 << 0) +#define PBIU_PBARx_WIDTH16 (1 << 0) +#define PBIU_PBARx_WIDTH32 (2 << 0) +#define PBIU_PBARx_ADWAIT4 (0 << 2) +#define PBIU_PBARx_ADWAIT8 (1 << 2) +#define PBIU_PBARx_ADWAIT12 (2 << 2) +#define PBIU_PBARx_ADWAIT16 (3 << 2) +#define PBIU_PBARx_ADWAIT20 (4 << 2) +#define PBIU_PBARx_RCWAIT1 (0 << 6) +#define PBIU_PBARx_RCWAIT4 (1 << 6) +#define PBIU_PBARx_RCWAIT8 (2 << 6) +#define PBIU_PBARx_RCWAIT12 (3 << 6) +#define PBIU_PBARx_RCWAIT16 (4 << 6) +#define PBIU_PBARx_RCWAIT20 (5 << 6) +#define PBIU_PBARx_FWE (1 << 9) +#define PBIU_BASE_MASK 0xfffff000U + +#define PBIU_PBLRx_SIZE(x) (~((x) - 1)) + +/* + * Messaging Unit + */ +#define MU_IMR0 0x0010 /* MU Inbound Message Register 0 */ +#define MU_IMR1 0x0014 /* MU Inbound Message Register 1 */ +#define MU_OMR0 0x0018 /* MU Outbound Message Register 0 */ +#define MU_OMR1 0x001c /* MU Outbound Message Register 1 */ +#define MU_IDR 0x0020 /* MU Inbound Doorbell Register */ +#define MU_IISR 0x0024 /* MU Inbound Interrupt Status Reg */ +#define MU_IIMR 0x0028 /* MU Inbound Interrupt Mask Reg */ +#define MU_ODR 0x002c /* MU Outbound Doorbell Register */ +#define MU_OISR 0x0030 /* MU Outbound Interrupt Status Reg */ +#define MU_OIMR 0x0034 /* MU Outbound Interrupt Mask Reg */ +#define MU_MUCR 0x0050 /* MU Configuration Register */ +#define MU_QBAR 0x0054 /* MU Queue Base Address Register */ +#define MU_IFHPR 0x0060 /* MU Inbound Free Head Pointer Reg */ +#define MU_IFTPR 0x0064 /* MU Inbound Free Tail Pointer Reg */ +#define MU_IPHPR 0x0068 /* MU Inbound Post Head Pointer Reg */ +#define MU_IPTPR 0x006c /* MU Inbound Post Tail Pointer Reg */ +#define MU_OFHPR 0x0070 /* MU Outbound Free Head Pointer Reg */ +#define MU_OFTPR 0x0074 /* MU Outbound Free Tail Pointer Reg */ +#define MU_OPHPR 0x0078 /* MU Outbound Post Head Pointer Reg */ +#define MU_OPTPR 0x007c /* MU Outbound Post Tail Pointer Reg */ +#define MU_IAR 0x0080 /* MU Index Address Register */ + +#define MU_IIMR_IRI (1 << 6) /* Index Register Interrupt */ +#define MU_IIMR_OFQFI (1 << 5) /* Outbound Free Queue Full Int. */ +#define MU_IIMR_IPQI (1 << 4) /* Inbound Post Queue Interrupt */ +#define MU_IIMR_EDI (1 << 3) /* Error Doorbell Interrupt */ +#define MU_IIMR_IDI (1 << 2) /* Inbound Doorbell Interrupt */ +#define MU_IIMR_IM1I (1 << 1) /* Inbound Message 1 Interrupt */ +#define MU_IIMR_IM0I (1 << 0) /* Inbound Message 0 Interrupt */ + +#endif /* _ARM_XSCALE_I80321REG_H_ */ diff --git a/sys/arm/xscale/i8134x/i80321var.h b/sys/arm/xscale/i8134x/i80321var.h new file mode 100644 index 000000000000..0fead2577a2e --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321var.h @@ -0,0 +1,137 @@ +/* $NetBSD: i80321var.h,v 1.8 2003/10/06 16:06:06 thorpej Exp $ */ + +/*- + * Copyright (c) 2002, 2003 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. + * + * $FreeBSD$ + * + */ + +#ifndef _ARM_XSCALE_I80321VAR_H_ +#define _ARM_XSCALE_I80321VAR_H_ + +#include <sys/queue.h> +#include <dev/pci/pcivar.h> +#include <sys/rman.h> + +extern struct bus_space i80321_bs_tag; + +struct i80321_softc { + device_t dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + /* Handles for the various subregions. */ + bus_space_handle_t sc_atu_sh; + bus_space_handle_t sc_mcu_sh; + int sc_is_host; + + /* + * We expect the board-specific front-end to have already mapped + * the PCI I/O space .. it is only 64K, and I/O mappings tend to + * be smaller than a page size, so it's generally more efficient + * to map them all into virtual space in one fell swoop. + */ + vm_offset_t sc_iow_vaddr; /* I/O window vaddr */ + + /* + * Variables that define the Inbound windows. The base address of + * 0-2 are configured by a host via BARs. The xlate variable + * defines the start of the local address space that it maps to. + * The size variable defines the byte size. + * + * The first 3 windows are for incoming PCI memory read/write + * cycles from a host. The 4th window, not configured by the + * host (as it outside the normal BAR range) is the inbound + * window for PCI devices controlled by the i80321. + */ + struct { + uint32_t iwin_base_hi; + uint32_t iwin_base_lo; + uint32_t iwin_xlate; + uint32_t iwin_size; + } sc_iwin[4]; + + /* + * Variables that define the Outbound windows. + */ + struct { + uint32_t owin_xlate_lo; + uint32_t owin_xlate_hi; + } sc_owin[2]; + + /* + * This is the PCI address that the Outbound I/O + * window maps to. + */ + uint32_t sc_ioout_xlate; + + /* Bus space, DMA, and PCI tags for the PCI bus (private devices). */ + struct bus_space sc_pci_iot; + struct bus_space sc_pci_memt; + + /* GPIO state */ + uint8_t sc_gpio_dir; /* GPIO pin direction (1 == output) */ + uint8_t sc_gpio_val; /* GPIO output pin value */ + struct rman sc_irq_rman; + +}; + + +struct i80321_pci_softc { + device_t sc_dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_atu_sh; + bus_space_tag_t sc_pciio; + bus_space_tag_t sc_pcimem; + int sc_busno; + struct rman sc_mem_rman; + struct rman sc_io_rman; + struct rman sc_irq_rman; + uint32_t sc_mem; + uint32_t sc_io; +}; + +void i80321_sdram_bounds(bus_space_tag_t, bus_space_handle_t, + vm_paddr_t *, vm_size_t *); + +void i80321_attach(struct i80321_softc *); +void i80321_calibrate_delay(void); + +void i80321_bs_init(bus_space_tag_t, void *); +void i80321_io_bs_init(bus_space_tag_t, void *); +void i80321_mem_bs_init(bus_space_tag_t, void *); +extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin); + + +#endif /* _ARM_XSCALE_I80321VAR_H_ */ diff --git a/sys/arm/xscale/i8134x/i81342.c b/sys/arm/xscale/i8134x/i81342.c new file mode 100644 index 000000000000..ace6004cf9c0 --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342.c @@ -0,0 +1,468 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#define _ARM32_BUS_DMA_PRIVATE +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/i81342var.h> + +#define WDTCR_ENABLE1 0x1e1e1e1e +#define WDTCR_ENABLE2 0xe1e1e1e1 + +static volatile int intr_enabled0; +static volatile int intr_enabled1; +static volatile int intr_enabled2; +static volatile int intr_enabled3; + +struct bus_space i81342_bs_tag; + +/* Read the interrupt pending register */ + +static __inline +uint32_t intpnd0_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c0, c3, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intpnd1_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c1, c3, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intpnd2_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c2, c3, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intpnd3_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c3, c3, 0" + : "=r" (ret)); + return (ret); +} + +/* Read the interrupt control register */ +/* 0 masked, 1 unmasked */ +static __inline +uint32_t intctl0_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c0, c4, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intctl1_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c1, c4, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intctl2_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c2, c4, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intctl3_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c3, c4, 0" + : "=r" (ret)); + return (ret); +} + +/* Write the interrupt control register */ + +static __inline +void intctl0_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c0, c4, 0" + : : "r" (val)); +} + +static __inline +void intctl1_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c1, c4, 0" + : : "r" (val)); +} + +static __inline +void intctl2_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c2, c4, 0" + : : "r" (val)); +} + +static __inline +void intctl3_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c3, c4, 0" + : : "r" (val)); +} + +/* Read the interrupt steering register */ +/* 0 IRQ 1 FIQ */ +static __inline +uint32_t intstr0_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c0, c5, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intstr1_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c1, c5, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intstr2_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c2, c5, 0" + : "=r" (ret)); + return (ret); +} + +static __inline +uint32_t intstr3_read(void) +{ + uint32_t ret; + + __asm __volatile("mrc p6, 0, %0, c3, c5, 0" + : "=r" (ret)); + return (ret); +} + +/* Write the interrupt steering register */ + +static __inline +void intstr0_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c0, c5, 0" + : : "r" (val)); +} + +static __inline +void intstr1_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c1, c5, 0" + : : "r" (val)); +} + +static __inline +void intstr2_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c2, c5, 0" + : : "r" (val)); +} + +static __inline +void intstr3_write(uint32_t val) +{ + + __asm __volatile("mcr p6, 0, %0, c3, c5, 0" + : : "r" (val)); +} + +void +cpu_reset(void) +{ + + disable_interrupts(PSR_I); + /* XXX: Use the watchdog to reset for now */ + __asm __volatile("mcr p6, 0, %0, c8, c9, 0\n" + "mcr p6, 0, %1, c7, c9, 0\n" + "mcr p6, 0, %2, c7, c9, 0\n" + : : "r" (1), "r" (WDTCR_ENABLE1), "r" (WDTCR_ENABLE2)); + while (1); +} + +void +arm_mask_irq(uintptr_t nb) +{ + + if (nb < 32) { + intr_enabled0 &= ~(1 << nb); + intctl0_write(intr_enabled0); + } else if (nb < 64) { + intr_enabled1 &= ~(1 << (nb - 32)); + intctl1_write(intr_enabled1); + } else if (nb < 96) { + intr_enabled2 &= ~(1 << (nb - 64)); + intctl2_write(intr_enabled2); + } else { + intr_enabled3 &= ~(1 << (nb - 96)); + intctl3_write(intr_enabled3); + } +} + +void +arm_unmask_irq(uintptr_t nb) +{ + if (nb < 32) { + intr_enabled0 |= (1 << nb); + intctl0_write(intr_enabled0); + } else if (nb < 64) { + intr_enabled1 |= (1 << (nb - 32)); + intctl1_write(intr_enabled1); + } else if (nb < 96) { + intr_enabled2 |= (1 << (nb - 64)); + intctl2_write(intr_enabled2); + } else { + intr_enabled3 |= (1 << (nb - 96)); + intctl3_write(intr_enabled3); + } +} + +int +arm_get_next_irq(int last __unused) +{ + uint32_t val; + val = intpnd0_read() & intr_enabled0; + if (val) + return (ffs(val) - 1); + val = intpnd1_read() & intr_enabled1; + if (val) + return (32 + ffs(val) - 1); + val = intpnd2_read() & intr_enabled2; + if (val) + return (64 + ffs(val) - 1); + val = intpnd3_read() & intr_enabled3; + if (val) + return (96 + ffs(val) - 1); + return (-1); +} + +int +bus_dma_get_range_nb(void) +{ + return (0); +} + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + return (NULL); +} + +static int +i81342_probe(device_t dev) +{ + unsigned int freq; + + freq = *(volatile unsigned int *)(IOP34X_VADDR + IOP34X_PFR); + + switch (freq & IOP34X_FREQ_MASK) { + case IOP34X_FREQ_600: + device_set_desc(dev, "Intel 81342 600MHz"); + break; + case IOP34X_FREQ_667: + device_set_desc(dev, "Intel 81342 667MHz"); + break; + case IOP34X_FREQ_800: + device_set_desc(dev, "Intel 81342 800MHz"); + break; + case IOP34X_FREQ_833: + device_set_desc(dev, "Intel 81342 833MHz"); + break; + case IOP34X_FREQ_1000: + device_set_desc(dev, "Intel 81342 1000MHz"); + break; + case IOP34X_FREQ_1200: + device_set_desc(dev, "Intel 81342 1200MHz"); + break; + default: + device_set_desc(dev, "Intel 81342 unknown frequency"); + break; + } + return (0); +} + +static void +i81342_identify(driver_t *driver, device_t parent) +{ + + BUS_ADD_CHILD(parent, 0, "iq", 0); +} + +static int +i81342_attach(device_t dev) +{ + struct i81342_softc *sc = device_get_softc(dev); + uint32_t esstrsr; + + i81342_bs_init(&i81342_bs_tag, sc); + sc->sc_st = &i81342_bs_tag; + sc->sc_sh = IOP34X_VADDR; + esstrsr = bus_space_read_4(sc->sc_st, sc->sc_sh, IOP34X_ESSTSR0); + sc->sc_atux_sh = IOP34X_ATUX_ADDR(esstrsr) - IOP34X_HWADDR + + IOP34X_VADDR; + sc->sc_atue_sh = IOP34X_ATUE_ADDR(esstrsr) - IOP34X_HWADDR + + IOP34X_VADDR; + /* Disable all interrupts. */ + intctl0_write(0); + intctl1_write(0); + intctl2_write(0); + intctl3_write(0); + /* Defaults to IRQ */ + intstr0_write(0); + intstr1_write(0); + intstr2_write(0); + intstr3_write(0); + sc->sc_irq_rman.rm_type = RMAN_ARRAY; + sc->sc_irq_rman.rm_descr = "i81342 IRQs"; + if (rman_init(&sc->sc_irq_rman) != 0 || + rman_manage_region(&sc->sc_irq_rman, 0, 127) != 0) + panic("i81342_attach: failed to set up IRQ rman"); + + device_add_child(dev, "obio", 0); + device_add_child(dev, "itimer", 0); + device_add_child(dev, "iopwdog", 0); + device_add_child(dev, "pcib", 0); + device_add_child(dev, "pcib", 1); + device_add_child(dev, "iqseg", 0); + bus_generic_probe(dev); + bus_generic_attach(dev); + return (0); +} + +static struct resource * +i81342_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct i81342_softc *sc = device_get_softc(dev); + struct resource *rv; + + if (type == SYS_RES_IRQ) { + rv = rman_reserve_resource(&sc->sc_irq_rman, + start, end, count, flags, child); + if (rv != NULL) + rman_set_rid(rv, *rid); + return (rv); + } + + return (NULL); +} + +static int +i81342_setup_intr(device_t dev, device_t child, struct resource *ires, + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, + void **cookiep) +{ + int error; + + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, + filt, intr, arg, cookiep); + if (error) + return (error); + return (0); +} + +static int +i81342_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); +} + +static device_method_t i81342_methods[] = { + DEVMETHOD(device_probe, i81342_probe), + DEVMETHOD(device_attach, i81342_attach), + DEVMETHOD(device_identify, i81342_identify), + DEVMETHOD(bus_alloc_resource, i81342_alloc_resource), + DEVMETHOD(bus_setup_intr, i81342_setup_intr), + DEVMETHOD(bus_teardown_intr, i81342_teardown_intr), + {0, 0}, +}; + +static driver_t i81342_driver = { + "iq", + i81342_methods, + sizeof(struct i81342_softc), +}; +static devclass_t i81342_devclass; + +DRIVER_MODULE(iq, nexus, i81342_driver, i81342_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/i81342_mcu.c b/sys/arm/xscale/i8134x/i81342_mcu.c new file mode 100644 index 000000000000..a144774233ff --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342_mcu.c @@ -0,0 +1,58 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/i81342var.h> + +void +i81342_sdram_bounds(bus_space_tag_t bt, bus_space_handle_t bh, + vm_paddr_t *start, vm_size_t *size) +{ + uint32_t reg; + int bank_nb; + + reg = bus_space_read_4(bt, bh, SMC_SDBR); + *start = (reg & SMC_SDBR_BASEADDR_MASK); + reg = bus_space_read_4(bt, bh, SMC_SBSR); + if (reg & SMC_SBSR_BANK_NB) + bank_nb = 1; + else + bank_nb = 2; + + *size = (reg & SMC_SBSR_BANK_SZ_MASK) * bank_nb; +} diff --git a/sys/arm/xscale/i8134x/i81342_pci.c b/sys/arm/xscale/i8134x/i81342_pci.c new file mode 100644 index 000000000000..fc348ef1da67 --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342_pci.c @@ -0,0 +1,547 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/types.h> +#include <sys/rman.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/pcb.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/i81342var.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcib_private.h> +#include "pcib_if.h" + +#include <dev/pci/pcireg.h> + +static pcib_read_config_t i81342_pci_read_config; +static pcib_write_config_t i81342_pci_write_config; + +static int +i81342_pci_probe(device_t dev) +{ + struct i81342_pci_softc *sc; + + sc = device_get_softc(dev); + if (device_get_unit(dev) == 0) { + device_set_desc(dev, "i81342 PCI-X bus"); + sc->sc_is_atux = 1; + } else { + device_set_desc(dev, "i81342 PCIe bus"); + sc->sc_is_atux = 0; + } + return (0); +} + +#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008 +#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004 + +static int +i81342_pci_attach(device_t dev) +{ + struct i81342_softc *parent_sc; + struct i81342_pci_softc *sc; + uint32_t memsize, memstart; + uint32_t reg; + int func; + uint32_t busno; + + sc = device_get_softc(dev); + parent_sc = device_get_softc(device_get_parent(dev)); + sc->sc_atu_sh = sc->sc_is_atux ? parent_sc->sc_atux_sh : + parent_sc->sc_atue_sh; + sc->sc_st = parent_sc->sc_st; + if (bus_space_read_4(sc->sc_st, parent_sc->sc_sh, IOP34X_ESSTSR0) + & IOP34X_INT_SEL_PCIX) { + if (sc->sc_is_atux) + func = 5; + else + func = 0; + } else { + if (sc->sc_is_atux) + func = 0; + else + func = 5; + } + i81342_io_bs_init(&sc->sc_pciio, sc); + i81342_mem_bs_init(&sc->sc_pcimem, sc); + i81342_sdram_bounds(sc->sc_st, IOP34X_VADDR, &memstart, &memsize); + if (sc->sc_is_atux) { + reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR); + if (reg & ATUX_P_RSTOUT) { + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR, + reg &~ ATUX_P_RSTOUT); + DELAY(200); + } + } + /* Setup the Inbound windows. */ + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR0, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR0, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 0); + + /* Set the mapping Physical address <=> PCI address */ + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR1, + memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK | + PCI_MAPREG_MEM_TYPE_64BIT); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR1, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, + rounddown2(~(0xfff), memsize)); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR1, memstart); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUTVR1, 0); + + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR2, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR2, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 0); + + /* Setup the Outbound IO Bar */ + if (sc->sc_is_atux) + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR, + (IOP34X_PCIX_OIOBAR >> 4) | func); + else + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR, + (IOP34X_PCIE_OIOBAR >> 4) | func); + + /* Setup the Outbound windows */ + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR0, 0); + if (sc->sc_is_atux) + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1, + (IOP34X_PCIX_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) | + ATU_OUMBAR_EN); + else + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1, + (IOP34X_PCIE_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) | + ATU_OUMBAR_EN); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR2, 0); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR3, 0); + + /* Enable the outbound windows. */ + reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_CR); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_CR, + reg | ATU_CR_OUT_EN); + + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, + bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK); + /* + * Enable bus mastering, memory access, SERR, and parity + * checking on the ATU. + */ + if (sc->sc_is_atux) { + busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); + busno = PCIXSR_BUSNO(busno); + } else { + busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR); + busno = PCIE_BUSNO(busno); + } + reg = bus_space_read_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD); + reg |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | + PCIM_CMD_SERRESPEN; + bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD, reg); + sc->sc_busno = busno; + /* Initialize memory and i/o rmans. */ + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "I81342 PCI I/O Ports"; + if (rman_init(&sc->sc_io_rman) != 0 || + rman_manage_region(&sc->sc_io_rman, + sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR : + IOP34X_PCIE_OIOBAR_VADDR, + (sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR : + IOP34X_PCIE_OIOBAR_VADDR) + IOP34X_OIOBAR_SIZE) != 0) { + panic("i81342_pci_probe: failed to set up I/O rman"); + } + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "I81342 PCI Memory"; + if (rman_init(&sc->sc_mem_rman) != 0 || + rman_manage_region(&sc->sc_mem_rman, + 0, 0xffffffff) != 0) { + panic("i81342_pci_attach: failed to set up memory rman"); + } + sc->sc_irq_rman.rm_type = RMAN_ARRAY; + sc->sc_irq_rman.rm_descr = "i81342 PCI IRQs"; + if (sc->sc_is_atux) { + if (rman_init(&sc->sc_irq_rman) != 0 || + rman_manage_region(&sc->sc_irq_rman, ICU_INT_XINT0, + ICU_INT_XINT3) != 0) + panic("i83142_pci_attach: failed to set up IRQ rman"); + } else { + if (rman_init(&sc->sc_irq_rman) != 0 || + rman_manage_region(&sc->sc_irq_rman, ICU_INT_ATUE_MA, + ICU_INT_ATUE_MD) != 0) + panic("i81342_pci_attach: failed to set up IRQ rman"); + + } + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, + bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK); + device_add_child(dev, "pci", -1); + return (bus_generic_attach(dev)); +} + +static int +i81342_pci_maxslots(device_t dev) +{ + + return (PCI_SLOTMAX); +} + +static void +i81342_pci_conf_setup(struct i81342_pci_softc *sc, int bus, int slot, int func, + int reg, uint32_t *addr) +{ + uint32_t busno; + + if (sc->sc_is_atux) { + busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); + busno = PCIXSR_BUSNO(busno); + } else { + busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR); + busno = PCIE_BUSNO(busno); + } + bus &= 0xff; + slot &= 0x1f; + func &= 0x7; + if (sc->sc_is_atux) { + if (busno == bus) + *addr = (1 << (slot + 16)) | (slot << 11) | + (func << 8) | reg; + else + *addr = (bus << 16) | (slot << 11) | (func << 11) | + reg | 1; + } else { + *addr = (bus << 24) | (slot << 19) | (func << 16) | reg; + if (bus != busno) + *addr |= 1; + } +} + +static u_int32_t +i81342_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + struct i81342_pci_softc *sc = device_get_softc(dev); + uint32_t addr; + uint32_t ret = 0; + uint32_t isr; + int err = 0; + vm_offset_t va; + + i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ? + ATUX_OCCAR : ATUE_OCCAR, addr); + if (sc->sc_is_atux) + va = sc->sc_atu_sh + ATUX_OCCDR; + else + va = sc->sc_atu_sh + ATUE_OCCDR; + switch (bytes) { + case 1: + err = badaddr_read((void*)(va + (reg & 3)), 1, &ret); + break; + case 2: + err = badaddr_read((void*)(va + (reg & 3)), 2, &ret); + break; + case 4: + err = badaddr_read((void *)(va) , 4, &ret); + break; + default: + printf("i81342_read_config: invalid size %d\n", bytes); + ret = -1; + } + if (err) { + isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR); + if (sc->sc_is_atux) + isr &= ATUX_ISR_ERRMSK; + else + isr &= ATUE_ISR_ERRMSK; + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, isr); + ret = -1; + } + + return (ret); +} + +static void +i81342_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, u_int32_t data, int bytes) +{ + struct i81342_pci_softc *sc = device_get_softc(dev); + uint32_t addr; + vm_offset_t va; + + i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr); + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ? + ATUX_OCCAR : ATUE_OCCAR, addr); + va = sc->sc_is_atux ? ATUX_OCCDR : ATUE_OCCDR; + switch (bytes) { + case 1: + bus_space_write_1(sc->sc_st, sc->sc_atu_sh, va + (reg & 3) + , data); + break; + case 2: + bus_space_write_2(sc->sc_st, sc->sc_atu_sh, va + (reg & 3) + , data); + break; + case 4: + bus_space_write_4(sc->sc_st, sc->sc_atu_sh, va, data); + break; + default: + printf("i81342_pci_write_config: Invalid size : %d\n", bytes); + } + + +} + +static struct resource * +i81342_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct i81342_pci_softc *sc = device_get_softc(bus); + struct resource *rv; + struct rman *rm; + bus_space_tag_t bt = NULL; + bus_space_handle_t bh = 0; + + switch (type) { + case SYS_RES_IRQ: + rm = &sc->sc_irq_rman; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + bt = &sc->sc_pcimem; + bh = 0; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + bt = &sc->sc_pciio; + bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR : + IOP34X_PCIE_OIOBAR_VADDR; + start += bh; + end += bh; + break; + default: + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) + return (NULL); + rman_set_rid(rv, *rid); + if (type != SYS_RES_IRQ) { + if (type == SYS_RES_MEMORY) + bh += (rman_get_start(rv)); + rman_set_bustag(rv, bt); + rman_set_bushandle(rv, bh); + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + } + return (rv); + + + return (NULL); +} + +static int +i81342_pci_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + bus_space_handle_t p; + int error; + + if (type == SYS_RES_MEMORY) { + error = bus_space_map(rman_get_bustag(r), + rman_get_bushandle(r), rman_get_size(r), 0, &p); + if (error) + return (error); + rman_set_bushandle(r, p); + + } + return (rman_activate_resource(r)); +} + +static int +i81342_pci_setup_intr(device_t dev, device_t child, struct resource *ires, + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, + void **cookiep) +{ + + return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, + filt, intr, arg, cookiep)); +} + + + +static int +i81342_pci_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); +} + +static int +i81342_pci_route_interrupt(device_t pcib, device_t dev, int pin) +{ + struct i81342_pci_softc *sc; + int device; + + device = pci_get_slot(dev); + sc = device_get_softc(pcib); + /* XXX: Is board specific */ + if (sc->sc_is_atux) { + /* PCI-X */ + switch(device) { + case 1: + switch (pin) { + case 1: + return (ICU_INT_XINT1); + case 2: + return (ICU_INT_XINT2); + case 3: + return (ICU_INT_XINT3); + case 4: + return (ICU_INT_XINT0); + default: + break; + } + case 2: + switch (pin) { + case 1: + return (ICU_INT_XINT2); + case 2: + return (ICU_INT_XINT3); + case 3: + return (ICU_INT_XINT2); + case 4: + return (ICU_INT_XINT3); + default: + break; + } + } + + } else { + switch (pin) { + case 1: + return (ICU_INT_ATUE_MA); + case 2: + return (ICU_INT_ATUE_MB); + case 3: + return (ICU_INT_ATUE_MC); + case 4: + return (ICU_INT_ATUE_MD); + default: + break; + } + } + printf("Warning: couldn't map %s IRQ for device %d pin %d\n", + sc->sc_is_atux ? "PCI-X" : "PCIe", device, pin); + return (-1); +} + +static int +i81342_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct i81342_pci_softc *sc = device_get_softc(dev); + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = 0; + return (0); + case PCIB_IVAR_BUS: + *result = sc->sc_busno; + return (0); + + } + return (ENOENT); +} + +static int +i81342_write_ivar(device_t dev, device_t child, int which, uintptr_t result) +{ + struct i81342_pci_softc * sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + return (EINVAL); + case PCIB_IVAR_BUS: + sc->sc_busno = result; + return (0); + } + return (ENOENT); +} + +static device_method_t i81342_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, i81342_pci_probe), + DEVMETHOD(device_attach, i81342_pci_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_read_ivar, i81342_read_ivar), + DEVMETHOD(bus_write_ivar, i81342_write_ivar), + DEVMETHOD(bus_alloc_resource, i81342_pci_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, i81342_pci_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, i81342_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, i81342_pci_teardown_intr), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, i81342_pci_maxslots), + DEVMETHOD(pcib_read_config, i81342_pci_read_config), + DEVMETHOD(pcib_write_config, i81342_pci_write_config), + DEVMETHOD(pcib_route_interrupt, i81342_pci_route_interrupt), + DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), + + DEVMETHOD_END +}; + +static driver_t i81342_pci_driver = { + "pcib", + i81342_pci_methods, + sizeof(struct i81342_pci_softc), +}; + +static devclass_t i81342_pci_devclass; + +DRIVER_MODULE(ipci, iq, i81342_pci_driver, i81342_pci_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/i81342_space.c b/sys/arm/xscale/i8134x/i81342_space.c new file mode 100644 index 000000000000..ed27675e4a0f --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342_space.c @@ -0,0 +1,234 @@ +/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * bus_space functions for i81342 I/O Processor. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <machine/pcb.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/pmap.h> +#include <vm/vm_page.h> +#include <vm/vm_extern.h> + +#include <machine/bus.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/i81342var.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(i81342); +bs_protos(i81342_io); +bs_protos(i81342_mem); + +void +i81342_bs_init(bus_space_tag_t bs, void *cookie) +{ + + *bs = *arm_base_bs_tag; + bs->bs_privdata = cookie; +} + +void +i81342_io_bs_init(bus_space_tag_t bs, void *cookie) +{ + + *bs = *arm_base_bs_tag; + bs->bs_privdata = cookie; + + bs->bs_map = i81342_io_bs_map; + bs->bs_unmap = i81342_io_bs_unmap; + bs->bs_alloc = i81342_io_bs_alloc; + bs->bs_free = i81342_io_bs_free; + +} + +void +i81342_mem_bs_init(bus_space_tag_t bs, void *cookie) +{ + + *bs = *arm_base_bs_tag; + bs->bs_privdata = cookie; + + bs->bs_map = i81342_mem_bs_map; + bs->bs_unmap = i81342_mem_bs_unmap; + bs->bs_alloc = i81342_mem_bs_alloc; + bs->bs_free = i81342_mem_bs_free; + +} + +/* *** Routines shared by i81342, PCI IO, and PCI MEM. *** */ + +int +i81342_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + + *nbshp = bsh + offset; + return (0); +} + +void +i81342_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t len, int flags) +{ + + /* Nothing to do. */ +} + +/* *** Routines for PCI IO. *** */ + +int +i81342_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + + *bshp = bpa; + return (0); +} + +void +i81342_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) +{ + + /* Nothing to do. */ +} + +int +i81342_io_bs_alloc(bus_space_tag_t tag, 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("i81342_io_bs_alloc(): not implemented"); +} + +void +i81342_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("i81342_io_bs_free(): not implemented"); +} + + +/* *** Routines for PCI MEM. *** */ +extern int badaddr_read(void *, int, void *); +static vm_offset_t allocable = 0xe1000000; +int +i81342_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + struct i81342_pci_softc *sc = (struct i81342_pci_softc *)tag->bs_privdata; + struct i81342_pci_map *tmp; + vm_offset_t addr, endaddr; + vm_paddr_t paddr; + + /* Lookup to see if we already have a mapping at this address. */ + tmp = sc->sc_pci_mappings; + while (tmp) { + if (tmp->paddr <= bpa && tmp->paddr + tmp->size > + bpa + size) { + *bshp = bpa - tmp->paddr + tmp->vaddr; + return (0); + } + tmp = tmp->next; + } + addr = allocable; + endaddr = rounddown2(addr + size, 0x1000000) + 0x1000000; + if (endaddr >= IOP34X_VADDR) + panic("PCI virtual memory exhausted"); + allocable = endaddr; + tmp = malloc(sizeof(*tmp), M_DEVBUF, M_WAITOK); + tmp->next = NULL; + paddr = rounddown2(bpa, 0x100000); + tmp->paddr = paddr; + tmp->vaddr = addr; + tmp->size = 0; + while (addr < endaddr) { + pmap_kenter_supersection(addr, paddr + (sc->sc_is_atux ? + IOP34X_PCIX_OMBAR : IOP34X_PCIE_OMBAR), 0); + addr += 0x1000000; + paddr += 0x1000000; + tmp->size += 0x1000000; + } + tmp->next = sc->sc_pci_mappings; + sc->sc_pci_mappings = tmp; + *bshp = bpa - tmp->paddr + tmp->vaddr; + return (0); +} + +void +i81342_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) +{ +#if 0 + vm_offset_t va, endva; + + va = trunc_page((vm_offset_t)h); + endva = va + round_page(size); + + /* Free the kernel virtual mapping. */ + kva_free(va, endva - va); +#endif +} + +int +i81342_mem_bs_alloc(bus_space_tag_t tag, 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("i81342_mem_bs_alloc(): not implemented"); +} + +void +i81342_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("i81342_mem_bs_free(): not implemented"); +} diff --git a/sys/arm/xscale/i8134x/i81342reg.h b/sys/arm/xscale/i8134x/i81342reg.h new file mode 100644 index 000000000000..07bec22ef89c --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342reg.h @@ -0,0 +1,350 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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. + */ + +/* $FreeBSD$ */ + +#ifndef I83142_REG_H_ +#define I83142_REG_H_ +/* Physical Memory Map */ +/* + * 0x000000000 - 0x07FFFFFFF SDRAM + * 0x090100000 - 0x0901FFFFF ATUe Outbound IO Window + * 0x0F0000000 - 0x0F1FFFFFF Flash + * 0x0F2000000 - 0x0F20FFFFF PCE1 + * 0x0F3000000 - 0x0FFCFFFFF Compact Flash + * 0x0FFD00000 - 0x0FFDFFFFF MMR + * 0x0FFFB0000 - 0x0FFFBFFFF ATU-X Outbound I/O Window + * 0x0FFFD0000 - 0x0FFFDFFFF ATUe Outbound I/O Window + * 0x100000000 - 0x1FFFFFFFF ATU-X outbound Memory Translation Window + * 0x2FF000000 - 0x2FFFFFFFF ATUe Outbound Memory Translation Window + */ + +#define IOP34X_VADDR 0xf0000000 +#define IOP34X_HWADDR 0xffd00000 +#define IOP34X_SIZE 0x100000 + +#define IOP34X_ADMA0_OFFSET 0x00080000 +#define IOP34X_ADMA1_OFFSET 0x00080200 +#define IOP34X_ADMA2_OFFSET 0x00080400 +#define IOP34X_ADMA_SIZE 0x200 + + +/* ADMA Registers */ +#define IOP34X_ADMA_CCR 0x0000 /* Channel Control Register */ +#define IOP34X_ADMA_CSR 0x0004 /* Channel Status Register */ +#define IOP34X_ADMA_DAR 0x0008 /* Descriptor Address Register */ +#define IOP34X_ADMA_IPCR 0x0018 /* Internal Interface Parity Ctrl Reg */ +#define IOP34X_ADMA_NDAR 0x0024 /* Next Descriptor Register */ +#define IOP34X_ADMA_DCR 0x0028 /* Descriptor Control Register */ + +#define IOP34X_ADMA_IE (1 << 0) /* Interrupt enable */ +#define IOP34X_ADMA_TR (1 << 1) /* Transfert Direction */ +/* + * Source Destination + * 00 Host I/O Interface Local Memory + * 01 Local Memory Host I/O Interface + * 10 Internal Bus Local Memory + * 11 Local Memory Internal Bus + */ +#define IOP34X_ADMA_SS (1 << 3) /* Source selection */ +/* 0000: Data Transfer / CRC / Memory Block Fill */ +#define IOP34X_ADMA_ZRBCE (1 << 7) /* Zero Result Buffer Check Enable */ +#define IOP34X_ADMA_MBFE (1 << 8) /* Memory Block Fill Enable */ +#define IOP34X_ADMA_CGE (1 << 9) /* CRC Generation enable */ +#define IOP34X_ADMA_CTD (1 << 10) /* CRC Transfer disable */ +#define IOP34X_ADMA_CSFD (1 << 11) /* CRC Seed fetch disable */ +#define IOP34X_ADMA_SWBE (1 << 12) /* Status write back enable */ +#define IOP34X_ADMA_ESE (1 << 13) /* Endian swap enable */ +#define IOP34X_ADMA_PQUTE (1 << 16) /* P+Q Update Transfer Enable */ +#define IOP34X_ADMA_DXE (1 << 17) /* Dual XOR Enable */ +#define IOP34X_ADMA_PQTE (1 << 18) /* P+Q Transfer Enable */ +#define IOP34X_ADMA_PTD (1 << 19) /* P Transfer Disable */ +#define IOP34X_ADMA_ROE (1 << 30) /* Relaxed Ordering Enable */ +#define IOP34X_ADMA_NSE (1U << 31) /* No Snoop Enable */ + +#define IOP34X_PBBAR0 0x81588 /* PBI Base Address Register 0 */ +#define IOP34X_PBBAR0_ADDRMASK 0xfffff000 +#define IOP34X_PBBAR1 0x81590 +#define IOP34X_PCE1 0xF2000000 +#define IOP34X_PCE1_SIZE 0x00100000 +#define IOP34X_PCE1_VADDR 0xF1000000 +#define IOP34X_ESSTSR0 0x82188 +#define IOP34X_CONTROLLER_ONLY (1 << 14) +#define IOP34X_INT_SEL_PCIX (1 << 15) +#define IOP34X_PFR 0x82180 /* Processor Frequency Register */ +#define IOP34X_FREQ_MASK ((1 << 16) | (1 << 17) | (1 << 18)) +#define IOP34X_FREQ_600 (0) +#define IOP34X_FREQ_667 (1 << 16) +#define IOP34X_FREQ_800 (1 << 17) +#define IOP34X_FREQ_833 ((1 << 17) | (1 << 16)) +#define IOP34X_FREQ_1000 (1 << 18) +#define IOP34X_FREQ_1200 ((1 << 16) | (1 << 18)) + +#define IOP34X_UART0_VADDR IOP34X_VADDR + 0x82300 +#define IOP34X_UART0_HWADDR IOP34X_HWADDR + 0x82300 +#define IOP34X_UART1_VADDR IOP34X_VADDR + 0x82340 +#define IOP34X_UART1_HWADDR IOP34X_HWADDR + 0x82340 +#define IOP34X_PBI_HWADDR 0xffd81580 + +/* SDRAM Memory Controller */ +#define SMC_SDBR 0x8180c /* Base Register */ +#define SMC_SDBR_BASEADDR (1 << 27) +#define SMC_SDBR_BASEADDR_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \ + | (1U << 31)) +#define SMC_SDUBR 0x81810 /* Upper Base Register */ +#define SMC_SBSR 0x81814 /* SDRAM Bank Size Register */ +#define SMC_SBSR_BANK_NB (1 << 2) /* Number of DDR Banks + 0 => 2 Banks + 1 => 1 Bank + */ +#define SMC_SBSR_BANK_SZ (1 << 27) /* SDRAM Bank Size : + 0x00000 Empty + 0x00001 128MB + 0x00010 256MB + 0x00100 512MB + 0x01000 1GB + */ +#define SMC_SBSR_BANK_SZ_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \ + | (1U << 31)) + + +/* Two possible addresses for ATUe depending on configuration. */ +#define IOP34X_ATUE_ADDR(esstrsr) ((((esstrsr) & (IOP34X_CONTROLLER_ONLY | \ + IOP34X_INT_SEL_PCIX)) == (IOP34X_CONTROLLER_ONLY | IOP34X_INT_SEL_PCIX)) ? \ + 0xffdc8000 : 0xffdcd000) + +/* Three possible addresses for ATU-X depending on configuration. */ +#define IOP34X_ATUX_ADDR(esstrsr) (!((esstrsr) & IOP34X_CONTROLLER_ONLY) ? \ + 0xffdcc000 : !((esstrsr) & IOP34X_INT_SEL_PCIX) ? 0xffdc8000 : 0xffdcd000) + +#define IOP34X_OIOBAR_SIZE 0x10000 +#define IOP34X_PCIX_OIOBAR 0xfffb0000 +#define IOP34X_PCIX_OIOBAR_VADDR 0xf01b0000 +#define IOP34X_PCIX_OMBAR 0x100000000 +#define IOP34X_PCIE_OIOBAR 0xfffd0000 +#define IOP34X_PCIE_OIOBAR_VADDR 0xf01d0000 +#define IOP34X_PCIE_OMBAR 0x200000000 + +/* ATU Registers */ +/* Common for ATU-X and ATUe */ +#define ATU_VID 0x0000 /* ATU Vendor ID */ +#define ATU_DID 0x0002 /* ATU Device ID */ +#define ATU_CMD 0x0004 /* ATU Command Register */ +#define ATU_SR 0x0006 /* ATU Status Register */ +#define ATU_RID 0x0008 /* ATU Revision ID */ +#define ATU_CCR 0x0009 /* ATU Class Code */ +#define ATU_CLSR 0x000c /* ATU Cacheline Size */ +#define ATU_LT 0x000d /* ATU Latency Timer */ +#define ATU_HTR 0x000e /* ATU Header Type */ +#define ATU_BISTR 0x000f /* ATU BIST Register */ +#define ATU_IABAR0 0x0010 /* Inbound ATU Base Address register 0 */ +#define ATU_IAUBAR0 0x0014 /* Inbound ATU Upper Base Address Register 0 */ +#define ATU_IABAR1 0x0018 /* Inbound ATU Base Address Register 1 */ +#define ATU_IAUBAR1 0x001c /* Inbound ATU Upper Base Address Register 1 */ +#define ATU_IABAR2 0x0020 /* Inbound ATU Base Address Register 2 */ +#define ATU_IAUBAR2 0x0024 /* Inbound ATU Upper Base Address Register 2 */ +#define ATU_VSIR 0x002c /* ATU Subsystem Vendor ID Register */ +#define ATU_SIR 0x002e /* ATU Subsystem ID Register */ +#define ATU_ERBAR 0x0030 /* Expansion ROM Base Address Register */ +#define ATU_CAPPTR 0x0034 /* ATU Capabilities Pointer Register */ +#define ATU_ILR 0x003c /* ATU Interrupt Line Register */ +#define ATU_IPR 0x003d /* ATU Interrupt Pin Register */ +#define ATU_MGNT 0x003e /* ATU Minimum Grand Register */ +#define ATU_MLAT 0x003f /* ATU Maximum Latency Register */ +#define ATU_IALR0 0x0040 /* Inbound ATU Limit Register 0 */ +#define ATU_IATVR0 0x0044 /* Inbound ATU Translate Value Register 0 */ +#define ATU_IAUTVR0 0x0048 /* Inbound ATU Upper Translate Value Register 0*/ +#define ATU_IALR1 0x004c /* Inbound ATU Limit Register 1 */ +#define ATU_IATVR1 0x0050 /* Inbound ATU Translate Value Register 1 */ +#define ATU_IAUTVR1 0x0054 /* Inbound ATU Upper Translate Value Register 1*/ +#define ATU_IALR2 0x0058 /* Inbound ATU Limit Register 2 */ +#define ATU_IATVR2 0x005c /* Inbound ATU Translate Value Register 2 */ +#define ATU_IAUTVR2 0x0060 /* Inbound ATU Upper Translate Value Register 2*/ +#define ATU_ERLR 0x0064 /* Expansion ROM Limit Register */ +#define ATU_ERTVR 0x0068 /* Expansion ROM Translator Value Register */ +#define ATU_ERUTVR 0x006c /* Expansion ROM Upper Translate Value Register*/ +#define ATU_CR 0x0070 /* ATU Configuration Register */ +#define ATU_CR_OUT_EN (1 << 1) +#define ATU_PCSR 0x0074 /* PCI Configuration and Status Register */ +#define PCIE_BUSNO(x) ((x & 0xff000000) >> 24) +#define ATUX_CORE_RST ((1 << 30) | (1U << 31)) /* Core Processor Reset */ +#define ATUX_P_RSTOUT (1 << 21) /* Central Resource PCI Bus Reset */ +#define ATUE_CORE_RST ((1 << 9) | (1 << 8)) /* Core Processor Reset */ +#define ATU_ISR 0x0078 /* ATU Interrupt Status Register */ +#define ATUX_ISR_PIE (1 << 18) /* PCI Interface error */ +#define ATUX_ISR_IBPR (1 << 16) /* Internal Bus Parity Error */ +#define ATUX_ISR_DCE (1 << 14) /* Detected Correctable error */ +#define ATUX_ISR_ISCE (1 << 13) /* Initiated Split Completion Error Msg */ +#define ATUX_ISR_RSCE (1 << 12) /* Received Split Completion Error Msg */ +#define ATUX_ISR_DPE (1 << 9) /* Detected Parity Error */ +#define ATUX_ISR_IBMA (1 << 7) /* Internal Bus Master Abort */ +#define ATUX_ISR_PMA (1 << 3) /* PCI Master Abort */ +#define ATUX_ISR_PTAM (1 << 2) /* PCI Target Abort (Master) */ +#define ATUX_ISR_PTAT (1 << 1) /* PCI Target Abort (Target) */ +#define ATUX_ISR_PMPE (1 << 0) /* PCI Master Parity Error */ +#define ATUX_ISR_ERRMSK (ATUX_ISR_PIE | ATUX_ISR_IBPR | ATUX_ISR_DCE | \ + ATUX_ISR_ISCE | ATUX_ISR_RSCE | ATUX_ISR_DPE | ATUX_ISR_IBMA | ATUX_ISR_PMA\ + | ATUX_ISR_PTAM | ATUX_ISR_PTAT | ATUX_ISR_PMPE) +#define ATUE_ISR_HON (1 << 13) /* Halt on Error Interrupt */ +#define ATUE_ISR_RSE (1 << 12) /* Root System Error Message */ +#define ATUE_ISR_REM (1 << 11) /* Root Error Message */ +#define ATUE_ISR_PIE (1 << 10) /* PCI Interface error */ +#define ATUE_ISR_CEM (1 << 9) /* Correctable Error Message */ +#define ATUE_ISR_UEM (1 << 8) /* Uncorrectable error message */ +#define ATUE_ISR_CRS (1 << 7) /* Received Configuration Retry Status */ +#define ATUE_ISR_IBMA (1 << 5) /* Internal Bus Master Abort */ +#define ATUE_ISR_DPE (1 << 4) /* Detected Parity Error Interrupt */ +#define ATUE_ISR_MAI (1 << 3) /* Received Master Abort Interrupt */ +#define ATUE_ISR_STAI (1 << 2) /* Signaled Target Abort Interrupt */ +#define ATUE_ISR_TAI (1 << 1) /* Received Target Abort Interrupt */ +#define ATUE_ISR_MDPE (1 << 0) /* Master Data Parity Error Interrupt */ +#define ATUE_ISR_ERRMSK (ATUE_ISR_HON | ATUE_ISR_RSE | ATUE_ISR_REM | \ + ATUE_ISR_PIE | ATUE_ISR_CEM | ATUE_ISR_UEM | ATUE_ISR_CRS | ATUE_ISR_IBMA |\ + ATUE_ISR_DPE | ATUE_ISR_MAI | ATUE_ISR_STAI | ATUE_ISR_TAI | ATUE_ISR_MDPE) +#define ATU_IMR 0x007c /* ATU Interrupt Mask Register */ +/* 0x0080 - 0x008f reserved */ +#define ATU_VPDCID 0x0090 /* VPD Capability Identifier Register */ +#define ATU_VPDNIP 0x0091 /* VPD Next Item Pointer Register */ +#define ATU_VPDAR 0x0092 /* VPD Address Register */ +#define ATU_VPDDR 0x0094 /* VPD Data Register */ +#define ATU_PMCID 0x0098 /* PM Capability Identifier Register */ +#define ATU_PMNIPR 0x0099 /* PM Next Item Pointer Register */ +#define ATU_PMCR 0x009a /* ATU Power Management Capabilities Register */ +#define ATU_PMCSR 0x009c /* ATU Power Management Control/Status Register*/ +#define ATU_MSICIR 0x00a0 /* MSI Capability Identifier Register */ +#define ATU_MSINIPR 0x00a1 /* MSI Next Item Pointer Register */ +#define ATU_MCR 0x00a2 /* Message Control Register */ +#define ATU_MAR 0x00a4 /* Message Address Register */ +#define ATU_MUAR 0x00a8 /* Message Upper Address Register */ +#define ATU_MDR 0x00ac /* Message Data Register */ +#define ATU_PCIXSR 0x00d4 /* PCI-X Status Register */ +#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8) +#define ATU_IABAR3 0x0200 /* Inbound ATU Base Address Register 3 */ +#define ATU_IAUBAR3 0x0204 /* Inbound ATU Upper Base Address Register 3 */ +#define ATU_IALR3 0x0208 /* Inbound ATU Limit Register 3 */ +#define ATU_ITVR3 0x020c /* Inbound ATU Upper Translate Value Reg 3 */ +#define ATU_OIOBAR 0x0300 /* Outbound I/O Base Address Register */ +#define ATU_OIOWTVR 0x0304 /* Outbound I/O Window Translate Value Reg */ +#define ATU_OUMBAR0 0x0308 /* Outbound Upper Memory Window base addr reg 0*/ +#define ATU_OUMBAR_FUNC (28) +#define ATU_OUMBAR_EN (1U << 31) +#define ATU_OUMWTVR0 0x030c /* Outbound Upper 32bit Memory Window Translate Value Register 0 */ +#define ATU_OUMBAR1 0x0310 /* Outbound Upper Memory Window base addr reg1*/ +#define ATU_OUMWTVR1 0x0314 /* Outbound Upper 32bit Memory Window Translate Value Register 1 */ +#define ATU_OUMBAR2 0x0318 /* Outbound Upper Memory Window base addr reg2*/ +#define ATU_OUMWTVR2 0x031c /* Outbount Upper 32bit Memory Window Translate Value Register 2 */ +#define ATU_OUMBAR3 0x0320 /* Outbound Upper Memory Window base addr reg3*/ +#define ATU_OUMWTVR3 0x0324 /* Outbound Upper 32bit Memory Window Translate Value Register 3 */ + +/* ATU-X specific */ +#define ATUX_OCCAR 0x0330 /* Outbound Configuration Cycle Address Reg */ +#define ATUX_OCCDR 0x0334 /* Outbound Configuration Cycle Data Reg */ +#define ATUX_OCCFN 0x0338 /* Outbound Configuration Cycle Function Number*/ +/* ATUe specific */ +#define ATUE_OCCAR 0x032c /* Outbound Configuration Cycle Address Reg */ +#define ATUE_OCCDR 0x0330 /* Outbound Configuration Cycle Data Reg */ +#define ATUE_OCCFN 0x0334 /* Outbound Configuration Cycle Function Number*/ +/* Interrupts */ + +/* IINTRSRC0 */ +#define ICU_INT_ADMA0_EOT (0) /* ADMA 0 End of transfer */ +#define ICU_INT_ADMA0_EOC (1) /* ADMA 0 End of Chain */ +#define ICU_INT_ADMA1_EOT (2) /* ADMA 1 End of transfer */ +#define ICU_INT_ADMA1_EOC (3) /* ADMA 1 End of chain */ +#define ICU_INT_ADMA2_EOT (4) /* ADMA 2 End of transfer */ +#define ICU_INT_ADMA2_EOC (5) /* ADMA 2 end of chain */ +#define ICU_INT_WDOG (6) /* Watchdog timer */ +/* 7 Reserved */ +#define ICU_INT_TIMER0 (8) /* Timer 0 */ +#define ICU_INT_TIMER1 (9) /* Timer 1 */ +#define ICU_INT_I2C0 (10) /* I2C bus interface 0 */ +#define ICU_INT_I2C1 (11) /* I2C bus interface 1 */ +#define ICU_INT_MU (12) /* Message Unit */ +#define ICU_INT_MU_IPQ (13) /* Message unit inbound post queue */ +#define ICU_INT_ATUE_IM (14) /* ATU-E inbound message */ +#define ICU_INT_ATU_BIST (15) /* ATU/Start BIST */ +#define ICU_INT_PMC (16) /* PMC */ +#define ICU_INT_PMU (17) /* PMU */ +#define ICU_INT_PC (18) /* Processor cache */ +/* 19-23 Reserved */ +#define ICU_INT_XINT0 (24) +#define ICU_INT_XINT1 (25) +#define ICU_INT_XINT2 (26) +#define ICU_INT_XINT3 (27) +#define ICU_INT_XINT4 (28) +#define ICU_INT_XINT5 (29) +#define ICU_INT_XINT6 (30) +#define ICU_INT_XINT7 (31) +/* IINTSRC1 */ +#define ICU_INT_XINT8 (32) +#define ICU_INT_XINT9 (33) +#define ICU_INT_XINT10 (34) +#define ICU_INT_XINT11 (35) +#define ICU_INT_XINT12 (36) +#define ICU_INT_XINT13 (37) +#define ICU_INT_XINT14 (38) +#define ICU_INT_XINT15 (39) +/* 40-50 reserved */ +#define ICU_INT_UART0 (51) /* UART 0 */ +#define ICU_INT_UART1 (52) /* UART 1 */ +#define ICU_INT_PBIUE (53) /* Peripheral bus interface unit error */ +#define ICU_INT_ATUCRW (54) /* ATU Configuration register write */ +#define ICU_INT_ATUE (55) /* ATU error */ +#define ICU_INT_MCUE (56) /* Memory controller unit error */ +#define ICU_INT_ADMA0E (57) /* ADMA Channel 0 error */ +#define ICU_INT_ADMA1E (58) /* ADMA Channel 1 error */ +#define ICU_INT_ADMA2E (59) /* ADMA Channel 2 error */ +/* 60-61 reserved */ +#define ICU_INT_MUE (62) /* Messaging Unit Error */ +/* 63 reserved */ + +/* IINTSRC2 */ +#define ICU_INT_IP (64) /* Inter-processor */ +/* 65-93 reserved */ +#define ICU_INT_SIBBE (94) /* South internal bus bridge error */ +/* 95 reserved */ + +/* IINTSRC3 */ +#define ICU_INT_I2C2 (96) /* I2C bus interface 2 */ +#define ICU_INT_ATUE_BIST (97) /* ATU-E/Start BIST */ +#define ICU_INT_ATUE_CRW (98) /* ATU-E Configuration register write */ +#define ICU_INT_ATUEE (99) /* ATU-E Error */ +#define ICU_INT_IMU (100) /* IMU */ +/* 101-106 reserved */ +#define ICU_INT_ATUE_MA (107) /* ATUE Interrupt message A */ +#define ICU_INT_ATUE_MB (108) /* ATUE Interrupt message B */ +#define ICU_INT_ATUE_MC (109) /* ATUE Interrupt message C */ +#define ICU_INT_ATUE_MD (110) /* ATUE Interrupt message D */ +#define ICU_INT_MU_MSIX_TW (111) /* MU MSI-X Table write */ +/* 112 reserved */ +#define ICU_INT_IMSI (113) /* Inbound MSI */ +/* 114-126 reserved */ +#define ICU_INT_HPI (127) /* HPI */ + + +#endif /* I81342_REG_H_ */ diff --git a/sys/arm/xscale/i8134x/i81342var.h b/sys/arm/xscale/i8134x/i81342var.h new file mode 100644 index 000000000000..92574964610e --- /dev/null +++ b/sys/arm/xscale/i8134x/i81342var.h @@ -0,0 +1,72 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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. + */ + +/* $FreeBSD$ */ +#ifndef I81342VAR_H_ +#define I81342VAR_H_ + +#include <sys/rman.h> + +struct i81342_softc { + device_t dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + bus_space_handle_t sc_atux_sh; + bus_space_handle_t sc_atue_sh; + bus_space_tag_t sc_pciio; + bus_space_tag_t sc_pcimem; + struct rman sc_irq_rman; +}; + +struct i81342_pci_map { + vm_offset_t vaddr; + vm_paddr_t paddr; + vm_size_t size; + struct i81342_pci_map *next; +}; + +struct i81342_pci_softc { + device_t sc_dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_atu_sh; + struct bus_space sc_pciio; + struct bus_space sc_pcimem; + struct rman sc_mem_rman; + struct rman sc_io_rman; + struct rman sc_irq_rman; + char sc_is_atux; + int sc_busno; + struct i81342_pci_map *sc_pci_mappings; +}; + +void i81342_bs_init(bus_space_tag_t, void *); +void i81342_io_bs_init(bus_space_tag_t, void *); +void i81342_mem_bs_init(bus_space_tag_t, void *); +void i81342_sdram_bounds(bus_space_tag_t, bus_space_handle_t, vm_paddr_t *, + vm_size_t *); +#endif /*I81342VAR_H_ */ diff --git a/sys/arm/xscale/i8134x/iq81342_7seg.c b/sys/arm/xscale/i8134x/iq81342_7seg.c new file mode 100644 index 000000000000..7264d1c9e656 --- /dev/null +++ b/sys/arm/xscale/i8134x/iq81342_7seg.c @@ -0,0 +1,393 @@ +/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001, 2002, 2003 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. + */ + +/* + * Support for the 7-segment display on the Intel IQ81342. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/iq81342reg.h> +#include <arm/xscale/i8134x/iq81342var.h> + +#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v) + +static int snakestate; + +/* + * The 7-segment display looks like so: + * + * A + * +-----+ + * | | + * F | | B + * | G | + * +-----+ + * | | + * E | | C + * | D | + * +-----+ o DP + * + * Setting a bit clears the corresponding segment on the + * display. + */ +#define SEG_A (1 << 1) +#define SEG_B (1 << 2) +#define SEG_C (1 << 3) +#define SEG_D (1 << 4) +#define SEG_E (1 << 5) +#define SEG_F (1 << 6) +#define SEG_G (1 << 7) +#define SEG_DP (1 << 0) + +static const uint8_t digitmap[] = { +/* +#####+ + * # # + * # # + * # # + * +-----+ + * # # + * # # + * # # + * +#####+ + */ + (unsigned char)~SEG_G, + +/* +-----+ + * | # + * | # + * | # + * +-----+ + * | # + * | # + * | # + * +-----+ + */ + SEG_B|SEG_C, + +/* +#####+ + * | # + * | # + * | # + * +#####+ + * # | + * # | + * # | + * +#####+ + */ + ~(SEG_C|SEG_F), + +/* +#####+ + * | # + * | # + * | # + * +#####+ + * | # + * | # + * | # + * +#####+ + */ + ~(SEG_E|SEG_F), + +/* +-----+ + * # # + * # # + * # # + * +#####+ + * | # + * | # + * | # + * +-----+ + */ + ~(SEG_A|SEG_D|SEG_E), + +/* +#####+ + * # | + * # | + * # | + * +#####+ + * | # + * | # + * | # + * +#####+ + */ + ~(SEG_B|SEG_E), + +/* +#####+ + * # | + * # | + * # | + * +#####+ + * # # + * # # + * # # + * +#####+ + */ + ~(SEG_B), + +/* +#####+ + * | # + * | # + * | # + * +-----+ + * | # + * | # + * | # + * +-----+ + */ + ~(SEG_D|SEG_E|SEG_F), + +/* +#####+ + * # # + * # # + * # # + * +#####+ + * # # + * # # + * # # + * +#####+ + */ + ~0, + +/* +#####+ + * # # + * # # + * # # + * +#####+ + * | # + * | # + * | # + * +-----+ + */ + ~(SEG_D|SEG_E), +}; + +static uint8_t +iq81342_7seg_xlate(char c) +{ + uint8_t rv; + + if (c >= '0' && c <= '9') + rv = digitmap[c - '0']; + else if (c == '.') + rv = (uint8_t) ~SEG_DP; + else + rv = 0xff; + + return (rv); +} + +void +iq81342_7seg(char a, char b) +{ + uint8_t msb, lsb; + + msb = iq81342_7seg_xlate(a); + lsb = iq81342_7seg_xlate(b); + + snakestate = 0; + + WRITE(IQ8134X_7SEG_MSB, msb); + WRITE(IQ8134X_7SEG_LSB, lsb); +} + +static const uint8_t snakemap[][2] = { + +/* +#####+ +#####+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + */ + { SEG_A, SEG_A }, + +/* +-----+ +-----+ + * # | | # + * # | | # + * # | | # + * +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + */ + { SEG_F, SEG_B }, + +/* +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +#####+ +#####+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + */ + { SEG_G, SEG_G }, + +/* +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + * | # # | + * | # # | + * | # # | + * +-----+ +-----+ + */ + { SEG_C, SEG_E }, + +/* +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +#####+ +#####+ + */ + { SEG_D, SEG_D }, + +/* +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + * # | | # + * # | | # + * # | | # + * +-----+ +-----+ + */ + { SEG_E, SEG_C }, + +/* +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +#####+ +#####+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + */ + { SEG_G, SEG_G }, + +/* +-----+ +-----+ + * | # # | + * | # # | + * | # # | + * +-----+ +-----+ + * | | | | + * | | | | + * | | | | + * +-----+ +-----+ + */ + { SEG_B, SEG_F }, +}; + +static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg"); +static int freq = 20; +SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0, + "7 Seg update frequency"); +static void +iq81342_7seg_snake(void) +{ + static int snakefreq; + int cur = snakestate; + + snakefreq++; + if ((snakefreq % freq)) + return; + WRITE(IQ8134X_7SEG_MSB, snakemap[cur][0]); + WRITE(IQ8134X_7SEG_LSB, snakemap[cur][1]); + + snakestate = (cur + 1) & 7; +} + +struct iq81342_7seg_softc { + device_t dev; +}; + +static int +iq81342_7seg_probe(device_t dev) +{ + + device_set_desc(dev, "IQ81342 7seg"); + return (0); +} + +extern void (*i80321_hardclock_hook)(void); +static int +iq81342_7seg_attach(device_t dev) +{ + + i80321_hardclock_hook = iq81342_7seg_snake; + return (0); +} + +static device_method_t iq81342_7seg_methods[] = { + DEVMETHOD(device_probe, iq81342_7seg_probe), + DEVMETHOD(device_attach, iq81342_7seg_attach), + {0, 0}, +}; + +static driver_t iq81342_7seg_driver = { + "iqseg", + iq81342_7seg_methods, + sizeof(struct iq81342_7seg_softc), +}; +static devclass_t iq81342_7seg_devclass; + +DRIVER_MODULE(iqseg, iq, iq81342_7seg_driver, iq81342_7seg_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/iq81342reg.h b/sys/arm/xscale/i8134x/iq81342reg.h new file mode 100644 index 000000000000..da1e67b83f21 --- /dev/null +++ b/sys/arm/xscale/i8134x/iq81342reg.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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. + */ + +/* $FreeBSD$ */ + +#ifndef _IQ81342REG_H_ +#define _IQ81342REG_H_ +#define IQ8134X_7SEG_MSB IOP34X_PCE1_VADDR + 0x40000 +#define IQ8134X_7SEG_LSB IOP34X_PCE1_VADDR + 0x50000 +#endif /* _IQ81342REG_H_ */ diff --git a/sys/arm/xscale/i8134x/iq81342var.h b/sys/arm/xscale/i8134x/iq81342var.h new file mode 100644 index 000000000000..8c89a0f82ef7 --- /dev/null +++ b/sys/arm/xscale/i8134x/iq81342var.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Olivier Houchard + * 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. + * + * 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 + * 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. + */ + +/* $FreeBSD$ */ + +#ifndef _IQ81342VAR_H_ +#define _IQ81342VAR_H_ +void iq81342_7seg(char, char); +#endif /* _I8Q1342VAR_H_ */ diff --git a/sys/arm/xscale/i8134x/obio.c b/sys/arm/xscale/i8134x/obio.c new file mode 100644 index 000000000000..f81b02795a77 --- /dev/null +++ b/sys/arm/xscale/i8134x/obio.c @@ -0,0 +1,168 @@ +/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001, 2002, 2003 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. + */ + +/* + * On-board device autoconfiguration support for Intel IQ80321 + * evaluation boards. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/obiovar.h> + +static int +obio_probe(device_t dev) +{ + return (0); +} + +static int +obio_attach(device_t dev) +{ + struct obio_softc *sc = device_get_softc(dev); + + sc->oba_st = arm_base_bs_tag; + sc->oba_rman.rm_type = RMAN_ARRAY; + sc->oba_rman.rm_descr = "OBIO I/O"; + if (rman_init(&sc->oba_rman) != 0 || + rman_manage_region(&sc->oba_rman, + IOP34X_UART0_VADDR, IOP34X_UART1_VADDR + 0x40) != 0) + panic("obio_attach: failed to set up I/O rman"); + sc->oba_irq_rman.rm_type = RMAN_ARRAY; + sc->oba_irq_rman.rm_descr = "OBIO IRQ"; + if (rman_init(&sc->oba_irq_rman) != 0 || + rman_manage_region(&sc->oba_irq_rman, ICU_INT_UART0, ICU_INT_UART1) != 0) + panic("obio_attach: failed to set up IRQ rman"); + device_add_child(dev, "uart", 0); + device_add_child(dev, "uart", 1); + bus_generic_probe(dev); + bus_generic_attach(dev); + return (0); +} + +static struct resource * +obio_alloc_resource(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct resource *rv; + struct rman *rm; + bus_space_tag_t bt = NULL; + bus_space_handle_t bh = 0; + struct obio_softc *sc = device_get_softc(bus); + int unit = device_get_unit(child); + + switch (type) { + case SYS_RES_IRQ: + rm = &sc->oba_irq_rman; + if (unit == 0) + start = end = ICU_INT_UART0; + else + start = end = ICU_INT_UART1; + break; + case SYS_RES_MEMORY: + return (NULL); + case SYS_RES_IOPORT: + rm = &sc->oba_rman; + bt = sc->oba_st; + if (unit == 0) { + bh = IOP34X_UART0_VADDR; + start = bh; + end = IOP34X_UART1_VADDR; + } else { + bh = IOP34X_UART1_VADDR; + start = bh; + end = start + 0x40; + } + break; + default: + return (NULL); + } + + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) + return (NULL); + if (type == SYS_RES_IRQ) + return (rv); + rman_set_rid(rv, *rid); + rman_set_bustag(rv, bt); + rman_set_bushandle(rv, bh); + + return (rv); + +} + +static int +obio_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (0); +} +static device_method_t obio_methods[] = { + DEVMETHOD(device_probe, obio_probe), + DEVMETHOD(device_attach, obio_attach), + + DEVMETHOD(bus_alloc_resource, obio_alloc_resource), + DEVMETHOD(bus_activate_resource, obio_activate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + {0, 0}, +}; + +static driver_t obio_driver = { + "obio", + obio_methods, + sizeof(struct obio_softc), +}; +static devclass_t obio_devclass; + +DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/obiovar.h b/sys/arm/xscale/i8134x/obiovar.h new file mode 100644 index 000000000000..fe773df10c82 --- /dev/null +++ b/sys/arm/xscale/i8134x/obiovar.h @@ -0,0 +1,56 @@ +/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2002, 2003 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. + * + * $FreeBSD$ + * + */ + +#ifndef _IQ81342_OBIOVAR_H_ +#define _IQ81342_OBIOVAR_H_ + +#include <sys/rman.h> + +struct obio_softc { + bus_space_tag_t oba_st; /* bus space tag */ + int oba_irq; /* XINT interrupt bit # */ + struct rman oba_rman; + struct rman oba_irq_rman; + +}; + +#endif /* _IQ80321_OBIOVAR_H_ */ diff --git a/sys/arm/xscale/i8134x/std.crb b/sys/arm/xscale/i8134x/std.crb new file mode 100644 index 000000000000..fe80ffb1c02e --- /dev/null +++ b/sys/arm/xscale/i8134x/std.crb @@ -0,0 +1,6 @@ +#CRB board configuration +#$FreeBSD$ +include "../xscale/i8134x/std.i81342" +files "../xscale/i8134x/files.crb" +makeoptions KERNPHYSADDR=0x00200000 +makeoptions KERNVIRTADDR=0xc0200000 diff --git a/sys/arm/xscale/i8134x/std.i81342 b/sys/arm/xscale/i8134x/std.i81342 new file mode 100644 index 000000000000..a9ad3f92a3c8 --- /dev/null +++ b/sys/arm/xscale/i8134x/std.i81342 @@ -0,0 +1,6 @@ +#XScale i81342 generic configuration +#$FreeBSD$ +files "../xscale/i8134x/files.i81342" +include "../xscale/std.xscale" +cpu CPU_XSCALE_81342 +machine arm diff --git a/sys/arm/xscale/i8134x/uart_bus_i81342.c b/sys/arm/xscale/i8134x/uart_bus_i81342.c new file mode 100644 index 000000000000..c1b39f7db55d --- /dev/null +++ b/sys/arm/xscale/i8134x/uart_bus_i81342.c @@ -0,0 +1,94 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2004 Olivier Houchard. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + +#include <dev/pci/pcivar.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> +#include <dev/uart/uart_cpu.h> + +#include <dev/ic/ns16550.h> + +#include "uart_if.h" + +static int uart_i81342_probe(device_t dev); + +static device_method_t uart_i81342_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_i81342_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + { 0, 0 } +}; + +static driver_t uart_i81342_driver = { + uart_driver_name, + uart_i81342_methods, + sizeof(struct uart_softc), +}; + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; +static int +uart_i81342_probe(device_t dev) +{ + struct uart_softc *sc; + int err; + + sc = device_get_softc(dev); + sc->sc_class = &uart_ns8250_class; + if (device_get_unit(dev) == 0) { + sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + } + sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, + &sc->sc_rrid, uart_getrange(sc->sc_class), RF_ACTIVE); + + sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); + sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); + bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, REG_IER << 2, + 0x40 | 0x10); + bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); + + err = uart_bus_probe(dev, 2, 0, 33334000, 0, device_get_unit(dev)); + sc->sc_rxfifosz = sc->sc_txfifosz = 1; + return (err); +} + + +DRIVER_MODULE(uart, obio, uart_i81342_driver, uart_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/uart_cpu_i81342.c b/sys/arm/xscale/i8134x/uart_cpu_i81342.c new file mode 100644 index 000000000000..59bd47602186 --- /dev/null +++ b/sys/arm/xscale/i8134x/uart_cpu_i81342.c @@ -0,0 +1,70 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2003 Marcel Moolenaar + * 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <machine/bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> + +#include <arm/xscale/i8134x/i81342reg.h> +#include <arm/xscale/i8134x/obiovar.h> + +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + +int +uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +{ + return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); +} + +int +uart_cpu_getdev(int devtype, struct uart_devinfo *di) +{ + + di->ops = uart_getops(&uart_ns8250_class); + di->bas.chan = 0; + di->bas.bst = arm_base_bs_tag; + di->bas.regshft = 2; + di->bas.rclk = 33334000; + di->baudrate = 115200; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + uart_bus_space_io = arm_base_bs_tag; + uart_bus_space_mem = NULL; + di->bas.bsh = IOP34X_UART0_VADDR; + return (0); +} diff --git a/sys/arm/xscale/pxa/files.pxa b/sys/arm/xscale/pxa/files.pxa new file mode 100644 index 000000000000..652877060dcb --- /dev/null +++ b/sys/arm/xscale/pxa/files.pxa @@ -0,0 +1,14 @@ +# $FreeBSD$ + +arm/xscale/pxa/pxa_gpio.c standard +arm/xscale/pxa/pxa_icu.c standard +arm/xscale/pxa/pxa_machdep.c standard +arm/xscale/pxa/pxa_obio.c standard +arm/xscale/pxa/pxa_smi.c standard +arm/xscale/pxa/pxa_space.c standard +arm/xscale/pxa/pxa_timer.c standard + +arm/xscale/pxa/uart_bus_pxa.c optional uart +arm/xscale/pxa/uart_cpu_pxa.c optional uart + +arm/xscale/pxa/if_smc_smi.c optional smc diff --git a/sys/arm/xscale/pxa/if_smc_smi.c b/sys/arm/xscale/pxa/if_smc_smi.c new file mode 100644 index 000000000000..4b9c58d8d865 --- /dev/null +++ b/sys/arm/xscale/pxa/if_smc_smi.c @@ -0,0 +1,127 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008 Benno Rice + * 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/systm.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <net/if_media.h> + +#include <dev/smc/if_smcvar.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +#include "miibus_if.h" + +#include <arm/xscale/pxa/pxareg.h> +#include <arm/xscale/pxa/pxavar.h> + +static int smc_smi_probe(device_t); +static int smc_smi_attach(device_t); +static int smc_smi_detach(device_t); + +static int +smc_smi_probe(device_t dev) +{ + struct smc_softc *sc; + + sc = device_get_softc(dev); + sc->smc_usemem = 1; + + if (smc_probe(dev) != 0) { + return (ENXIO); + } + return (0); +} + +static int +smc_smi_attach(device_t dev) +{ + int err; + struct smc_softc *sc; + + sc = device_get_softc(dev); + + err = smc_attach(dev); + if (err) { + return (err); + } + + return (0); +} + +static int +smc_smi_detach(device_t dev) +{ + + smc_detach(dev); + + return (0); +} + +static device_method_t smc_smi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, smc_smi_probe), + DEVMETHOD(device_attach, smc_smi_attach), + DEVMETHOD(device_detach, smc_smi_detach), + + /* MII interface */ + DEVMETHOD(miibus_readreg, smc_miibus_readreg), + DEVMETHOD(miibus_writereg, smc_miibus_writereg), + DEVMETHOD(miibus_statchg, smc_miibus_statchg), + + { 0, 0 } +}; + +static driver_t smc_smi_driver = { + "smc", + smc_smi_methods, + sizeof(struct smc_softc), +}; + +extern devclass_t smc_devclass; + +DRIVER_MODULE(smc, smi, smc_smi_driver, smc_devclass, 0, 0); +DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0); +MODULE_DEPEND(smc, smi, 1, 1, 1); +MODULE_DEPEND(smc, ether, 1, 1, 1); +MODULE_DEPEND(smc, miibus, 1, 1, 1); diff --git a/sys/arm/xscale/pxa/pxa_gpio.c b/sys/arm/xscale/pxa/pxa_gpio.c new file mode 100644 index 000000000000..91f3865d3ba5 --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_gpio.c @@ -0,0 +1,360 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/interrupt.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> +#include <sys/timetc.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +struct pxa_gpio_softc { + struct resource * pg_res[4]; + bus_space_tag_t pg_bst; + bus_space_handle_t pg_bsh; + struct mtx pg_mtx; + + uint32_t pg_intr[3]; +}; + +static struct resource_spec pxa_gpio_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { -1, 0 } +}; + +static struct pxa_gpio_softc *pxa_gpio_softc = NULL; + +static int pxa_gpio_probe(device_t); +static int pxa_gpio_attach(device_t); + +static driver_filter_t pxa_gpio_intr0; +static driver_filter_t pxa_gpio_intr1; +static driver_filter_t pxa_gpio_intrN; + +static int +pxa_gpio_probe(device_t dev) +{ + + device_set_desc(dev, "GPIO Controller"); + return (0); +} + +static int +pxa_gpio_attach(device_t dev) +{ + int error; + void *ihl; + struct pxa_gpio_softc *sc; + + sc = (struct pxa_gpio_softc *)device_get_softc(dev); + + if (pxa_gpio_softc != NULL) + return (ENXIO); + pxa_gpio_softc = sc; + + error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res); + if (error) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->pg_bst = rman_get_bustag(sc->pg_res[0]); + sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]); + + /* Disable and clear all interrupts. */ + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER0, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER1, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER2, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER0, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER1, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER2, 0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, ~0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, ~0); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, ~0); + + mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN); + + if (bus_setup_intr(dev, sc->pg_res[1], INTR_TYPE_MISC|INTR_MPSAFE, + pxa_gpio_intr0, NULL, sc, &ihl) != 0) { + bus_release_resources(dev, pxa_gpio_spec, sc->pg_res); + device_printf(dev, "could not set up intr0\n"); + return (ENXIO); + } + + if (bus_setup_intr(dev, sc->pg_res[2], INTR_TYPE_MISC|INTR_MPSAFE, + pxa_gpio_intr1, NULL, sc, &ihl) != 0) { + bus_release_resources(dev, pxa_gpio_spec, sc->pg_res); + device_printf(dev, "could not set up intr1\n"); + return (ENXIO); + } + + if (bus_setup_intr(dev, sc->pg_res[3], INTR_TYPE_MISC|INTR_MPSAFE, + pxa_gpio_intrN, NULL, sc, &ihl) != 0) { + bus_release_resources(dev, pxa_gpio_spec, sc->pg_res); + device_printf(dev, "could not set up intrN\n"); + return (ENXIO); + } + + return (0); +} + +static int +pxa_gpio_intr0(void *arg) +{ + struct pxa_gpio_softc *sc; + + sc = (struct pxa_gpio_softc *)arg; + + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1); + sc->pg_intr[0] |= 1; + + return (FILTER_HANDLED); +} + +static int +pxa_gpio_intr1(void *arg) +{ + struct pxa_gpio_softc *sc; + + sc = (struct pxa_gpio_softc *)arg; + + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2); + sc->pg_intr[1] |= 2; + + return (FILTER_HANDLED); +} + +static int +pxa_gpio_intrN(void *arg) +{ + uint32_t gedr0, gedr1, gedr2; + struct pxa_gpio_softc *sc; + + sc = (struct pxa_gpio_softc *)arg; + + gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0); + gedr0 &= 0xfffffffc; + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0); + + gedr1 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1); + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, gedr1); + + gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2); + gedr2 &= 0x001fffff; + bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2); + + sc->pg_intr[0] |= gedr0; + sc->pg_intr[1] |= gedr1; + sc->pg_intr[2] |= gedr2; + + return (FILTER_HANDLED); +} + +static device_method_t pxa_gpio_methods[] = { + DEVMETHOD(device_probe, pxa_gpio_probe), + DEVMETHOD(device_attach, pxa_gpio_attach), + + {0, 0} +}; + +static driver_t pxa_gpio_driver = { + "gpio", + pxa_gpio_methods, + sizeof(struct pxa_gpio_softc), +}; + +static devclass_t pxa_gpio_devclass; + +DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0); + +#define pxagpio_reg_read(softc, reg) \ + bus_space_read_4(sc->pg_bst, sc->pg_bsh, reg) +#define pxagpio_reg_write(softc, reg, val) \ + bus_space_write_4(sc->pg_bst, sc->pg_bsh, reg, val) + +uint32_t +pxa_gpio_get_function(int gpio) +{ + struct pxa_gpio_softc *sc; + uint32_t rv, io; + + sc = pxa_gpio_softc; + + rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio); + rv = GPIO_FN(rv); + + io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)); + if (io & GPIO_BIT(gpio)) + rv |= GPIO_OUT; + + io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio)); + if (io & GPIO_BIT(gpio)) + rv |= GPIO_SET; + + return (rv); +} + +uint32_t +pxa_gpio_set_function(int gpio, uint32_t fn) +{ + struct pxa_gpio_softc *sc; + uint32_t rv, bit, oldfn; + + sc = pxa_gpio_softc; + + oldfn = pxa_gpio_get_function(gpio); + + if (GPIO_FN(fn) == GPIO_FN(oldfn) && + GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) { + /* + * The pin's function is not changing. + * For Alternate Functions and GPIO input, we can just + * return now. + * For GPIO output pins, check the initial state is + * the same. + * + * Return 'fn' instead of 'oldfn' so the caller can + * reliably detect that we didn't change anything. + * (The initial state might be different for non- + * GPIO output pins). + */ + if (!GPIO_IS_GPIO_OUT(fn) || + GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn)) + return (fn); + } + + /* + * See section 4.1.3.7 of the PXA2x0 Developer's Manual for + * the correct procedure for changing GPIO pin functions. + */ + + bit = GPIO_BIT(gpio); + + /* + * 1. Configure the correct set/clear state of the pin + */ + if (GPIO_FN_IS_SET(fn)) + pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit); + else + pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit); + + /* + * 2. Configure the pin as an input or output as appropriate + */ + rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit; + if (GPIO_FN_IS_OUT(fn)) + rv |= bit; + pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv); + + /* + * 3. Configure the pin's function + */ + bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio); + fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio); + rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit; + pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn); + + return (oldfn); +} + +/* + * GPIO "interrupt" handling. + */ + +void +pxa_gpio_mask_irq(int irq) +{ + uint32_t val; + struct pxa_gpio_softc *sc; + int gpio; + + sc = pxa_gpio_softc; + gpio = IRQ_TO_GPIO(irq); + + val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio)); + val &= ~GPIO_BIT(gpio); + pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val); +} + +void +pxa_gpio_unmask_irq(int irq) +{ + uint32_t val; + struct pxa_gpio_softc *sc; + int gpio; + + sc = pxa_gpio_softc; + gpio = IRQ_TO_GPIO(irq); + + val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio)); + val |= GPIO_BIT(gpio); + pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val); +} + +int +pxa_gpio_get_next_irq(void) +{ + struct pxa_gpio_softc *sc; + int gpio; + + sc = pxa_gpio_softc; + + if (sc->pg_intr[0] != 0) { + gpio = ffs(sc->pg_intr[0]) - 1; + sc->pg_intr[0] &= ~(1 << gpio); + return (GPIO_TO_IRQ(gpio)); + } + if (sc->pg_intr[1] != 0) { + gpio = ffs(sc->pg_intr[1]) - 1; + sc->pg_intr[1] &= ~(1 << gpio); + return (GPIO_TO_IRQ(gpio + 32)); + } + if (sc->pg_intr[2] != 0) { + gpio = ffs(sc->pg_intr[2]) - 1; + sc->pg_intr[2] &= ~(1 << gpio); + return (GPIO_TO_IRQ(gpio + 64)); + } + + return (-1); +} diff --git a/sys/arm/xscale/pxa/pxa_icu.c b/sys/arm/xscale/pxa/pxa_icu.c new file mode 100644 index 000000000000..d39fa3e09c7a --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_icu.c @@ -0,0 +1,261 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timetc.h> +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +struct pxa_icu_softc { + struct resource * pi_res[1]; + bus_space_tag_t pi_bst; + bus_space_handle_t pi_bsh; +}; + +static struct resource_spec pxa_icu_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static struct pxa_icu_softc *pxa_icu_softc = NULL; + +static int pxa_icu_probe(device_t); +static int pxa_icu_attach(device_t); + +uint32_t pxa_icu_get_icip(void); +void pxa_icu_clear_icip(int); +uint32_t pxa_icu_get_icfp(void); +void pxa_icu_clear_icfp(int); +uint32_t pxa_icu_get_icmr(void); +void pxa_icu_set_icmr(uint32_t); +uint32_t pxa_icu_get_iclr(void); +void pxa_icu_set_iclr(uint32_t); +uint32_t pxa_icu_get_icpr(void); +void pxa_icu_idle_enable(void); +void pxa_icu_idle_disable(void); + +extern uint32_t pxa_gpio_intr_flags[]; + +static int +pxa_icu_probe(device_t dev) +{ + + device_set_desc(dev, "Interrupt Controller"); + return (0); +} + +static int +pxa_icu_attach(device_t dev) +{ + int error; + struct pxa_icu_softc *sc; + + sc = (struct pxa_icu_softc *)device_get_softc(dev); + + if (pxa_icu_softc != NULL) + return (ENXIO); + pxa_icu_softc = sc; + + error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res); + if (error) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->pi_bst = rman_get_bustag(sc->pi_res[0]); + sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]); + + /* Disable all interrupts. */ + pxa_icu_set_icmr(0); + + /* Route all interrupts to IRQ rather than FIQ. */ + pxa_icu_set_iclr(0); + + /* XXX: This should move to configure_final or something. */ + enable_interrupts(PSR_I|PSR_F); + + return (0); +} + +static device_method_t pxa_icu_methods[] = { + DEVMETHOD(device_probe, pxa_icu_probe), + DEVMETHOD(device_attach, pxa_icu_attach), + + {0, 0} +}; + +static driver_t pxa_icu_driver = { + "icu", + pxa_icu_methods, + sizeof(struct pxa_icu_softc), +}; + +static devclass_t pxa_icu_devclass; + +DRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0); + +int +arm_get_next_irq(int last __unused) +{ + int irq; + + if ((irq = pxa_icu_get_icip()) != 0) { + return (ffs(irq) - 1); + } + + return (pxa_gpio_get_next_irq()); +} + +void +arm_mask_irq(uintptr_t nb) +{ + uint32_t mr; + + if (nb >= IRQ_GPIO0) { + pxa_gpio_mask_irq(nb); + return; + } + + mr = pxa_icu_get_icmr(); + mr &= ~(1 << nb); + pxa_icu_set_icmr(mr); +} + +void +arm_unmask_irq(uintptr_t nb) +{ + uint32_t mr; + + if (nb >= IRQ_GPIO0) { + pxa_gpio_unmask_irq(nb); + return; + } + + mr = pxa_icu_get_icmr(); + mr |= (1 << nb); + pxa_icu_set_icmr(mr); +} + +uint32_t +pxa_icu_get_icip(void) +{ + + return (bus_space_read_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_IP)); +} + +void +pxa_icu_clear_icip(int irq) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq)); +} + +uint32_t +pxa_icu_get_icfp(void) +{ + + return (bus_space_read_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_FP)); +} + +void +pxa_icu_clear_icfp(int irq) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq)); +} + +uint32_t +pxa_icu_get_icmr(void) +{ + + return (bus_space_read_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_MR)); +} + +void +pxa_icu_set_icmr(uint32_t val) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_MR, val); +} + +uint32_t +pxa_icu_get_iclr(void) +{ + + return (bus_space_read_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_LR)); +} + +void +pxa_icu_set_iclr(uint32_t val) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_LR, val); +} + +uint32_t +pxa_icu_get_icpr(void) +{ + + return (bus_space_read_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_PR)); +} + +void +pxa_icu_idle_enable(void) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_CR, 0x0); +} + +void +pxa_icu_idle_disable(void) +{ + + bus_space_write_4(pxa_icu_softc->pi_bst, + pxa_icu_softc->pi_bsh, ICU_CR, 0x1); +} diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c new file mode 100644 index 000000000000..e28599be9bfd --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -0,0 +1,439 @@ +/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 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 BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * machdep.c + * + * Machine dependent functions for kernel setup + * + * This file needs a lot of work. + * + * Created : 17/09/94 + */ + +#include "opt_ddb.h" +#include "opt_kstack_pages.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/imgact.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/linker.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/cons.h> +#include <sys/bio.h> +#include <sys/bus.h> +#include <sys/buf.h> +#include <sys/exec.h> +#include <sys/kdb.h> +#include <sys/msgbuf.h> +#include <sys/devmap.h> +#include <machine/reg.h> +#include <machine/cpu.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <machine/vmparam.h> +#include <machine/pcb.h> +#include <machine/undefined.h> +#include <machine/machdep.h> +#include <machine/metadata.h> +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/physmem.h> +#include <sys/reboot.h> + +#include <arm/xscale/pxa/pxareg.h> +#include <arm/xscale/pxa/pxavar.h> + +#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ +#define KERNEL_PT_IOPXS 1 +#define KERNEL_PT_BEFOREKERN 2 +#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ +#define KERNEL_PT_AFKERNEL_NUM 9 + +/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ +#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) + +struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; + +/* Physical and virtual addresses for some global pages */ + +struct pv_addr systempage; +struct pv_addr msgbufpv; +struct pv_addr irqstack; +struct pv_addr undstack; +struct pv_addr abtstack; +struct pv_addr kernelstack; +struct pv_addr minidataclean; + +static void pxa_probe_sdram(bus_space_tag_t, bus_space_handle_t, + uint32_t *, uint32_t *); + +/* Static device mappings. */ +static const struct devmap_entry pxa_devmap[] = { + /* + * Map the on-board devices up into the KVA region so we don't muck + * up user-space. + */ + { + PXA2X0_PERIPH_START + PXA2X0_PERIPH_OFFSET, + PXA2X0_PERIPH_START, + PXA250_PERIPH_END - PXA2X0_PERIPH_START, + }, + { 0, 0, 0, } +}; + +#define SDRAM_START 0xa0000000 + +extern vm_offset_t xscale_cache_clean_addr; + +void * +initarm(struct arm_boot_params *abp) +{ + struct pv_addr kernel_l1pt; + struct pv_addr dpcpu; + int loop; + u_int l1pagetable; + vm_offset_t freemempos; + vm_offset_t freemem_pt; + vm_offset_t afterkern; + vm_offset_t freemem_after; + vm_offset_t lastaddr; + int i, j; + uint32_t memsize[PXA2X0_SDRAM_BANKS], memstart[PXA2X0_SDRAM_BANKS]; + + lastaddr = parse_boot_param(abp); + arm_physmem_kernaddr = abp->abp_physaddr; + set_cpufuncs(); + pcpu_init(pcpup, 0, sizeof(struct pcpu)); + PCPU_SET(curthread, &thread0); + + /* Do basic tuning, hz etc */ + init_param1(); + + freemempos = 0xa0200000; + /* Define a macro to simplify memory allocation */ +#define valloc_pages(var, np) \ + alloc_pages((var).pv_pa, (np)); \ + (var).pv_va = (var).pv_pa + 0x20000000; + +#define alloc_pages(var, np) \ + freemempos -= (np * PAGE_SIZE); \ + (var) = freemempos; \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + + while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) + freemempos -= PAGE_SIZE; + valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { + valloc_pages(kernel_pt_table[loop], + L2_TABLE_SIZE / PAGE_SIZE); + } else { + kernel_pt_table[loop].pv_pa = freemempos + + (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * + L2_TABLE_SIZE_REAL; + kernel_pt_table[loop].pv_va = + kernel_pt_table[loop].pv_pa + 0x20000000; + } + } + freemem_pt = freemempos; + freemempos = 0xa0100000; + /* + * 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); + + /* Allocate dynamic per-cpu area. */ + valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); + dpcpu_init((void *)dpcpu.pv_va, 0); + + /* Allocate stacks for all modes */ + valloc_pages(irqstack, IRQ_STACK_SIZE); + valloc_pages(abtstack, ABT_STACK_SIZE); + valloc_pages(undstack, UND_STACK_SIZE); + valloc_pages(kernelstack, kstack_pages); + alloc_pages(minidataclean.pv_pa, 1); + valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); + /* + * Allocate memory for the l1 and l2 page tables. The scheme to avoid + * wasting memory by allocating the l1pt on the first 16k memory was + * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for + * this to work (which is supposed to be the case). + */ + + /* + * 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 + */ + l1pagetable = kernel_l1pt.pv_va; + + /* Map the L2 pages tables in the L1 page table */ + pmap_link_l2pt(l1pagetable, rounddown2(ARM_VECTORS_HIGH, 0x00100000), + &kernel_pt_table[KERNEL_PT_SYS]); +#if 0 /* XXXBJR: What is this? Don't know if there's an analogue. */ + pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, + &kernel_pt_table[KERNEL_PT_IOPXS]); +#endif + pmap_link_l2pt(l1pagetable, KERNBASE, + &kernel_pt_table[KERNEL_PT_BEFOREKERN]); + pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000, + 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000, + rounddown2(((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE, L1_S_SIZE), + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + freemem_after = rounddown2((int)lastaddr + PAGE_SIZE, PAGE_SIZE); + afterkern = round_page(rounddown2((vm_offset_t)lastaddr + L1_S_SIZE, L1_S_SIZE)); + for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { + pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, + &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); + } + pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + + /* Map the Mini-Data cache clean area. */ + xscale_setup_minidata(l1pagetable, afterkern, + minidataclean.pv_pa); + + /* Map the vector page. */ + pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + devmap_bootstrap(l1pagetable, pxa_devmap); + + /* + * Give the XScale global cache clean code an appropriately + * sized chunk of unmapped VA space starting at 0xff000000 + * (our device mappings end before this address). + */ + xscale_cache_clean_addr = 0xff000000U; + + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); + cpu_setttb(kernel_l1pt.pv_pa); + cpu_tlb_flushID(); + cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); + + /* + * 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. + */ + set_stackptrs(0); + + /* + * We must now clean the cache again.... + * Cleaning may be done by reading new data to displace any + * dirty data in the cache. This will have happened in cpu_setttb() + * but since we are boot strapping the addresses used for the read + * may have just been remapped and thus the cache could be out + * of sync. A re-clean after the switch will cure this. + * After booting there are no gross relocations of the kernel thus + * this problem will not occur after initarm(). + */ + cpu_idcache_wbinv_all(); + cpu_setup(); + + /* + * Sort out bus_space for on-board devices. + */ + pxa_obio_tag_init(); + + /* + * Fetch the SDRAM start/size from the PXA2X0 SDRAM configration + * registers. + */ + pxa_probe_sdram(obio_tag, PXA2X0_MEMCTL_BASE, memstart, memsize); + + /* Fire up consoles. */ + cninit(); + + undefined_init(); + + init_proc0(kernelstack.pv_va); + + /* Enable MMU, I-cache, D-cache, write buffer. */ + arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); + + pmap_curmaxkvaddr = afterkern + PAGE_SIZE; + vm_max_kernel_address = 0xe0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); + msgbufp = (void*)msgbufpv.pv_va; + msgbufinit(msgbufp, msgbufsize); + mutex_init(); + + /* + * Add the physical ram we have available. + * + * Exclude the kernel (and all the things we allocated which immediately + * follow the kernel) from the VM allocation pool but not from crash + * dumps. virtual_avail is a global variable which tracks the kva we've + * "allocated" while setting up pmaps. + * + * Prepare the list of physical memory available to the vm subsystem. + */ + for (j = 0; j < PXA2X0_SDRAM_BANKS; j++) { + if (memsize[j] > 0) + arm_physmem_hardware_region(memstart[j], memsize[j]); + } + arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - + freemem_pt, EXFLAG_NOALLOC); + arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - + freemempos, EXFLAG_NOALLOC); + arm_physmem_exclude_region(abp->abp_physaddr, + virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); + arm_physmem_init_kernel_globals(); + + init_param2(physmem); + kdb_init(); + return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - + sizeof(struct pcb))); +} + +static void +pxa_probe_sdram(bus_space_tag_t bst, bus_space_handle_t bsh, + uint32_t *memstart, uint32_t *memsize) +{ + uint32_t mdcnfg, dwid, dcac, drac, dnb; + int i; + + mdcnfg = bus_space_read_4(bst, bsh, MEMCTL_MDCNFG); + + /* + * Scan all 4 SDRAM banks + */ + for (i = 0; i < PXA2X0_SDRAM_BANKS; i++) { + memstart[i] = 0; + memsize[i] = 0; + + switch (i) { + case 0: + case 1: + if ((i == 0 && (mdcnfg & MDCNFG_DE0) == 0) || + (i == 1 && (mdcnfg & MDCNFG_DE1) == 0)) + continue; + dwid = mdcnfg >> MDCNFD_DWID01_SHIFT; + dcac = mdcnfg >> MDCNFD_DCAC01_SHIFT; + drac = mdcnfg >> MDCNFD_DRAC01_SHIFT; + dnb = mdcnfg >> MDCNFD_DNB01_SHIFT; + break; + + case 2: + case 3: + if ((i == 2 && (mdcnfg & MDCNFG_DE2) == 0) || + (i == 3 && (mdcnfg & MDCNFG_DE3) == 0)) + continue; + dwid = mdcnfg >> MDCNFD_DWID23_SHIFT; + dcac = mdcnfg >> MDCNFD_DCAC23_SHIFT; + drac = mdcnfg >> MDCNFD_DRAC23_SHIFT; + dnb = mdcnfg >> MDCNFD_DNB23_SHIFT; + break; + default: + panic("pxa_probe_sdram: impossible"); + } + + dwid = 2 << (1 - (dwid & MDCNFD_DWID_MASK)); /* 16/32 width */ + dcac = 1 << ((dcac & MDCNFD_DCAC_MASK) + 8); /* 8-11 columns */ + drac = 1 << ((drac & MDCNFD_DRAC_MASK) + 11); /* 11-13 rows */ + dnb = 2 << (dnb & MDCNFD_DNB_MASK); /* # of banks */ + + memsize[i] = dwid * dcac * drac * dnb; + memstart[i] = PXA2X0_SDRAM0_START + + (i * PXA2X0_SDRAM_BANK_SIZE); + } +} + +#define TIMER_FREQUENCY 3686400 +#define UNIMPLEMENTED panic("%s: unimplemented", __func__) + +/* XXXBJR: Belongs with DELAY in a timer.c of some sort. */ +void +cpu_startprofclock(void) +{ + UNIMPLEMENTED; +} + +void +cpu_stopprofclock(void) +{ + UNIMPLEMENTED; +} + +static struct arm32_dma_range pxa_range = { + .dr_sysbase = 0, + .dr_busbase = 0, + .dr_len = ~0u, +}; + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + return (&pxa_range); +} + +int +bus_dma_get_range_nb(void) +{ + + return (1); +} diff --git a/sys/arm/xscale/pxa/pxa_obio.c b/sys/arm/xscale/pxa/pxa_obio.c new file mode 100644 index 000000000000..e084a3b49471 --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_obio.c @@ -0,0 +1,399 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +static void pxa_identify(driver_t *, device_t); +static int pxa_probe(device_t); +static int pxa_attach(device_t); + +static int pxa_print_child(device_t, device_t); + +static int pxa_setup_intr(device_t, device_t, struct resource *, int, + driver_filter_t *, driver_intr_t *, void *, void **); +static int pxa_read_ivar(device_t, device_t, int, uintptr_t *); + +static struct resource_list * pxa_get_resource_list(device_t, device_t); +static struct resource * pxa_alloc_resource(device_t, device_t, int, + int *, rman_res_t, rman_res_t, rman_res_t, u_int); +static int pxa_release_resource(device_t, device_t, int, + int, struct resource *); +static int pxa_activate_resource(device_t, device_t, + int, int, struct resource *); + +static struct resource * pxa_alloc_gpio_irq(device_t, device_t, int, + int *, rman_res_t, rman_res_t, rman_res_t, u_int); + +struct obio_device { + const char *od_name; + u_long od_base; + u_long od_size; + u_int od_irqs[5]; + struct resource_list od_resources; +}; + +static struct obio_device obio_devices[] = { + { "icu", PXA2X0_INTCTL_BASE, PXA2X0_INTCTL_SIZE, { 0 } }, + { "timer", PXA2X0_OST_BASE, PXA2X0_OST_SIZE, { PXA2X0_INT_OST0, PXA2X0_INT_OST1, PXA2X0_INT_OST2, PXA2X0_INT_OST3, 0 } }, + { "dmac", PXA2X0_DMAC_BASE, PXA2X0_DMAC_SIZE, { PXA2X0_INT_DMA, 0 } }, + { "gpio", PXA2X0_GPIO_BASE, PXA250_GPIO_SIZE, { PXA2X0_INT_GPIO0, PXA2X0_INT_GPIO1, PXA2X0_INT_GPION, 0 } }, + { "uart", PXA2X0_FFUART_BASE, PXA2X0_FFUART_SIZE, { PXA2X0_INT_FFUART, 0 } }, + { "uart", PXA2X0_BTUART_BASE, PXA2X0_BTUART_SIZE, { PXA2X0_INT_BTUART, 0 } }, + { "uart", PXA2X0_STUART_BASE, PXA2X0_STUART_SIZE, { PXA2X0_INT_STUART, 0 } }, + { "uart", PXA2X0_HWUART_BASE, PXA2X0_HWUART_SIZE, { PXA2X0_INT_HWUART, 0 } }, + { "smi", PXA2X0_CS0_START, PXA2X0_CS_SIZE * 6, { 0 } }, + { NULL, 0, 0, { 0 } } +}; + +void +pxa_identify(driver_t *driver, device_t parent) +{ + + BUS_ADD_CHILD(parent, 0, "pxa", 0); +} + +int +pxa_probe(device_t dev) +{ + + device_set_desc(dev, "XScale PXA On-board IO"); + return (BUS_PROBE_NOWILDCARD); +} + +int +pxa_attach(device_t dev) +{ + struct obio_softc *sc; + struct obio_device *od; + int i; + device_t child; + + sc = device_get_softc(dev); + + sc->obio_bst = obio_tag; + + sc->obio_mem.rm_type = RMAN_ARRAY; + sc->obio_mem.rm_descr = "PXA2X0 OBIO Memory"; + if (rman_init(&sc->obio_mem) != 0) + panic("pxa_attach: failed to init obio mem rman"); + if (rman_manage_region(&sc->obio_mem, 0, PXA250_PERIPH_END) != 0) + panic("pxa_attach: failed to set up obio mem rman"); + + sc->obio_irq.rm_type = RMAN_ARRAY; + sc->obio_irq.rm_descr = "PXA2X0 OBIO IRQ"; + if (rman_init(&sc->obio_irq) != 0) + panic("pxa_attach: failed to init obio irq rman"); + if (rman_manage_region(&sc->obio_irq, 0, 31) != 0) + panic("pxa_attach: failed to set up obio irq rman (main irqs)"); + if (rman_manage_region(&sc->obio_irq, IRQ_GPIO0, IRQ_GPIO_MAX) != 0) + panic("pxa_attach: failed to set up obio irq rman (gpio irqs)"); + + for (od = obio_devices; od->od_name != NULL; od++) { + resource_list_init(&od->od_resources); + + resource_list_add(&od->od_resources, SYS_RES_MEMORY, 0, + od->od_base, od->od_base + od->od_size, od->od_size); + + for (i = 0; od->od_irqs[i] != 0; i++) { + resource_list_add(&od->od_resources, SYS_RES_IRQ, i, + od->od_irqs[i], od->od_irqs[i], 1); + } + + child = device_add_child(dev, od->od_name, -1); + device_set_ivars(child, od); + } + + bus_generic_probe(dev); + bus_generic_attach(dev); + + return (0); +} + +static int +pxa_print_child(device_t dev, device_t child) +{ + struct obio_device *od; + int retval; + + od = (struct obio_device *)device_get_ivars(child); + if (od == NULL) + panic("Unknown device on pxa0"); + + retval = 0; + + retval += bus_print_child_header(dev, child); + + retval += resource_list_print_type(&od->od_resources, "at mem", + SYS_RES_MEMORY, "0x%08jx"); + retval += resource_list_print_type(&od->od_resources, "irq", + SYS_RES_IRQ, "%jd"); + + retval += bus_print_child_footer(dev, child); + + return (retval); +} + +static int +pxa_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, + driver_filter_t *filter, driver_intr_t *ithread, void *arg, void **cookiep) +{ + struct obio_softc *sc; + int error; + + sc = (struct obio_softc *)device_get_softc(dev); + + error = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, + filter, ithread, arg, cookiep); + if (error) + return (error); + return (0); +} + +static int +pxa_teardown_intr(device_t dev, device_t child, struct resource *ires, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, ires, cookie));} + +static int +pxa_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct obio_device *od; + + od = (struct obio_device *)device_get_ivars(child); + + switch (which) { + case PXA_IVAR_BASE: + *((u_long *)result) = od->od_base; + break; + + default: + return (ENOENT); + } + + return (0); +} + +static struct resource_list * +pxa_get_resource_list(device_t dev, device_t child) +{ + struct obio_device *od; + + od = (struct obio_device *)device_get_ivars(child); + + if (od == NULL) + return (NULL); + + return (&od->od_resources); +} + +static struct resource * +pxa_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct obio_softc *sc; + struct obio_device *od; + struct resource *rv; + struct resource_list *rl; + struct resource_list_entry *rle; + struct rman *rm; + int needactivate; + + sc = (struct obio_softc *)device_get_softc(dev); + od = (struct obio_device *)device_get_ivars(child); + rl = &od->od_resources; + + rle = resource_list_find(rl, type, *rid); + if (rle == NULL) { + /* We can allocate GPIO-based IRQs lazily. */ + if (type == SYS_RES_IRQ) + return (pxa_alloc_gpio_irq(dev, child, type, rid, + start, end, count, flags)); + return (NULL); + } + if (rle->res != NULL) + panic("pxa_alloc_resource: resource is busy"); + + switch (type) { + case SYS_RES_IRQ: + rm = &sc->obio_irq; + break; + + case SYS_RES_MEMORY: + rm = &sc->obio_mem; + break; + + default: + return (NULL); + } + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + rv = rman_reserve_resource(rm, rle->start, rle->end, rle->count, flags, + child); + if (rv == NULL) + return (NULL); + rle->res = rv; + rman_set_rid(rv, *rid); + if (type == SYS_RES_MEMORY) { + rman_set_bustag(rv, sc->obio_bst); + rman_set_bushandle(rv, rle->start); + } + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +pxa_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct obio_device *od; + struct resource_list *rl; + struct resource_list_entry *rle; + + od = (struct obio_device *)device_get_ivars(child); + rl = &od->od_resources; + + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rle = resource_list_find(rl, type, rid); + + if (!rle) + panic("pxa_release_resource: can't find resource"); + if (!rle->res) + panic("pxa_release_resource: resource entry is not busy"); + + rman_release_resource(rle->res); + rle->res = NULL; + + return (0); +} + +static int +pxa_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + + return (rman_activate_resource(r)); +} + +static device_method_t pxa_methods[] = { + DEVMETHOD(device_identify, pxa_identify), + DEVMETHOD(device_probe, pxa_probe), + DEVMETHOD(device_attach, pxa_attach), + + DEVMETHOD(bus_print_child, pxa_print_child), + + DEVMETHOD(bus_read_ivar, pxa_read_ivar), + DEVMETHOD(bus_setup_intr, pxa_setup_intr), + DEVMETHOD(bus_teardown_intr, pxa_teardown_intr), + + DEVMETHOD(bus_get_resource_list, pxa_get_resource_list), + DEVMETHOD(bus_alloc_resource, pxa_alloc_resource), + DEVMETHOD(bus_release_resource, pxa_release_resource), + DEVMETHOD(bus_activate_resource, pxa_activate_resource), + + {0, 0} +}; + +static driver_t pxa_driver = { + "pxa", + pxa_methods, + sizeof(struct obio_softc), +}; + +static devclass_t pxa_devclass; + +DRIVER_MODULE(pxa, nexus, pxa_driver, pxa_devclass, 0, 0); + +static struct resource * +pxa_alloc_gpio_irq(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct obio_softc *sc; + struct obio_device *od; + struct resource_list *rl; + struct resource_list_entry *rle; + struct resource *rv; + struct rman *rm; + int needactivate; + + sc = device_get_softc(dev); + od = device_get_ivars(child); + rl = &od->od_resources; + rm = &sc->obio_irq; + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) + return (NULL); + + resource_list_add(rl, type, *rid, start, end, count); + rle = resource_list_find(rl, type, *rid); + if (rle == NULL) + panic("pxa_alloc_gpio_irq: unexpectedly can't find resource"); + + rle->res = rv; + rle->start = rman_get_start(rv); + rle->end = rman_get_end(rv); + rle->count = count; + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + + if (bootverbose) + device_printf(dev, "lazy allocation of irq %jd for %s\n", + start, device_get_nameunit(child)); + + return (rv); +} diff --git a/sys/arm/xscale/pxa/pxa_smi.c b/sys/arm/xscale/pxa/pxa_smi.c new file mode 100644 index 000000000000..569405e664d8 --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_smi.c @@ -0,0 +1,356 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timetc.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +static MALLOC_DEFINE(M_PXASMI, "PXA SMI", + "Data for static memory interface devices."); + +struct pxa_smi_softc { + struct resource *ps_res[1]; + struct rman ps_mem; + bus_space_tag_t ps_bst; + bus_addr_t ps_base; +}; + +struct smi_ivars { + struct resource_list smid_resources; + bus_addr_t smid_mem; +}; + +static struct resource_spec pxa_smi_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int pxa_smi_probe(device_t); +static int pxa_smi_attach(device_t); + +static int pxa_smi_print_child(device_t, device_t); + +static int pxa_smi_read_ivar(device_t, device_t, int, uintptr_t *); + +static struct resource * pxa_smi_alloc_resource(device_t, device_t, + int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); +static int pxa_smi_release_resource(device_t, device_t, + int, int, struct resource *); +static int pxa_smi_activate_resource(device_t, device_t, + int, int, struct resource *); + +static void pxa_smi_add_device(device_t, const char *, int); + +static int +pxa_smi_probe(device_t dev) +{ + + if (resource_disabled("smi", device_get_unit(dev))) + return (ENXIO); + + device_set_desc(dev, "Static Memory Interface"); + return (0); +} + +static int +pxa_smi_attach(device_t dev) +{ + int error, i, dunit; + const char *dname; + struct pxa_smi_softc *sc; + + sc = (struct pxa_smi_softc *)device_get_softc(dev); + + error = bus_alloc_resources(dev, pxa_smi_spec, sc->ps_res); + if (error) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->ps_mem.rm_type = RMAN_ARRAY; + sc->ps_mem.rm_descr = device_get_nameunit(dev); + if (rman_init(&sc->ps_mem) != 0) + panic("pxa_smi_attach: failed to init mem rman"); + if (rman_manage_region(&sc->ps_mem, 0, PXA2X0_CS_SIZE * 6) != 0) + panic("pxa_smi_attach: failed ot set up mem rman"); + + sc->ps_bst = base_tag; + sc->ps_base = rman_get_start(sc->ps_res[0]); + + i = 0; + while (resource_find_match(&i, &dname, &dunit, "at", + device_get_nameunit(dev)) == 0) { + pxa_smi_add_device(dev, dname, dunit); + } + + bus_generic_probe(dev); + bus_generic_attach(dev); + + return (0); +} + +static int +pxa_smi_print_child(device_t dev, device_t child) +{ + struct smi_ivars *smid; + int retval; + + smid = (struct smi_ivars *)device_get_ivars(child); + if (smid == NULL) { + device_printf(dev, "unknown device: %s\n", + device_get_nameunit(child)); + return (0); + } + + retval = 0; + + retval += bus_print_child_header(dev, child); + + retval += resource_list_print_type(&smid->smid_resources, "at mem", + SYS_RES_MEMORY, "%#jx"); + retval += resource_list_print_type(&smid->smid_resources, "irq", + SYS_RES_IRQ, "%jd"); + + retval += bus_print_child_footer(dev, child); + + return (retval); +} + +static int +pxa_smi_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct pxa_smi_softc *sc; + struct smi_ivars *smid; + + sc = device_get_softc(dev); + smid = device_get_ivars(child); + + switch (which) { + case SMI_IVAR_PHYSBASE: + *((bus_addr_t *)result) = smid->smid_mem; + break; + + default: + return (ENOENT); + } + + return (0); +} + +static struct resource * +pxa_smi_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct pxa_smi_softc *sc; + struct smi_ivars *smid; + struct resource *rv; + struct resource_list *rl; + struct resource_list_entry *rle; + int needactivate; + + sc = (struct pxa_smi_softc *)device_get_softc(dev); + smid = (struct smi_ivars *)device_get_ivars(child); + rl = &smid->smid_resources; + + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rle = resource_list_find(rl, type, *rid); + if (rle == NULL) + return (NULL); + if (rle->res != NULL) + panic("pxa_smi_alloc_resource: resource is busy"); + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + switch (type) { + case SYS_RES_MEMORY: + rv = rman_reserve_resource(&sc->ps_mem, rle->start, rle->end, + rle->count, flags, child); + if (rv == NULL) + return (NULL); + rle->res = rv; + rman_set_rid(rv, *rid); + rman_set_bustag(rv, sc->ps_bst); + rman_set_bushandle(rv, rle->start); + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); + } + } + + break; + + case SYS_RES_IRQ: + rv = bus_alloc_resource(dev, type, rid, rle->start, rle->end, + rle->count, flags); + if (rv == NULL) + return (NULL); + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + bus_release_resource(dev, type, *rid, rv); + return (NULL); + } + } + + break; + + default: + return (NULL); + } + + return (rv); +} + +static int +pxa_smi_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct smi_ivars *smid; + struct resource_list *rl; + struct resource_list_entry *rle; + + if (type == SYS_RES_IRQ) + return (bus_release_resource(dev, SYS_RES_IRQ, rid, r)); + + smid = (struct smi_ivars *)device_get_ivars(child); + rl = &smid->smid_resources; + + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rle = resource_list_find(rl, type, rid); + if (rle == NULL) + panic("pxa_smi_release_resource: can't find resource"); + if (rle->res == NULL) + panic("pxa_smi_release_resource: resource entry not busy"); + + rman_release_resource(rle->res); + rle->res = NULL; + + return (0); +} + +static int +pxa_smi_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct pxa_smi_softc *sc; + + sc = (struct pxa_smi_softc *)device_get_softc(dev); + + if (type == SYS_RES_IRQ) + return (bus_activate_resource(dev, SYS_RES_IRQ, rid, r)); + + rman_set_bushandle(r, (bus_space_handle_t)pmap_mapdev(rman_get_start(r), + rman_get_size(r))); + return (rman_activate_resource(r)); +} + +static device_method_t pxa_smi_methods[] = { + DEVMETHOD(device_probe, pxa_smi_probe), + DEVMETHOD(device_attach, pxa_smi_attach), + + DEVMETHOD(bus_print_child, pxa_smi_print_child), + + DEVMETHOD(bus_read_ivar, pxa_smi_read_ivar), + + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + + DEVMETHOD(bus_alloc_resource, pxa_smi_alloc_resource), + DEVMETHOD(bus_release_resource, pxa_smi_release_resource), + DEVMETHOD(bus_activate_resource, pxa_smi_activate_resource), + + {0, 0} +}; + +static driver_t pxa_smi_driver = { + "smi", + pxa_smi_methods, + sizeof(struct pxa_smi_softc), +}; + +static devclass_t pxa_smi_devclass; + +DRIVER_MODULE(smi, pxa, pxa_smi_driver, pxa_smi_devclass, 0, 0); + +static void +pxa_smi_add_device(device_t dev, const char *name, int unit) +{ + device_t child; + int start, count; + struct smi_ivars *ivars; + + ivars = (struct smi_ivars *)malloc( + sizeof(struct smi_ivars), M_PXASMI, M_WAITOK); + + child = device_add_child(dev, name, unit); + if (child == NULL) { + free(ivars, M_PXASMI); + return; + } + + device_set_ivars(child, ivars); + resource_list_init(&ivars->smid_resources); + + start = 0; + count = 0; + resource_int_value(name, unit, "mem", &start); + resource_int_value(name, unit, "size", &count); + if (start > 0 || count > 0) { + resource_list_add(&ivars->smid_resources, SYS_RES_MEMORY, 0, + start, start + count, count); + ivars->smid_mem = (bus_addr_t)start; + } + + start = -1; + count = 0; + resource_int_value(name, unit, "irq", &start); + if (start > -1) + resource_list_add(&ivars->smid_resources, SYS_RES_IRQ, 0, start, + start, 1); + + if (resource_disabled(name, unit)) + device_disable(child); +} diff --git a/sys/arm/xscale/pxa/pxa_space.c b/sys/arm/xscale/pxa/pxa_space.c new file mode 100644 index 000000000000..bb235c935b29 --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_space.c @@ -0,0 +1,267 @@ +/* $NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * bus_space functions for PXA devices + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +#include <arm/xscale/pxa/pxareg.h> +#include <arm/xscale/pxa/pxavar.h> + +static MALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA"); + +/* Prototypes for all the bus_space structure functions */ +bs_protos(generic); +bs_protos(pxa); + +/* + * The obio bus space tag. This is constant for all instances, so + * we never have to explicitly "create" it. + */ +struct bus_space _base_tag = { + /* cookie */ + .bs_privdata = NULL, + + /* mapping/unmapping */ + .bs_map = generic_bs_map, + .bs_unmap = generic_bs_unmap, + .bs_subregion = generic_bs_subregion, + + /* allocation/deallocation */ + .bs_alloc = generic_bs_alloc, + .bs_free = generic_bs_free, + + /* barrier */ + .bs_barrier = generic_bs_barrier, + + /* read (single) */ + .bs_r_1 = pxa_bs_r_1, + .bs_r_2 = pxa_bs_r_2, + .bs_r_4 = pxa_bs_r_4, + .bs_r_8 = BS_UNIMPLEMENTED, + + /* read multiple */ + .bs_rm_1 = pxa_bs_rm_1, + .bs_rm_2 = pxa_bs_rm_2, + .bs_rm_4 = BS_UNIMPLEMENTED, + .bs_rm_8 = BS_UNIMPLEMENTED, + + /* read region */ + .bs_rr_1 = pxa_bs_rr_1, + .bs_rr_2 = BS_UNIMPLEMENTED, + .bs_rr_4 = BS_UNIMPLEMENTED, + .bs_rr_8 = BS_UNIMPLEMENTED, + + /* write (single) */ + .bs_w_1 = pxa_bs_w_1, + .bs_w_2 = pxa_bs_w_2, + .bs_w_4 = pxa_bs_w_4, + .bs_w_8 = BS_UNIMPLEMENTED, + + /* write multiple */ + .bs_wm_1 = pxa_bs_wm_1, + .bs_wm_2 = pxa_bs_wm_2, + .bs_wm_4 = BS_UNIMPLEMENTED, + .bs_wm_8 = BS_UNIMPLEMENTED, + + /* write region */ + .bs_wr_1 = BS_UNIMPLEMENTED, + .bs_wr_2 = BS_UNIMPLEMENTED, + .bs_wr_4 = BS_UNIMPLEMENTED, + .bs_wr_8 = BS_UNIMPLEMENTED, + + /* set multiple */ + .bs_sm_1 = BS_UNIMPLEMENTED, + .bs_sm_2 = BS_UNIMPLEMENTED, + .bs_sm_4 = BS_UNIMPLEMENTED, + .bs_sm_8 = BS_UNIMPLEMENTED, + + /* set region */ + .bs_sr_1 = BS_UNIMPLEMENTED, + .bs_sr_2 = BS_UNIMPLEMENTED, + .bs_sr_4 = BS_UNIMPLEMENTED, + .bs_sr_8 = BS_UNIMPLEMENTED, + + /* copy */ + .bs_c_1 = BS_UNIMPLEMENTED, + .bs_c_2 = BS_UNIMPLEMENTED, + .bs_c_4 = BS_UNIMPLEMENTED, + .bs_c_8 = BS_UNIMPLEMENTED, + + /* read stream (single) */ + .bs_r_1_s = BS_UNIMPLEMENTED, + .bs_r_2_s = BS_UNIMPLEMENTED, + .bs_r_4_s = BS_UNIMPLEMENTED, + .bs_r_8_s = BS_UNIMPLEMENTED, + + /* read multiple stream */ + .bs_rm_1_s = BS_UNIMPLEMENTED, + .bs_rm_2_s = BS_UNIMPLEMENTED, + .bs_rm_4_s = BS_UNIMPLEMENTED, + .bs_rm_8_s = BS_UNIMPLEMENTED, + + /* read region stream */ + .bs_rr_1_s = BS_UNIMPLEMENTED, + .bs_rr_2_s = BS_UNIMPLEMENTED, + .bs_rr_4_s = BS_UNIMPLEMENTED, + .bs_rr_8_s = BS_UNIMPLEMENTED, + + /* write stream (single) */ + .bs_w_1_s = BS_UNIMPLEMENTED, + .bs_w_2_s = BS_UNIMPLEMENTED, + .bs_w_4_s = BS_UNIMPLEMENTED, + .bs_w_8_s = BS_UNIMPLEMENTED, + + /* write multiple stream */ + .bs_wm_1_s = BS_UNIMPLEMENTED, + .bs_wm_2_s = BS_UNIMPLEMENTED, + .bs_wm_4_s = BS_UNIMPLEMENTED, + .bs_wm_8_s = BS_UNIMPLEMENTED, + + /* write region stream */ + .bs_wr_1_s = BS_UNIMPLEMENTED, + .bs_wr_2_s = BS_UNIMPLEMENTED, + .bs_wr_4_s = BS_UNIMPLEMENTED, + .bs_wr_8_s = BS_UNIMPLEMENTED, +}; + +static struct bus_space _obio_tag; + +bus_space_tag_t base_tag = &_base_tag; +bus_space_tag_t obio_tag = NULL; + +void +pxa_obio_tag_init(void) +{ + + bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space)); + _obio_tag.bs_privdata = (void *)PXA2X0_PERIPH_OFFSET; + obio_tag = &_obio_tag; +} + +bus_space_tag_t +pxa_bus_tag_alloc(bus_addr_t offset) +{ + struct bus_space *tag; + + tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG, + M_WAITOK); + + bcopy(&_base_tag, tag, sizeof(struct bus_space)); + tag->bs_privdata = (void *)offset; + + return ((bus_space_tag_t)tag); +} + + +#define READ_SINGLE(type, proto, base) \ + type \ + proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset) \ + { \ + bus_addr_t tag_offset; \ + type value; \ + tag_offset = (bus_addr_t)tag->bs_privdata; \ + value = base(NULL, bsh + tag_offset, offset); \ + return (value); \ + } + +READ_SINGLE(u_int8_t, pxa_bs_r_1, generic_bs_r_1) +READ_SINGLE(u_int16_t, pxa_bs_r_2, generic_bs_r_2) +READ_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4) + +#undef READ_SINGLE + +#define WRITE_SINGLE(type, proto, base) \ + void \ + proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \ + type value) \ + { \ + bus_addr_t tag_offset; \ + tag_offset = (bus_addr_t)tag->bs_privdata; \ + base(NULL, bsh + tag_offset, offset, value); \ + } + +WRITE_SINGLE(u_int8_t, pxa_bs_w_1, generic_bs_w_1) +WRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_bs_w_2) +WRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4) + +#undef WRITE_SINGLE + +#define READ_MULTI(type, proto, base) \ + void \ + proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \ + type *dest, bus_size_t count) \ + { \ + bus_addr_t tag_offset; \ + tag_offset = (bus_addr_t)tag->bs_privdata; \ + base(NULL, bsh + tag_offset, offset, dest, count); \ + } + +READ_MULTI(u_int8_t, pxa_bs_rm_1, generic_bs_rm_1) +READ_MULTI(u_int16_t, pxa_bs_rm_2, generic_bs_rm_2) + +READ_MULTI(u_int8_t, pxa_bs_rr_1, generic_bs_rr_1) + +#undef READ_MULTI + +#define WRITE_MULTI(type, proto, base) \ + void \ + proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \ + const type *src, bus_size_t count) \ + { \ + bus_addr_t tag_offset; \ + tag_offset = (bus_addr_t)tag->bs_privdata; \ + base(NULL, bsh + tag_offset, offset, src, count); \ + } + +WRITE_MULTI(u_int8_t, pxa_bs_wm_1, generic_bs_wm_1) +WRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_bs_wm_2) + +#undef WRITE_MULTI diff --git a/sys/arm/xscale/pxa/pxa_timer.c b/sys/arm/xscale/pxa/pxa_timer.c new file mode 100644 index 000000000000..b000f0271d96 --- /dev/null +++ b/sys/arm/xscale/pxa/pxa_timer.c @@ -0,0 +1,322 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timetc.h> +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <machine/intr.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +#define PXA_TIMER_FREQUENCY 3686400 +#define PXA_TIMER_TICK (PXA_TIMER_FREQUENCY / hz) + +struct pxa_timer_softc { + struct resource * pt_res[5]; + bus_space_tag_t pt_bst; + bus_space_handle_t pt_bsh; +}; + +static struct resource_spec pxa_timer_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 3, RF_ACTIVE }, + { -1, 0 } +}; + +static struct pxa_timer_softc *timer_softc = NULL; + +static int pxa_timer_probe(device_t); +static int pxa_timer_attach(device_t); + +static driver_filter_t pxa_hardclock; + +static unsigned pxa_timer_get_timecount(struct timecounter *); + +uint32_t pxa_timer_get_osmr(int); +void pxa_timer_set_osmr(int, uint32_t); +uint32_t pxa_timer_get_oscr(void); +void pxa_timer_set_oscr(uint32_t); +uint32_t pxa_timer_get_ossr(void); +void pxa_timer_clear_ossr(uint32_t); +void pxa_timer_watchdog_enable(void); +void pxa_timer_watchdog_disable(void); +void pxa_timer_interrupt_enable(int); +void pxa_timer_interrupt_disable(int); + +static struct timecounter pxa_timer_timecounter = { + .tc_get_timecount = pxa_timer_get_timecount, + .tc_name = "OS Timer", + .tc_frequency = PXA_TIMER_FREQUENCY, + .tc_counter_mask = ~0u, + .tc_quality = 1000, +}; + +static int +pxa_timer_probe(device_t dev) +{ + + device_set_desc(dev, "OS Timer"); + return (0); +} + +static int +pxa_timer_attach(device_t dev) +{ + int error; + void *ihl; + struct pxa_timer_softc *sc; + + sc = (struct pxa_timer_softc *)device_get_softc(dev); + + if (timer_softc != NULL) + return (ENXIO); + + error = bus_alloc_resources(dev, pxa_timer_spec, sc->pt_res); + if (error) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->pt_bst = rman_get_bustag(sc->pt_res[0]); + sc->pt_bsh = rman_get_bushandle(sc->pt_res[0]); + + timer_softc = sc; + + pxa_timer_interrupt_disable(-1); + pxa_timer_watchdog_disable(); + + if (bus_setup_intr(dev, sc->pt_res[1], INTR_TYPE_CLK, + pxa_hardclock, NULL, NULL, &ihl) != 0) { + bus_release_resources(dev, pxa_timer_spec, sc->pt_res); + device_printf(dev, "could not setup hardclock interrupt\n"); + return (ENXIO); + } + + return (0); +} + +static int +pxa_hardclock(void *arg) +{ + struct trapframe *frame; + + frame = (struct trapframe *)arg; + + /* Clear the interrupt */ + pxa_timer_clear_ossr(OST_SR_CH0); + + /* Schedule next tick */ + pxa_timer_set_osmr(0, pxa_timer_get_oscr() + PXA_TIMER_TICK); + + /* Do what we came here for */ + hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); + + return (FILTER_HANDLED); +} + +static device_method_t pxa_timer_methods[] = { + DEVMETHOD(device_probe, pxa_timer_probe), + DEVMETHOD(device_attach, pxa_timer_attach), + + {0, 0} +}; + +static driver_t pxa_timer_driver = { + "timer", + pxa_timer_methods, + sizeof(struct pxa_timer_softc), +}; + +static devclass_t pxa_timer_devclass; + +DRIVER_MODULE(pxatimer, pxa, pxa_timer_driver, pxa_timer_devclass, 0, 0); + +static unsigned +pxa_timer_get_timecount(struct timecounter *tc) +{ + + return (pxa_timer_get_oscr()); +} + +void +cpu_initclocks(void) +{ + + pxa_timer_set_oscr(0); + pxa_timer_set_osmr(0, PXA_TIMER_TICK); + pxa_timer_interrupt_enable(0); + + tc_init(&pxa_timer_timecounter); +} + +void +cpu_reset(void) +{ + uint32_t val; + + (void)disable_interrupts(PSR_I|PSR_F); + + val = pxa_timer_get_oscr(); + val += PXA_TIMER_FREQUENCY; + pxa_timer_set_osmr(3, val); + pxa_timer_watchdog_enable(); + + for(;;); +} + +void +DELAY(int usec) +{ + uint32_t val; + + if (timer_softc == NULL) { + for (; usec > 0; usec--) + for (val = 100; val > 0; val--) + ; + return; + } + TSENTER(); + + val = pxa_timer_get_oscr(); + val += (PXA_TIMER_FREQUENCY * usec) / 1000000; + while (pxa_timer_get_oscr() <= val); + TSEXIT(); +} + +uint32_t +pxa_timer_get_osmr(int which) +{ + + return (bus_space_read_4(timer_softc->pt_bst, + timer_softc->pt_bsh, which * 0x4)); +} + +void +pxa_timer_set_osmr(int which, uint32_t val) +{ + + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, which * 0x4, val); +} + +uint32_t +pxa_timer_get_oscr(void) +{ + + return (bus_space_read_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_CR)); +} + +void +pxa_timer_set_oscr(uint32_t val) +{ + + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_CR, val); +} + +uint32_t +pxa_timer_get_ossr(void) +{ + + return (bus_space_read_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_SR)); +} + +void +pxa_timer_clear_ossr(uint32_t val) +{ + + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_SR, val); +} + +void +pxa_timer_watchdog_enable(void) +{ + + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_WR, 0x1); +} + +void +pxa_timer_watchdog_disable(void) +{ + + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_WR, 0x0); +} + +void +pxa_timer_interrupt_enable(int which) +{ + uint32_t oier; + + if (which == -1) { + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR, 0xf); + return; + } + + oier = bus_space_read_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR); + oier |= 1 << which; + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR, oier); +} + +void +pxa_timer_interrupt_disable(int which) +{ + uint32_t oier; + + if (which == -1) { + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR, 0); + } + + oier = bus_space_read_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR); + oier &= ~(1 << which); + bus_space_write_4(timer_softc->pt_bst, + timer_softc->pt_bsh, OST_IR, oier); +} diff --git a/sys/arm/xscale/pxa/pxareg.h b/sys/arm/xscale/pxa/pxareg.h new file mode 100644 index 000000000000..eb1f53b2790b --- /dev/null +++ b/sys/arm/xscale/pxa/pxareg.h @@ -0,0 +1,758 @@ +/* $NetBSD: pxa2x0reg.h,v 1.9 2006/04/10 04:13:58 simonb Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * 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. + * + * $FreeBSD$ + */ + + +/* + * Intel PXA2[15]0 processor is XScale based integrated CPU + * + * Reference: + * Intel(r) PXA250 and PXA210 Application Processors + * Developer's Manual + * (278522-001.pdf) + */ +#ifndef _ARM_XSCALE_PXAREG_H_ +#define _ARM_XSCALE_PXAREG_H_ + +#ifndef _LOCORE +#include <sys/types.h> /* for uint32_t */ +#endif + +/* + * Chip select domains + */ +#define PXA2X0_CS0_START 0x00000000 +#define PXA2X0_CS1_START 0x04000000 +#define PXA2X0_CS2_START 0x08000000 +#define PXA2X0_CS3_START 0x0c000000 +#define PXA2X0_CS4_START 0x10000000 +#define PXA2X0_CS5_START 0x14000000 +#define PXA2X0_CS_SIZE 0x04000000 + +#define PXA2X0_PCMCIA_SLOT0 0x20000000 +#define PXA2X0_PCMCIA_SLOT1 0x30000000 + +#define PXA2X0_PERIPH_START 0x40000000 +/* #define PXA2X0_MEMCTL_START 0x48000000 */ +#define PXA270_PERIPH_END 0x530fffff +#define PXA250_PERIPH_END 0x480fffff +#define PXA2X0_PERIPH_OFFSET 0xa8000000 + +#define PXA2X0_SDRAM0_START 0xa0000000 +#define PXA2X0_SDRAM1_START 0xa4000000 +#define PXA2X0_SDRAM2_START 0xa8000000 +#define PXA2X0_SDRAM3_START 0xac000000 +#define PXA2X0_SDRAM_BANKS 4 +#define PXA2X0_SDRAM_BANK_SIZE 0x04000000 + +/* + * Physical address of integrated peripherals + */ + +#define PXA2X0_DMAC_BASE 0x40000000 +#define PXA2X0_DMAC_SIZE 0x300 +#define PXA2X0_FFUART_BASE 0x40100000 /* Full Function UART */ +#define PXA2X0_FFUART_SIZE 0x20 +#define PXA2X0_BTUART_BASE 0x40200000 /* Bluetooth UART */ +#define PXA2X0_BTUART_SIZE 0x24 +#define PXA2X0_I2C_BASE 0x40300000 +#define PXA2X0_I2C_SIZE 0x000016a4 +#define PXA2X0_I2S_BASE 0x40400000 +#define PXA2X0_AC97_BASE 0x40500000 +#define PXA2X0_AC97_SIZE 0x600 +#define PXA2X0_USBDC_BASE 0x40600000 /* USB Client */ +#define PXA2X0_USBDC_SIZE 0x0e04 +#define PXA2X0_STUART_BASE 0x40700000 /* Standard UART */ +#define PXA2X0_STUART_SIZE 0x24 +#define PXA2X0_ICP_BASE 0x40800000 +#define PXA2X0_RTC_BASE 0x40900000 +#define PXA2X0_RTC_SIZE 0x10 +#define PXA2X0_OST_BASE 0x40a00000 /* OS Timer */ +#define PXA2X0_OST_SIZE 0x20 +#define PXA2X0_PWM0_BASE 0x40b00000 +#define PXA2X0_PWM1_BASE 0x40c00000 +#define PXA2X0_INTCTL_BASE 0x40d00000 /* Interrupt controller */ +#define PXA2X0_INTCTL_SIZE 0x20 +#define PXA2X0_GPIO_BASE 0x40e00000 + +#define PXA270_GPIO_SIZE 0x150 +#define PXA250_GPIO_SIZE 0x70 +#define PXA2X0_POWMAN_BASE 0x40f00000 /* Power management */ +#define PXA2X0_SSP_BASE 0x41000000 +#define PXA2X0_MMC_BASE 0x41100000 /* MultiMediaCard */ +#define PXA2X0_MMC_SIZE 0x48 +#define PXA2X0_CLKMAN_BASE 0x41300000 /* Clock Manager */ +#define PXA2X0_CLKMAN_SIZE 12 +#define PXA2X0_HWUART_BASE 0x41600000 /* Hardware UART */ +#define PXA2X0_HWUART_SIZE 0x30 +#define PXA2X0_LCDC_BASE 0x44000000 /* LCD Controller */ +#define PXA2X0_LCDC_SIZE 0x220 +#define PXA2X0_MEMCTL_BASE 0x48000000 /* Memory Controller */ +#define PXA2X0_MEMCTL_SIZE 0x48 +#define PXA2X0_USBH_BASE 0x4c000000 /* USB Host controller */ +#define PXA2X0_USBH_SIZE 0x70 + +/* Internal SRAM storage. PXA27x only */ +#define PXA270_SRAM0_START 0x5c000000 +#define PXA270_SRAM1_START 0x5c010000 +#define PXA270_SRAM2_START 0x5c020000 +#define PXA270_SRAM3_START 0x5c030000 +#define PXA270_SRAM_BANKS 4 +#define PXA270_SRAM_BANK_SIZE 0x00010000 + +/* width of interrupt controller */ +#define ICU_LEN 32 /* but [0..7,15,16] is not used */ +#define ICU_INT_HWMASK 0xffffff00 +#define PXA250_IRQ_MIN 8 /* 0..7 are not used by integrated + peripherals */ +#define PXA270_IRQ_MIN 0 + +#define PXA2X0_INT_USBH1 3 /* USB host (OHCI) */ + +#define PXA2X0_INT_HWUART 7 +#define PXA2X0_INT_GPIO0 8 +#define PXA2X0_INT_GPIO1 9 +#define PXA2X0_INT_GPION 10 /* irq from GPIO[2..80] */ +#define PXA2X0_INT_USB 11 +#define PXA2X0_INT_PMU 12 +#define PXA2X0_INT_I2S 13 +#define PXA2X0_INT_AC97 14 +#define PXA2X0_INT_LCD 17 +#define PXA2X0_INT_I2C 18 +#define PXA2X0_INT_ICP 19 +#define PXA2X0_INT_STUART 20 +#define PXA2X0_INT_BTUART 21 +#define PXA2X0_INT_FFUART 22 +#define PXA2X0_INT_MMC 23 +#define PXA2X0_INT_SSP 24 +#define PXA2X0_INT_DMA 25 +#define PXA2X0_INT_OST0 26 +#define PXA2X0_INT_OST1 27 +#define PXA2X0_INT_OST2 28 +#define PXA2X0_INT_OST3 29 +#define PXA2X0_INT_RTCHZ 30 +#define PXA2X0_INT_ALARM 31 /* RTC Alarm interrupt */ + +/* DMAC */ +#define DMAC_N_CHANNELS 16 +#define DMAC_N_PRIORITIES 3 + +#define DMAC_DCSR(n) ((n)*4) +#define DCSR_BUSERRINTR (1<<0) /* bus error interrupt */ +#define DCSR_STARTINTR (1<<1) /* start interrupt */ +#define DCSR_ENDINTR (1<<2) /* end interrupt */ +#define DCSR_STOPSTATE (1<<3) /* channel is not running */ +#define DCSR_REQPEND (1<<8) /* request pending */ +#define DCSR_STOPIRQEN (1<<29) /* stop interrupt enable */ +#define DCSR_NODESCFETCH (1<<30) /* no-descriptor fetch mode */ +#define DCSR_RUN (1<<31) +#define DMAC_DINT 0x00f0 /* DAM interrupt */ +#define DMAC_DINT_MASK 0xffffu +#define DMAC_DRCMR(n) (0x100+(n)*4) /* Channel map register */ +#define DRCMR_CHLNUM 0x0f /* channel number */ +#define DRCMR_MAPVLD (1<<7) /* map valid */ +#define DMAC_DDADR(n) (0x0200+(n)*16) +#define DDADR_STOP (1<<0) +#define DMAC_DSADR(n) (0x0204+(n)*16) +#define DMAC_DTADR(n) (0x0208+(n)*16) +#define DMAC_DCMD(n) (0x020c+(n)*16) +#define DCMD_LENGTH_MASK 0x1fff +#define DCMD_WIDTH_SHIFT 14 +#define DCMD_WIDTH_0 (0<<DCMD_WIDTH_SHIFT) /* for mem-to-mem transfer*/ +#define DCMD_WIDTH_1 (1<<DCMD_WIDTH_SHIFT) +#define DCMD_WIDTH_2 (2<<DCMD_WIDTH_SHIFT) +#define DCMD_WIDTH_4 (3<<DCMD_WIDTH_SHIFT) +#define DCMD_SIZE_SHIFT 16 +#define DCMD_SIZE_8 (1<<DCMD_SIZE_SHIFT) +#define DCMD_SIZE_16 (2<<DCMD_SIZE_SHIFT) +#define DCMD_SIZE_32 (3<<DCMD_SIZE_SHIFT) +#define DCMD_LITTLE_ENDIEN (0<<18) +#define DCMD_ENDIRQEN (1<<21) +#define DCMD_STARTIRQEN (1<<22) +#define DCMD_FLOWTRG (1<<28) /* flow control by target */ +#define DCMD_FLOWSRC (1<<29) /* flow control by source */ +#define DCMD_INCTRGADDR (1<<30) /* increment target address */ +#define DCMD_INCSRCADDR (1<<31) /* increment source address */ + +#ifndef __ASSEMBLER__ +/* DMA descriptor */ +struct pxa_dma_desc { + volatile uint32_t dd_ddadr; +#define DMAC_DESC_LAST 0x1 + volatile uint32_t dd_dsadr; + volatile uint32_t dd_dtadr; + volatile uint32_t dd_dcmd; /* command and length */ +}; +#endif + +/* UART */ +#define PXA2X0_COM_FREQ 14745600L + +/* I2C */ +#define I2C_IBMR 0x1680 /* Bus monitor register */ +#define I2C_IDBR 0x1688 /* Data buffer */ +#define I2C_ICR 0x1690 /* Control register */ +#define ICR_START (1<<0) +#define ICR_STOP (1<<1) +#define ICR_ACKNAK (1<<2) +#define ICR_TB (1<<3) +#define ICR_MA (1<<4) +#define I2C_ISR 0x1698 /* Status register */ +#define I2C_ISAR 0x16a0 /* Slave address */ + +/* Clock Manager */ +#define CLKMAN_CCCR 0x00 /* Core Clock Configuration */ +#define CCCR_TURBO_X1 (2<<7) +#define CCCR_TURBO_X15 (3<<7) /* x 1.5 */ +#define CCCR_TURBO_X2 (4<<7) +#define CCCR_TURBO_X25 (5<<7) /* x 2.5 */ +#define CCCR_TURBO_X3 (6<<7) /* x 3.0 */ +#define CCCR_RUN_X1 (1<<5) +#define CCCR_RUN_X2 (2<<5) +#define CCCR_RUN_X4 (3<<5) +#define CCCR_MEM_X27 (1<<0) /* x27, 99.53MHz */ +#define CCCR_MEM_X32 (2<<0) /* x32, 117,96MHz */ +#define CCCR_MEM_X36 (3<<0) /* x26, 132.71MHz */ +#define CCCR_MEM_X40 (4<<0) /* x27, 99.53MHz */ +#define CCCR_MEM_X45 (5<<0) /* x27, 99.53MHz */ +#define CCCR_MEM_X9 (0x1f<<0) /* x9, 33.2MHz */ + +#define CLKMAN_CKEN 0x04 /* Clock Enable Register */ +#define CLKMAN_OSCC 0x08 /* Osillcator Configuration Register */ + +#define CCCR_N_SHIFT 7 +#define CCCR_N_MASK (0x07<<CCCR_N_SHIFT) +#define CCCR_M_SHIFT 5 +#define CCCR_M_MASK (0x03<<CCCR_M_SHIFT) +#define CCCR_L_MASK 0x1f + +#define CKEN_PWM0 (1<<0) +#define CKEN_PWM1 (1<<1) +#define CKEN_AC97 (1<<2) +#define CKEN_SSP (1<<3) +#define CKEN_STUART (1<<5) +#define CKEN_FFUART (1<<6) +#define CKEN_BTUART (1<<7) +#define CKEN_I2S (1<<8) +#define CKEN_USBH (1<<10) +#define CKEN_USB (1<<11) +#define CKEN_MMC (1<<12) +#define CKEN_FICP (1<<13) +#define CKEN_I2C (1<<14) +#define CKEN_LCD (1<<16) + +#define OSCC_OOK (1<<0) /* 32.768 kHz oscillator status */ +#define OSCC_OON (1<<1) /* 32.768 kHz oscillator */ + +/* + * RTC + */ +#define RTC_RCNR 0x0000 /* count register */ +#define RTC_RTAR 0x0004 /* alarm register */ +#define RTC_RTSR 0x0008 /* status register */ +#define RTC_RTTR 0x000c /* trim register */ +/* + * GPIO + */ +#define GPIO_GPLR0 0x00 /* Level reg [31:0] */ +#define GPIO_GPLR1 0x04 /* Level reg [63:32] */ +#define GPIO_GPLR2 0x08 /* Level reg [80:64] */ + +#define GPIO_GPDR0 0x0c /* dir reg [31:0] */ +#define GPIO_GPDR1 0x10 /* dir reg [63:32] */ +#define GPIO_GPDR2 0x14 /* dir reg [80:64] */ + +#define GPIO_GPSR0 0x18 /* set reg [31:0] */ +#define GPIO_GPSR1 0x1c /* set reg [63:32] */ +#define GPIO_GPSR2 0x20 /* set reg [80:64] */ + +#define GPIO_GPCR0 0x24 /* clear reg [31:0] */ +#define GPIO_GPCR1 0x28 /* clear reg [63:32] */ +#define GPIO_GPCR2 0x2c /* clear reg [80:64] */ + +#define GPIO_GPER0 0x30 /* rising edge [31:0] */ +#define GPIO_GPER1 0x34 /* rising edge [63:32] */ +#define GPIO_GPER2 0x38 /* rising edge [80:64] */ + +#define GPIO_GRER0 0x30 /* rising edge [31:0] */ +#define GPIO_GRER1 0x34 /* rising edge [63:32] */ +#define GPIO_GRER2 0x38 /* rising edge [80:64] */ + +#define GPIO_GFER0 0x3c /* falling edge [31:0] */ +#define GPIO_GFER1 0x40 /* falling edge [63:32] */ +#define GPIO_GFER2 0x44 /* falling edge [80:64] */ + +#define GPIO_GEDR0 0x48 /* edge detect [31:0] */ +#define GPIO_GEDR1 0x4c /* edge detect [63:32] */ +#define GPIO_GEDR2 0x50 /* edge detect [80:64] */ + +#define GPIO_GAFR0_L 0x54 /* alternate function [15:0] */ +#define GPIO_GAFR0_U 0x58 /* alternate function [31:16] */ +#define GPIO_GAFR1_L 0x5c /* alternate function [47:32] */ +#define GPIO_GAFR1_U 0x60 /* alternate function [63:48] */ +#define GPIO_GAFR2_L 0x64 /* alternate function [79:64] */ +#define GPIO_GAFR2_U 0x68 /* alternate function [80] */ + +/* Only for PXA270 */ +#define GPIO_GAFR3_L 0x6c /* alternate function [111:96] */ +#define GPIO_GAFR3_U 0x70 /* alternate function [120:112] */ + +#define GPIO_GPLR3 0x100 /* Level reg [120:96] */ +#define GPIO_GPDR3 0x10c /* dir reg [120:96] */ +#define GPIO_GPSR3 0x118 /* set reg [120:96] */ +#define GPIO_GPCR3 0x124 /* clear reg [120:96] */ +#define GPIO_GRER3 0x130 /* rising edge [120:96] */ +#define GPIO_GFER3 0x13c /* falling edge [120:96] */ +#define GPIO_GEDR3 0x148 /* edge detect [120:96] */ + +/* a bit simpler if we don't support PXA270 */ +#define PXA250_GPIO_REG(r, pin) ((r) + (((pin) / 32) * 4)) +#define PXA250_GPIO_NPINS 85 + +#define PXA270_GPIO_REG(r, pin) \ +(pin < 96 ? PXA250_GPIO_REG(r,pin) : ((r) + 0x100 + ((((pin)-96) / 32) * 4))) +#define PXA270_GPIO_NPINS 121 + + +#define GPIO_BANK(pin) ((pin) / 32) +#define GPIO_BIT(pin) (1u << ((pin) & 0x1f)) +#define GPIO_FN_REG(pin) (GPIO_GAFR0_L + (((pin) / 16) * 4)) +#define GPIO_FN_SHIFT(pin) ((pin & 0xf) * 2) + +#define GPIO_IN 0x00 /* Regular GPIO input pin */ +#define GPIO_OUT 0x10 /* Regular GPIO output pin */ +#define GPIO_ALT_FN_1_IN 0x01 /* Alternate function 1 input */ +#define GPIO_ALT_FN_1_OUT 0x11 /* Alternate function 1 output */ +#define GPIO_ALT_FN_2_IN 0x02 /* Alternate function 2 input */ +#define GPIO_ALT_FN_2_OUT 0x12 /* Alternate function 2 output */ +#define GPIO_ALT_FN_3_IN 0x03 /* Alternate function 3 input */ +#define GPIO_ALT_FN_3_OUT 0x13 /* Alternate function 3 output */ +#define GPIO_SET 0x20 /* Initial state is Set */ +#define GPIO_CLR 0x00 /* Initial state is Clear */ + +#define GPIO_FN_MASK 0x03 +#define GPIO_FN_IS_OUT(n) ((n) & GPIO_OUT) +#define GPIO_FN_IS_SET(n) ((n) & GPIO_SET) +#define GPIO_FN(n) ((n) & GPIO_FN_MASK) +#define GPIO_IS_GPIO(n) (GPIO_FN(n) == 0) +#define GPIO_IS_GPIO_IN(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_IN) +#define GPIO_IS_GPIO_OUT(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_OUT) + +#define IRQ_GPIO0 64 +#define IRQ_NGPIO 128 +#define IRQ_GPIO_MAX IRQ_GPIO0 + IRQ_NGPIO +#define IRQ_TO_GPIO(x) (x - IRQ_GPIO0) +#define GPIO_TO_IRQ(x) (x + IRQ_GPIO0) + +/* + * memory controller + */ + +#define MEMCTL_MDCNFG 0x0000 +#define MDCNFG_DE0 (1<<0) +#define MDCNFG_DE1 (1<<1) +#define MDCNFD_DWID01_SHIFT 2 +#define MDCNFD_DCAC01_SHIFT 3 +#define MDCNFD_DRAC01_SHIFT 5 +#define MDCNFD_DNB01_SHIFT 7 +#define MDCNFG_DE2 (1<<16) +#define MDCNFG_DE3 (1<<17) +#define MDCNFD_DWID23_SHIFT 18 +#define MDCNFD_DCAC23_SHIFT 19 +#define MDCNFD_DRAC23_SHIFT 21 +#define MDCNFD_DNB23_SHIFT 23 + +#define MDCNFD_DWID_MASK 0x1 +#define MDCNFD_DCAC_MASK 0x3 +#define MDCNFD_DRAC_MASK 0x3 +#define MDCNFD_DNB_MASK 0x1 + +#define MEMCTL_MDREFR 0x04 /* refresh control register */ +#define MDREFR_DRI 0xfff +#define MDREFR_E0PIN (1<<12) +#define MDREFR_K0RUN (1<<13) /* SDCLK0 enable */ +#define MDREFR_K0DB2 (1<<14) /* SDCLK0 1/2 freq */ +#define MDREFR_E1PIN (1<<15) +#define MDREFR_K1RUN (1<<16) /* SDCLK1 enable */ +#define MDREFR_K1DB2 (1<<17) /* SDCLK1 1/2 freq */ +#define MDREFR_K2RUN (1<<18) /* SDCLK2 enable */ +#define MDREFR_K2DB2 (1<<19) /* SDCLK2 1/2 freq */ +#define MDREFR_APD (1<<20) /* Auto Power Down */ +#define MDREFR_SLFRSH (1<<22) /* Self Refresh */ +#define MDREFR_K0FREE (1<<23) /* SDCLK0 free run */ +#define MDREFR_K1FREE (1<<24) /* SDCLK1 free run */ +#define MDREFR_K2FREE (1<<25) /* SDCLK2 free run */ + +#define MEMCTL_MSC0 0x08 /* Asychronous Statis memory Control CS[01] */ +#define MEMCTL_MSC1 0x0c /* Asychronous Statis memory Control CS[23] */ +#define MEMCTL_MSC2 0x10 /* Asychronous Statis memory Control CS[45] */ +#define MSC_RBUFF_SHIFT 15 /* return data buffer */ +#define MSC_RBUFF (1<<MSC_RBUFF_SHIFT) +#define MSC_RRR_SHIFT 12 /* recovery time */ +#define MSC_RRR (7<<MSC_RRR_SHIFT) +#define MSC_RDN_SHIFT 8 /* ROM delay next access */ +#define MSC_RDN (0x0f<<MSC_RDN_SHIFT) +#define MSC_RDF_SHIFT 4 /* ROM delay first access*/ +#define MSC_RDF (0x0f<<MSC_RDF_SHIFT) +#define MSC_RBW_SHIFT 3 /* 32/16 bit bus */ +#define MSC_RBW (1<<MSC_RBW_SHIFT) +#define MSC_RT_SHIFT 0 /* type */ +#define MSC_RT (7<<MSC_RT_SHIFT) +#define MSC_RT_NONBURST 0 +#define MSC_RT_SRAM 1 +#define MSC_RT_BURST4 2 +#define MSC_RT_BURST8 3 +#define MSC_RT_VLIO 4 + +/* expansion memory timing configuration */ +#define MEMCTL_MCMEM(n) (0x28+4*(n)) +#define MEMCTL_MCATT(n) (0x30+4*(n)) +#define MEMCTL_MCIO(n) (0x38+4*(n)) + +#define MC_HOLD_SHIFT 14 +#define MC_ASST_SHIFT 7 +#define MC_SET_SHIFT 0 +#define MC_TIMING_VAL(hold,asst,set) (((hold)<<MC_HOLD_SHIFT)| \ + ((asst)<<MC_ASST_SHIFT)|((set)<<MC_SET_SHIFT)) + +#define MEMCTL_MECR 0x14 /* Expansion memory configuration */ +#define MECR_NOS (1<<0) /* Number of sockets */ +#define MECR_CIT (1<<1) /* Card-is-there */ + +#define MEMCTL_MDMRS 0x0040 + +/* + * LCD Controller + */ +#define LCDC_LCCR0 0x000 /* Controller Control Register 0 */ +#define LCCR0_ENB (1U<<0) /* LCD Controller Enable */ +#define LCCR0_CMS (1U<<1) /* Color/Mono select */ +#define LCCR0_SDS (1U<<2) /* Single/Dual -panel */ +#define LCCR0_LDM (1U<<3) /* LCD Disable Done Mask */ +#define LCCR0_SFM (1U<<4) /* Start of Frame Mask */ +#define LCCR0_IUM (1U<<5) /* Input FIFO Underrun Mask */ +#define LCCR0_EFM (1U<<6) /* End of Frame Mask */ +#define LCCR0_PAS (1U<<7) /* Passive/Active Display select */ +#define LCCR0_DPD (1U<<9) /* Double-Pixel Data pin mode */ +#define LCCR0_DIS (1U<<10) /* LCD Disable */ +#define LCCR0_QDM (1U<<11) /* LCD Quick Disable Mask */ +#define LCCR0_BM (1U<<20) /* Branch Mask */ +#define LCCR0_OUM (1U<<21) /* Output FIFO Underrun Mask */ + +#define LCCR0_IMASK (LCCR0_LDM|LCCR0_SFM|LCCR0_IUM|LCCR0_EFM|LCCR0_QDM|LCCR0_BM|LCCR0_OUM) + + +#define LCDC_LCCR1 0x004 /* Controller Control Register 1 */ +#define LCDC_LCCR2 0x008 /* Controller Control Register 2 */ +#define LCDC_LCCR3 0x00c /* Controller Control Register 2 */ +#define LCCR3_BPP_SHIFT 24 /* Bits per pixel */ +#define LCCR3_BPP (0x07<<LCCR3_BPP_SHIFT) +#define LCDC_LCCR4 0x010 /* Controller Control Register 4 */ +#define LCDC_LCCR5 0x014 /* Controller Control Register 5 */ +#define LCDC_FBR0 0x020 /* DMA ch0 frame branch register */ +#define LCDC_FBR1 0x024 /* DMA ch1 frame branch register */ +#define LCDC_FBR2 0x028 /* DMA ch2 frame branch register */ +#define LCDC_FBR3 0x02c /* DMA ch3 frame branch register */ +#define LCDC_FBR4 0x030 /* DMA ch4 frame branch register */ +#define LCDC_LCSR1 0x034 /* controller status register 1 PXA27x only */ +#define LCDC_LCSR 0x038 /* controller status register */ +#define LCSR_LDD (1U<<0) /* LCD disable done */ +#define LCSR_SOF (1U<<1) /* Start of frame */ +#define LCDC_LIIDR 0x03c /* controller interrupt ID Register */ +#define LCDC_TRGBR 0x040 /* TMED RGB Speed Register */ +#define LCDC_TCR 0x044 /* TMED Control Register */ +#define LCDC_OVL1C1 0x050 /* Overlay 1 control register 1 */ +#define LCDC_OVL1C2 0x060 /* Overlay 1 control register 2 */ +#define LCDC_OVL2C1 0x070 /* Overlay 1 control register 1 */ +#define LCDC_OVL2C2 0x080 /* Overlay 1 control register 2 */ +#define LCDC_CCR 0x090 /* Cursor control register */ +#define LCDC_CMDCR 0x100 /* Command control register */ +#define LCDC_PRSR 0x104 /* Panel read status register */ +#define LCDC_FBR5 0x110 /* DMA ch5 frame branch register */ +#define LCDC_FBR6 0x114 /* DMA ch6 frame branch register */ +#define LCDC_FDADR0 0x200 /* DMA ch0 frame descriptor address */ +#define LCDC_FSADR0 0x204 /* DMA ch0 frame source address */ +#define LCDC_FIDR0 0x208 /* DMA ch0 frame ID register */ +#define LCDC_LDCMD0 0x20c /* DMA ch0 command register */ +#define LCDC_FDADR1 0x210 /* DMA ch1 frame descriptor address */ +#define LCDC_FSADR1 0x214 /* DMA ch1 frame source address */ +#define LCDC_FIDR1 0x218 /* DMA ch1 frame ID register */ +#define LCDC_LDCMD1 0x21c /* DMA ch1 command register */ +#define LCDC_FDADR2 0x220 /* DMA ch2 frame descriptor address */ +#define LCDC_FSADR2 0x224 /* DMA ch2 frame source address */ +#define LCDC_FIDR2 0x228 /* DMA ch2 frame ID register */ +#define LCDC_LDCMD2 0x22c /* DMA ch2 command register */ +#define LCDC_FDADR3 0x230 /* DMA ch3 frame descriptor address */ +#define LCDC_FSADR3 0x234 /* DMA ch3 frame source address */ +#define LCDC_FIDR3 0x238 /* DMA ch3 frame ID register */ +#define LCDC_LDCMD3 0x23c /* DMA ch3 command register */ +#define LCDC_FDADR4 0x240 /* DMA ch4 frame descriptor address */ +#define LCDC_FSADR4 0x244 /* DMA ch4 frame source address */ +#define LCDC_FIDR4 0x248 /* DMA ch4 frame ID register */ +#define LCDC_LDCMD4 0x24c /* DMA ch4 command register */ +#define LCDC_FDADR5 0x250 /* DMA ch5 frame descriptor address */ +#define LCDC_FSADR5 0x254 /* DMA ch5 frame source address */ +#define LCDC_FIDR5 0x258 /* DMA ch5 frame ID register */ +#define LCDC_LDCMD5 0x25c /* DMA ch5 command register */ +#define LCDC_FDADR6 0x260 /* DMA ch6 frame descriptor address */ +#define LCDC_FSADR6 0x264 /* DMA ch6 frame source address */ +#define LCDC_FIDR6 0x268 /* DMA ch6 frame ID register */ +#define LCDC_LDCMD6 0x26c /* DMA ch6 command register */ +#define LCDC_LCDBSCNTR 0x054 /* LCD buffer strength control register */ + +/* + * MMC/SD controller + */ +#define MMC_STRPCL 0x00 /* start/stop MMC clock */ +#define STRPCL_NOOP 0 +#define STRPCL_STOP 1 /* stop MMC clock */ +#define STRPCL_START 2 /* start MMC clock */ +#define MMC_STAT 0x04 /* status register */ +#define STAT_READ_TIME_OUT (1<<0) +#define STAT_TIMEOUT_RESPONSE (1<<1) +#define STAT_CRC_WRITE_ERROR (1<<2) +#define STAT_CRC_READ_ERROR (1<<3) +#define STAT_SPI_READ_ERROR_TOKEN (1<<4) +#define STAT_RES_CRC_ERR (1<<5) +#define STAT_XMIT_FIFO_EMPTY (1<<6) +#define STAT_RECV_FIFO_FULL (1<<7) +#define STAT_CLK_EN (1<<8) +#define STAT_DATA_TRAN_DONE (1<<11) +#define STAT_PRG_DONE (1<<12) +#define STAT_END_CMD_RES (1<<13) +#define MMC_CLKRT 0x08 /* MMC clock rate */ +#define CLKRT_20M 0 +#define CLKRT_10M 1 +#define CLKRT_5M 2 +#define CLKRT_2_5M 3 +#define CLKRT_1_25M 4 +#define CLKRT_625K 5 +#define CLKRT_312K 6 +#define MMC_SPI 0x0c /* SPI mode control */ +#define SPI_EN (1<<0) /* enable SPI mode */ +#define SPI_CRC_ON (1<<1) /* enable CRC generation */ +#define SPI_CS_EN (1<<2) /* Enable CS[01] */ +#define SPI_CS_ADDRESS (1<<3) /* CS0/CS1 */ +#define MMC_CMDAT 0x10 /* command/response/data */ +#define CMDAT_RESPONSE_FORMAT 0x03 +#define CMDAT_RESPONSE_FORMAT_NO 0 /* no response */ +#define CMDAT_RESPONSE_FORMAT_R1 1 /* R1, R1b, R4, R5 */ +#define CMDAT_RESPONSE_FORMAT_R2 2 +#define CMDAT_RESPONSE_FORMAT_R3 3 +#define CMDAT_DATA_EN (1<<2) +#define CMDAT_WRITE (1<<3) /* 1=write 0=read operation */ +#define CMDAT_STREAM_BLOCK (1<<4) /* stream mode */ +#define CMDAT_BUSY (1<<5) /* busy signal is expected */ +#define CMDAT_INIT (1<<6) /* preceede command with 80 clocks */ +#define CMDAT_MMC_DMA_EN (1<<7) /* DMA enable */ +#define MMC_RESTO 0x14 /* expected response time out */ +#define MMC_RDTO 0x18 /* expected data read time out */ +#define MMC_BLKLEN 0x1c /* block length of data transaction */ +#define MMC_NOB 0x20 /* number of blocks (block mode) */ +#define MMC_PRTBUF 0x24 /* partial MMC_TXFIFO written */ +#define PRTBUF_BUF_PART_FULL (1<<0) /* buffer partially full */ +#define MMC_I_MASK 0x28 /* interrupt mask */ +#define MMC_I_REG 0x2c /* interrupt register */ +#define MMC_I_DATA_TRAN_DONE (1<<0) +#define MMC_I_PRG_DONE (1<<1) +#define MMC_I_END_CMD_RES (1<<2) +#define MMC_I_STOP_CMD (1<<3) +#define MMC_I_CLK_IS_OFF (1<<4) +#define MMC_I_RXFIFO_RD_REQ (1<<5) +#define MMC_I_TXFIFO_WR_REQ (1<<6) +#define MMC_CMD 0x30 /* index of current command */ +#define MMC_ARGH 0x34 /* MSW part of the current command arg */ +#define MMC_ARGL 0x38 /* LSW part of the current command arg */ +#define MMC_RES 0x3c /* response FIFO */ +#define MMC_RXFIFO 0x40 /* receive FIFO */ +#define MMC_TXFIFO 0x44 /* transmit FIFO */ + +/* + * AC97 + */ +#define AC97_N_CODECS 2 +#define AC97_GCR 0x000c /* Global control register */ +#define GCR_GIE (1<<0) /* interrupt enable */ +#define GCR_COLD_RST (1<<1) +#define GCR_WARM_RST (1<<2) +#define GCR_ACLINK_OFF (1<<3) +#define GCR_PRIRES_IEN (1<<4) /* Primary resume interrupt enable */ +#define GCR_SECRES_IEN (1<<5) /* Secondary resume interrupt enable */ +#define GCR_PRIRDY_IEN (1<<8) /* Primary ready interrupt enable */ +#define GCR_SECRDY_IEN (1<<9) /* Primary ready interrupt enable */ +#define GCR_SDONE_IE (1<<18) /* Status done interrupt enable */ +#define GCR_CDONE_IE (1<<19) /* Command done interrupt enable */ + +#define AC97_GSR 0x001c /* Global status register */ +#define GSR_GSCI (1<<0) /* codec GPI status change interrupt */ +#define GSR_MIINT (1<<1) /* modem in interrupt */ +#define GSR_MOINT (1<<2) /* modem out interrupt */ +#define GSR_PIINT (1<<5) /* PCM in interrupt */ +#define GSR_POINT (1<<6) /* PCM out interrupt */ +#define GSR_MINT (1<<7) /* Mic in interrupt */ +#define GSR_PCR (1<<8) /* primary code ready */ +#define GSR_SCR (1<<9) /* secondary code ready */ +#define GSR_PRIRES (1<<10) /* primary resume interrupt */ +#define GSR_SECRES (1<<11) /* secondary resume interrupt */ +#define GSR_BIT1SLT12 (1<<12) /* Bit 1 of slot 12 */ +#define GSR_BIT2SLT12 (1<<13) /* Bit 2 of slot 12 */ +#define GSR_BIT3SLT12 (1<<14) /* Bit 3 of slot 12 */ +#define GSR_RDCS (1<<15) /* Read completion status */ +#define GSR_SDONE (1<<18) /* status done */ +#define GSR_CDONE (1<<19) /* command done */ + +#define AC97_POCR 0x0000 /* PCM-out control */ +#define AC97_PICR 0x0004 /* PCM-in control */ +#define AC97_POSR 0x0010 /* PCM-out status */ +#define AC97_PISR 0x0014 /* PCM-out status */ +#define AC97_MCCR 0x0008 /* MIC-in control register */ +#define AC97_MCSR 0x0018 /* MIC-in status register */ +#define AC97_MICR 0x0100 /* Modem-in control register */ +#define AC97_MISR 0x0108 /* Modem-in status register */ +#define AC97_MOCR 0x0110 /* Modem-out control register */ +#define AC97_MOSR 0x0118 /* Modem-out status register */ +#define AC97_FEFIE (1<<3) /* fifo error interrupt enable */ +#define AC97_FIFOE (1<<4) /* fifo error */ + +#define AC97_CAR 0x0020 /* Codec access register */ +#define CAR_CAIP (1<<0) /* Codec access in progress */ + +#define AC97_PCDR 0x0040 /* PCM data register */ +#define AC97_MCDR 0x0060 /* MIC-in data register */ +#define AC97_MODR 0x0140 /* Modem data register */ + +/* address to access codec registers */ +#define AC97_PRIAUDIO 0x0200 /* Primary audio codec */ +#define AC97_SECAUDIO 0x0300 /* Secondary autio codec */ +#define AC97_PRIMODEM 0x0400 /* Primary modem codec */ +#define AC97_SECMODEM 0x0500 /* Secondary modem codec */ +#define AC97_CODEC_BASE(c) (AC97_PRIAUDIO + ((c) * 0x100)) + +/* + * USB device controller + */ +#define USBDC_UDCCR 0x0000 /* UDC control register */ +#define USBDC_UDCCS(n) (0x0010+4*(n)) /* Endpoint Control/Status Registers */ +#define USBDC_UICR0 0x0050 /* UDC Interrupt Control Register 0 */ +#define USBDC_UICR1 0x0054 /* UDC Interrupt Control Register 1 */ +#define USBDC_USIR0 0x0058 /* UDC Status Interrupt Register 0 */ +#define USBDC_USIR1 0x005C /* UDC Status Interrupt Register 1 */ +#define USBDC_UFNHR 0x0060 /* UDC Frame Number Register High */ +#define USBDC_UFNLR 0x0064 /* UDC Frame Number Register Low */ +#define USBDC_UBCR2 0x0068 /* UDC Byte Count Register 2 */ +#define USBDC_UBCR4 0x006C /* UDC Byte Count Register 4 */ +#define USBDC_UBCR7 0x0070 /* UDC Byte Count Register 7 */ +#define USBDC_UBCR9 0x0074 /* UDC Byte Count Register 9 */ +#define USBDC_UBCR12 0x0078 /* UDC Byte Count Register 12 */ +#define USBDC_UBCR14 0x007C /* UDC Byte Count Register 14 */ +#define USBDC_UDDR0 0x0080 /* UDC Endpoint 0 Data Register */ +#define USBDC_UDDR1 0x0100 /* UDC Endpoint 1 Data Register */ +#define USBDC_UDDR2 0x0180 /* UDC Endpoint 2 Data Register */ +#define USBDC_UDDR3 0x0200 /* UDC Endpoint 3 Data Register */ +#define USBDC_UDDR4 0x0400 /* UDC Endpoint 4 Data Register */ +#define USBDC_UDDR5 0x00A0 /* UDC Endpoint 5 Data Register */ +#define USBDC_UDDR6 0x0600 /* UDC Endpoint 6 Data Register */ +#define USBDC_UDDR7 0x0680 /* UDC Endpoint 7 Data Register */ +#define USBDC_UDDR8 0x0700 /* UDC Endpoint 8 Data Register */ +#define USBDC_UDDR9 0x0900 /* UDC Endpoint 9 Data Register */ +#define USBDC_UDDR10 0x00C0 /* UDC Endpoint 10 Data Register */ +#define USBDC_UDDR11 0x0B00 /* UDC Endpoint 11 Data Register */ +#define USBDC_UDDR12 0x0B80 /* UDC Endpoint 12 Data Register */ +#define USBDC_UDDR13 0x0C00 /* UDC Endpoint 13 Data Register */ +#define USBDC_UDDR14 0x0E00 /* UDC Endpoint 14 Data Register */ +#define USBDC_UDDR15 0x00E0 /* UDC Endpoint 15 Data Register */ + +#define USBHC_UHCRHDA 0x0048 /* UHC Root Hub Descriptor A */ +#define UHCRHDA_POTPGT_SHIFT 24 /* Power on to power good time */ +#define UHCRHDA_NOCP (1<<12) /* No over current protection */ +#define UHCRHDA_OCPM (1<<11) /* Over current protection mode */ +#define UHCRHDA_DT (1<<10) /* Device type */ +#define UHCRHDA_NPS (1<<9) /* No power switching */ +#define UHCRHDA_PSM (1<<8) /* Power switching mode */ +#define UHCRHDA_NDP_MASK 0xff /* Number downstream ports */ +#define USBHC_UHCRHDB 0x004c /* UHC Root Hub Descriptor B */ +#define USBHC_UHCRHS 0x0050 /* UHC Root Hub Stauts */ +#define USBHC_UHCHR 0x0064 /* UHC Reset Register */ +#define UHCHR_SSEP3 (1<<11) /* Sleep standby enable for port3 */ +#define UHCHR_SSEP2 (1<<10) /* Sleep standby enable for port2 */ +#define UHCHR_SSEP1 (1<<9) /* Sleep standby enable for port1 */ +#define UHCHR_PCPL (1<<7) /* Power control polarity low */ +#define UHCHR_PSPL (1<<6) /* Power sense polarity low */ +#define UHCHR_SSE (1<<5) /* Sleep standby enable */ +#define UHCHR_UIT (1<<4) /* USB interrupt test */ +#define UHCHR_SSDC (1<<3) /* Simulation scale down clock */ +#define UHCHR_CGR (1<<2) /* Clock generation reset */ +#define UHCHR_FHR (1<<1) /* Force host controller reset */ +#define UHCHR_FSBIR (1<<0) /* Force system bus interface reset */ +#define UHCHR_MASK 0xeff + +/* + * PWM controller + */ +#define PWM_PWMCR 0x0000 /* Control register */ +#define PWM_PWMDCR 0x0004 /* Duty cycle register */ +#define PWM_FD (1<<10) /* Full duty */ +#define PWM_PWMPCR 0x0008 /* Period register */ + +/* + * OS timer + */ +#define OST_MR0 0x00 /* Match register 0 */ +#define OST_MR1 0x04 /* Match register 1 */ +#define OST_MR2 0x08 /* Match register 2 */ +#define OST_MR3 0x0c /* Match register 3 */ +#define OST_CR 0x10 /* Count register */ +#define OST_SR 0x14 /* Status register */ +#define OST_SR_CH0 (1<<0) +#define OST_SR_CH1 (1<<1) +#define OST_SR_CH2 (1<<2) +#define OST_SR_CH3 (1<<3) +#define OST_WR 0x18 /* Watchdog enable register */ +#define OST_IR 0x1c /* Interrupt enable register */ + +/* + * Interrupt controller + */ +#define ICU_IP 0x00 /* IRQ pending register */ +#define ICU_MR 0x04 /* Mask register */ +#define ICU_LR 0x08 /* Level register */ +#define ICU_FP 0x0c /* FIQ pending register */ +#define ICU_PR 0x10 /* Pending register */ +#define ICU_CR 0x14 /* Control register */ + +#endif /* _ARM_XSCALE_PXAREG_H_ */ diff --git a/sys/arm/xscale/pxa/pxavar.h b/sys/arm/xscale/pxa/pxavar.h new file mode 100644 index 000000000000..01deea230fd0 --- /dev/null +++ b/sys/arm/xscale/pxa/pxavar.h @@ -0,0 +1,114 @@ +/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2002, 2003 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. + * + * $FreeBSD$ + * + */ + +#ifndef _PXAVAR_H_ +#define _PXAVAR_H_ + +#include <sys/rman.h> + +struct obio_softc { + bus_space_tag_t obio_bst; /* bus space tag */ + struct rman obio_mem; + struct rman obio_irq; +}; + +extern bus_space_tag_t base_tag; +extern bus_space_tag_t obio_tag; +void pxa_obio_tag_init(void); +bus_space_tag_t pxa_bus_tag_alloc(bus_addr_t); + +uint32_t pxa_gpio_get_function(int); +uint32_t pxa_gpio_set_function(int, uint32_t); +int pxa_gpio_setup_intrhandler(const char *, driver_filter_t *, + driver_intr_t *, void *, int, int, void **); +void pxa_gpio_mask_irq(int); +void pxa_gpio_unmask_irq(int); +int pxa_gpio_get_next_irq(void); + +struct dmac_channel; + +struct dmac_descriptor { + uint32_t ddadr; + uint32_t dsadr; + uint32_t dtadr; + uint32_t dcmd; +}; +#define DMACD_SET_DESCRIPTOR(d, dadr) do { d->ddadr = dadr; } while (0) +#define DMACD_SET_SOURCE(d, sadr) do { d->dsadr = sadr; } while (0) +#define DMACD_SET_TARGET(d, tadr) do { d->dtadr = tadr; } while (0) +#define DMACD_SET_COMMAND(d, cmd) do { d->dcmd = cmd; } while (0) + +#define DMAC_PRIORITY_HIGHEST 1 +#define DMAC_PRIORITY_HIGH 2 +#define DMAC_PRIORITY_LOW 3 + +int pxa_dmac_alloc(int, struct dmac_channel **, int); +void pxa_dmac_release(struct dmac_channel *); +int pxa_dmac_transfer(struct dmac_channel *, bus_addr_t); +int pxa_dmac_transfer_single(struct dmac_channel *, + bus_addr_t, bus_addr_t, uint32_t); +int pxa_dmac_transfer_done(struct dmac_channel *); +int pxa_dmac_transfer_failed(struct dmac_channel *); + +enum pxa_device_ivars { + PXA_IVAR_BASE, +}; + +enum smi_device_ivars { + SMI_IVAR_PHYSBASE, +}; + +#define PXA_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(pxa, var, PXA, ivar, type) + +PXA_ACCESSOR(base, BASE, u_long) + +#undef PXA_ACCESSOR + +#define SMI_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(smi, var, SMI, ivar, type) + +SMI_ACCESSOR(physbase, PHYSBASE, bus_addr_t) + +#undef CSR_ACCESSOR + +#endif /* _PXAVAR_H_ */ diff --git a/sys/arm/xscale/pxa/std.pxa b/sys/arm/xscale/pxa/std.pxa new file mode 100644 index 000000000000..b8e3484802cb --- /dev/null +++ b/sys/arm/xscale/pxa/std.pxa @@ -0,0 +1,9 @@ +# XScale PXA generic configuration +# $FreeBSD$ +files "../xscale/pxa/files.pxa" +include "../xscale/std.xscale" +makeoptions KERNPHYSADDR=0xa0200000 +makeoptions KERNVIRTADDR=0xc0200000 +makeoptions CONF_CFLAGS=-mcpu=xscale +options XSCALE_CACHE_READ_WRITE_ALLOCATE +machine arm diff --git a/sys/arm/xscale/pxa/uart_bus_pxa.c b/sys/arm/xscale/pxa/uart_bus_pxa.c new file mode 100644 index 000000000000..ed3ae53b23c5 --- /dev/null +++ b/sys/arm/xscale/pxa/uart_bus_pxa.c @@ -0,0 +1,105 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Benno Rice. 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + +#include <dev/pci/pcivar.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> +#include <dev/uart/uart_cpu.h> + +#include <dev/ic/ns16550.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +#include "uart_if.h" + +#define PXA_UART_UUE 0x40 /* UART Unit Enable */ + +static int uart_pxa_probe(device_t dev); + +static device_method_t uart_pxa_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_pxa_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + { 0, 0 } +}; + +static driver_t uart_pxa_driver = { + uart_driver_name, + uart_pxa_methods, + sizeof(struct uart_softc), +}; + +static int +uart_pxa_probe(device_t dev) +{ + bus_space_handle_t base; + struct uart_softc *sc; + + base = (bus_space_handle_t)pxa_get_base(dev); +#ifdef QEMU_WORKAROUNDS + /* + * QEMU really exposes only the first uart unless + * you specify several of them in the configuration. + * Otherwise all the rest of UARTs stay unconnected, + * which causes problems in the ns16550 attach routine. + * Unfortunately, even if you provide qemu with 4 uarts + * on the command line, it has a bug where it segfaults + * trying to enable bluetooth on the HWUART. So we just + * allow the FFUART to be attached. + * Also, don't check the UUE (UART Unit Enable) bit, as + * the gumstix bootloader doesn't set it. + */ + if (base != PXA2X0_FFUART_BASE) + return (ENXIO); +#else + /* Check to see if the enable bit's on. */ + if ((bus_space_read_4(obio_tag, base, + (REG_IER << 2)) & PXA_UART_UUE) == 0) + return (ENXIO); +#endif + sc = device_get_softc(dev); + sc->sc_class = &uart_ns8250_class; + + return(uart_bus_probe(dev, 2, 0, PXA2X0_COM_FREQ, 0, 0)); +} + +DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0); diff --git a/sys/arm/xscale/pxa/uart_cpu_pxa.c b/sys/arm/xscale/pxa/uart_cpu_pxa.c new file mode 100644 index 000000000000..68c253c32adb --- /dev/null +++ b/sys/arm/xscale/pxa/uart_cpu_pxa.c @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2003 Marcel Moolenaar + * 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. + * + * 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 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <machine/bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> + +#include <arm/xscale/pxa/pxavar.h> +#include <arm/xscale/pxa/pxareg.h> + +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + +int +uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +{ + + return (b1->bsh == b2->bsh ? 1 : 0); +} + +int +uart_cpu_getdev(int devtype, struct uart_devinfo *di) +{ + + di->ops = uart_getops(&uart_ns8250_class); + di->bas.chan = 0; + di->bas.bst = obio_tag; + di->bas.regshft = 2; + di->bas.rclk = PXA2X0_COM_FREQ; + di->baudrate = 115200; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + uart_bus_space_mem = obio_tag; + uart_bus_space_io = NULL; + di->bas.bsh = PXA2X0_FFUART_BASE; + return (0); +} diff --git a/sys/arm/xscale/std.xscale b/sys/arm/xscale/std.xscale new file mode 100644 index 000000000000..b5266bd8d80d --- /dev/null +++ b/sys/arm/xscale/std.xscale @@ -0,0 +1,3 @@ +# $FreeBSD$ +options ARM_CACHE_LOCK_ENABLE +options NO_EVENTTIMERS |