diff options
Diffstat (limited to 'sys/arch/arm')
24 files changed, 5407 insertions, 0 deletions
diff --git a/sys/arch/arm/arm/cpufunc_asm_xscale.S b/sys/arch/arm/arm/cpufunc_asm_xscale.S new file mode 100644 index 00000000000..56610025b84 --- /dev/null +++ b/sys/arch/arm/arm/cpufunc_asm_xscale.S @@ -0,0 +1,498 @@ +/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2001 Matt Thomas. + * Copyright (c) 1997,1998 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Causality Limited. + * 4. The name of Causality Limited may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``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 CAUSALITY LIMITED 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. + * + * XScale assembly functions for CPU / MMU / TLB specific operations + */ + +#include <machine/cpu.h> +#include <machine/asm.h> + +/* + * Size of the XScale core D-cache. + */ +#define DCACHE_SIZE 0x00008000 + +#ifndef CACHE_CLEAN_BLOCK_INTR +.Lblock_userspace_access: + .word _C_LABEL(block_userspace_access) +#endif + +/* + * CPWAIT -- Canonical method to wait for CP15 update. + * From: Intel 80200 manual, section 2.3.3. + * + * NOTE: Clobbers the specified temp reg. + */ +#define CPWAIT_BRANCH \ + sub pc, pc, #4 + +#define CPWAIT(tmp) \ + mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ + mov tmp, tmp /* wait for it to complete */ ;\ + CPWAIT_BRANCH /* branch to next insn */ + +#define CPWAIT_AND_RETURN_SHIFTER lsr #32 + +#define CPWAIT_AND_RETURN(tmp) \ + mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ + /* Wait for it to complete and branch to the return address */ \ + sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER + +ENTRY(xscale_cpwait) + CPWAIT_AND_RETURN(r0) + +/* + * We need a separate cpu_control() entry point, since we have to + * invalidate the Branch Target Buffer in the event the BPRD bit + * changes in the control register. + */ +ENTRY(xscale_control) + mrc p15, 0, r3, c1, c0, 0 /* Read the control register */ + bic r2, r3, r0 /* Clear bits */ + eor r2, r2, r1 /* XOR bits */ + + teq r2, r3 /* Only write if there was a change */ + mcrne p15, 0, r0, c7, c5, 6 /* Invalidate the BTB */ + mcrne p15, 0, r2, c1, c0, 0 /* Write new control register */ + mov r0, r3 /* Return old value */ + + CPWAIT_AND_RETURN(r1) + +/* + * Functions to set the MMU Translation Table Base register + * + * We need to clean and flush the cache as it uses virtual + * addresses that are about to change. + */ +ENTRY(xscale_setttb) +#ifdef CACHE_CLEAN_BLOCK_INTR + mrs r3, cpsr_all + orr r1, r3, #(I32_bit | F32_bit) + msr cpsr_all, r1 +#else + ldr r3, .Lblock_userspace_access + ldr r2, [r3] + orr r1, r2, #1 + str r1, [r3] +#endif + stmfd sp!, {r0-r3, lr} + bl _C_LABEL(xscale_cache_cleanID) + mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ + mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */ + + CPWAIT(r0) + + ldmfd sp!, {r0-r3, lr} + + /* Write the TTB */ + mcr p15, 0, r0, c2, c0, 0 + + /* If we have updated the TTB we must flush the TLB */ + mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */ + + /* The cleanID above means we only need to flush the I cache here */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ + + CPWAIT(r0) + +#ifdef CACHE_CLEAN_BLOCK_INTR + msr cpsr_all, r3 +#else + str r2, [r3] +#endif + mov pc, lr + +/* + * TLB functions + * + * Note: We don't need to worry about issuing a CPWAIT after + * TLB operations, because we expect a pmap_update() to follow. + */ +ENTRY(xscale_tlb_flushID_SE) + mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */ + mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */ + mov pc, lr + +/* + * Cache functions + */ +ENTRY(xscale_cache_flushID) + mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */ + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_flushI) + mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_flushD) + mcr p15, 0, r0, c7, c6, 0 /* flush D cache */ + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_flushI_SE) + mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_flushD_SE) + /* + * Errata (rev < 2): Must clean-dcache-line to an address + * before invalidate-dcache-line to an address, or dirty + * bits will not be cleared in the dcache array. + */ + mcr p15, 0, r0, c7, c10, 1 + mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_cleanD_E) + mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + CPWAIT_AND_RETURN(r0) + +/* + * Information for the XScale cache clean/purge functions: + * + * * Virtual address of the memory region to use + * * Size of memory region + * + * Note the virtual address for the Data cache clean operation + * does not need to be backed by physical memory, since no loads + * will actually be performed by the allocate-line operation. + * + * Note that the Mini-Data cache MUST be cleaned by executing + * loads from memory mapped into a region reserved exclusively + * for cleaning of the Mini-Data cache. + */ + .data + + .global _C_LABEL(xscale_cache_clean_addr) +_C_LABEL(xscale_cache_clean_addr): + .word 0x00000000 + + .global _C_LABEL(xscale_cache_clean_size) +_C_LABEL(xscale_cache_clean_size): + .word DCACHE_SIZE + +# .global _C_LABEL(xscale_minidata_clean_addr) +#_C_LABEL(xscale_minidata_clean_addr): +# .word 0x00000000 + +# .global _C_LABEL(xscale_minidata_clean_size) +#_C_LABEL(xscale_minidata_clean_size): +# .word 0x00000800 + + .text + +.Lxscale_cache_clean_addr: + .word _C_LABEL(xscale_cache_clean_addr) +.Lxscale_cache_clean_size: + .word _C_LABEL(xscale_cache_clean_size) + +.Lxscale_minidata_clean_addr: + .word _C_LABEL(xscale_minidata_clean_addr) +.Lxscale_minidata_clean_size: + .word _C_LABEL(xscale_minidata_clean_size) + +#ifdef CACHE_CLEAN_BLOCK_INTR +#define XSCALE_CACHE_CLEAN_BLOCK \ + mrs r3, cpsr_all ; \ + orr r0, r3, #(I32_bit | F32_bit) ; \ + msr cpsr_all, r0 + +#define XSCALE_CACHE_CLEAN_UNBLOCK \ + msr cpsr_all, r3 +#else +#define XSCALE_CACHE_CLEAN_BLOCK \ + ldr r3, .Lblock_userspace_access ; \ + ldr ip, [r3] ; \ + orr r0, ip, #1 ; \ + str r0, [r3] + +#define XSCALE_CACHE_CLEAN_UNBLOCK \ + str ip, [r3] +#endif /* CACHE_CLEAN_BLOCK_INTR */ + +#define XSCALE_CACHE_CLEAN_PROLOGUE \ + XSCALE_CACHE_CLEAN_BLOCK ; \ + ldr r2, .Lxscale_cache_clean_addr ; \ + ldmia r2, {r0, r1} ; \ + /* \ + * BUG ALERT! \ + * \ + * The XScale core has a strange cache eviction bug, which \ + * requires us to use 2x the cache size for the cache clean \ + * and for that area to be aligned to 2 * cache size. \ + * \ + * The work-around is to use 2 areas for cache clean, and to \ + * alternate between them whenever this is done. No one knows \ + * why the work-around works (mmm!). \ + */ \ + eor r0, r0, #(DCACHE_SIZE) ; \ + str r0, [r2] ; \ + add r0, r0, r1 + +#define XSCALE_CACHE_CLEAN_EPILOGUE \ + XSCALE_CACHE_CLEAN_UNBLOCK + +ENTRY_NP(xscale_cache_syncI) +ENTRY_NP(xscale_cache_purgeID) + mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */ +ENTRY_NP(xscale_cache_cleanID) +ENTRY_NP(xscale_cache_purgeD) +ENTRY(xscale_cache_cleanD) + XSCALE_CACHE_CLEAN_PROLOGUE + +1: subs r0, r0, #32 + mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */ + subs r1, r1, #32 + bne 1b + + CPWAIT(r0) + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT(r0) + + XSCALE_CACHE_CLEAN_EPILOGUE + mov pc, lr + +/* + * Clean the mini-data cache. + * + * It's expected that we only use the mini-data cache for + * kernel addresses, so there is no need to purge it on + * context switch, and no need to prevent userspace access + * while we clean it. + */ +ENTRY(xscale_cache_clean_minidata) + ldr r2, .Lxscale_minidata_clean_addr + ldmia r2, {r0, r1} +1: ldr r3, [r0], #32 + subs r1, r1, #32 + bne 1b + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r1) + +ENTRY(xscale_cache_purgeID_E) + mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + CPWAIT(r1) + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ + mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + CPWAIT_AND_RETURN(r1) + +ENTRY(xscale_cache_purgeD_E) + mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + CPWAIT(r1) + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + CPWAIT_AND_RETURN(r1) + +/* + * Soft functions + */ +/* xscale_cache_syncI is identical to xscale_cache_purgeID */ + +ENTRY(xscale_cache_cleanID_rng) +ENTRY(xscale_cache_cleanD_rng) + cmp r1, #0x4000 + bcs _C_LABEL(xscale_cache_cleanID) + + and r2, r0, #0x1f + add r1, r1, r2 + bic r0, r0, #0x1f + +1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + add r0, r0, #32 + subs r1, r1, #32 + bhi 1b + + CPWAIT(r0) + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_purgeID_rng) + cmp r1, #0x4000 + bcs _C_LABEL(xscale_cache_purgeID) + + and r2, r0, #0x1f + add r1, r1, r2 + bic r0, r0, #0x1f + +1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ + add r0, r0, #32 + subs r1, r1, #32 + bhi 1b + + CPWAIT(r0) + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_purgeD_rng) + cmp r1, #0x4000 + bcs _C_LABEL(xscale_cache_purgeD) + + and r2, r0, #0x1f + add r1, r1, r2 + bic r0, r0, #0x1f + +1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + add r0, r0, #32 + subs r1, r1, #32 + bhi 1b + + CPWAIT(r0) + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_syncI_rng) + cmp r1, #0x4000 + bcs _C_LABEL(xscale_cache_syncI) + + and r2, r0, #0x1f + add r1, r1, r2 + bic r0, r0, #0x1f + +1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ + mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ + add r0, r0, #32 + subs r1, r1, #32 + bhi 1b + + CPWAIT(r0) + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r0) + +ENTRY(xscale_cache_flushD_rng) + and r2, r0, #0x1f + add r1, r1, r2 + bic r0, r0, #0x1f + +1: mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ + add r0, r0, #32 + subs r1, r1, #32 + bhi 1b + + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ + + CPWAIT_AND_RETURN(r0) + +/* + * Context switch. + * + * These is the CPU-specific parts of the context switcher cpu_switch() + * These functions actually perform the TTB reload. + * + * NOTE: Special calling convention + * r1, r4-r13 must be preserved + */ +ENTRY(xscale_context_switch) + /* + * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. + * Thus the data cache will contain only kernel data and the + * instruction cache will contain only kernel code, and all + * kernel mappings are shared by all processes. + */ + + /* Write the TTB */ + mcr p15, 0, r0, c2, c0, 0 + + /* If we have updated the TTB we must flush the TLB */ + mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */ + + CPWAIT_AND_RETURN(r0) + +/* + * xscale_cpu_sleep + * + * This is called when there is nothing on any of the run queues. + * We go into IDLE mode so that any IRQ or FIQ will awaken us. + * + * If this is called with anything other than ARM_SLEEP_MODE_IDLE, + * ignore it. + */ +ENTRY(xscale_cpu_sleep) + tst r0, #0x00000000 + bne 1f + mov r0, #0x1 + mcr p14, 0, r0, c7, c0, 0 + +1: + mov pc, lr diff --git a/sys/arch/arm/conf/ldscript.head b/sys/arch/arm/conf/ldscript.head new file mode 100644 index 00000000000..58e099f1d5d --- /dev/null +++ b/sys/arch/arm/conf/ldscript.head @@ -0,0 +1,25 @@ +/* $NetBSD: ldscript.evbarm,v 1.2 2003/03/05 23:54:22 thorpej Exp $ +*/ + +OUTPUT_ARCH(arm) +ENTRY(KERNEL_BASE_phys) +SECTIONS +{ + KERNEL_BASE_phys = @KERNEL_BASE_PHYS@; + KERNEL_BASE_virt = @KERNEL_BASE_VIRT@; + + /* Kernel start: */ + .start (KERNEL_BASE_phys) : + { + *(.start) + } =0 + + /* Read-only sections, merged into text segment: */ + .text (KERNEL_BASE_virt + SIZEOF(.start)) : + AT (LOADADDR(.start) + SIZEOF(.start)) + { + *(.text) + *(.text.*) + *(.stub) + *(.glue_7t) *(.glue_7) + *(.rodata) *(.rodata.*) diff --git a/sys/arch/arm/conf/ldscript.tail b/sys/arch/arm/conf/ldscript.tail new file mode 100644 index 00000000000..b6af89f2632 --- /dev/null +++ b/sys/arch/arm/conf/ldscript.tail @@ -0,0 +1,52 @@ + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + /* Adjust the address for the data segment to start on the next page + boundary. */ + . = ALIGN(0x8000); + .data : + AT (LOADADDR(.text) + (ADDR(.data) - ADDR(.text))) + { + __data_start = . ; + *(.data) + *(.data.*) + } + .sdata : + AT (LOADADDR(.data) + (ADDR(.sdata) - ADDR(.data))) + { + *(.sdata) + *(.sdata.*) + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + _bss_end__ = . ; __bss_end__ = . ; __end__ = . ; + PROVIDE (end = .); +} + diff --git a/sys/arch/arm/sa11x0/sa1111_reg.h b/sys/arch/arm/sa11x0/sa1111_reg.h new file mode 100644 index 00000000000..f34a7dcaf81 --- /dev/null +++ b/sys/arch/arm/sa11x0/sa1111_reg.h @@ -0,0 +1,128 @@ +/* $NetBSD: sa1111_reg.h,v 1.3 2002/12/18 04:09:31 bsh Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_SA11X0_SA1111_REG_H +#define _ARM_SA11X0_SA1111_REG_H + + +/* Interrupt Controller */ + +/* number of interrupt bits */ +#define SACCIC_LEN 55 + +/* System Bus Interface */ +#define SACCSBI_SKCR 0x0000 +#define SKCR_PLLBYPASS (1<<0) +#define SKCR_RCLKEN (1<<1) +#define SKCR_SLEEP (1<<2) +#define SKCR_DOZE (1<<3) +#define SKCR_VCOOFF (1<<4) +#define SKCR_RDYEN (1<<7) +#define SKCR_SELAC (1<<8) /* AC Link or I2S */ +#define SKCR_NOEEN (1<<12) /* Enable nOE */ +#define SACCSBI_SMCR 0x0004 +#define SACCSBI_SKID 0x0008 + +/* System Controller */ +#define SACCSC_SKPCR 0x0200 + +/* USB Host Controller */ +#define SACCUSB_REVISION 0x0400 +#define SACCUSB_CONTROL 0x0404 +#define SACCUSB_STATUS 0x0408 +#define SACCUSB_RESET 0x051C + +/* Interrupt Controller */ +#define SACCIC_INTTEST0 0x1600 +#define SACCIC_INTTEST1 0x1604 +#define SACCIC_INTEN0 0x1608 +#define SACCIC_INTEN1 0x160C +#define SACCIC_INTPOL0 0x1610 +#define SACCIC_INTPOL1 0x1614 +#define SACCIC_INTTSTSEL 0x1618 +#define SACCIC_INTSTATCLR0 0x161C +#define SACCIC_INTSTATCLR1 0x1620 +#define SACCIC_INTSET0 0x1624 +#define SACCIC_INTSET1 0x1628 +#define SACCIC_WAKE_EN0 0x162C +#define SACCIC_WAKE_EN1 0x1630 +#define SACCIC_WAKE_POL0 0x1634 +#define SACCIC_WAKE_POL1 0x1638 + +/* GPIO registers */ +#define SACCGPIOA_DDR 0x1000 /* data direction */ +#define SACCGPIOA_DVR 0x1004 /* data value */ +#define SACCGPIOA_SDR 0x1008 /* sleep direction */ +#define SACCGPIOA_SSR 0x100C /* sleep state */ +#define SACCGPIOB_DDR 0x1010 +#define SACCGPIOB_DVR 0x1014 +#define SACCGPIOB_SDR 0x1018 +#define SACCGPIOB_SSR 0x101C +#define SACCGPIOC_DDR 0x1020 +#define SACCGPIOC_DVR 0x1024 +#define SACCGPIOC_SDR 0x1028 +#define SACCGPIOC_SSR 0x102C + +#define SACC_KBD0 0x0a00 +#define SACC_KBD1 0x0c00 + +#define SACCKBD_CR 0x00 +#define KBDCR_FKC (1<<0) /* Force MSCLK/TPCLK low */ +#define KBDCR_FKD (1<<1) /* Force MSDATA/TPDATA low */ +#define KBDCR_ENA (1<<3) /* Enable */ +#define SACCKBD_STAT 0x04 +#define KBDSTAT_KBC (1<<0) /* KBCLK pin value */ +#define KBDSTAT_KBD (1<<1) /* KBDATA pin value */ +#define KBDSTAT_RXP (1<<2) /* Parity */ +#define KBDSTAT_ENA (1<<3) /* Enable */ +#define KBDSTAT_RXB (1<<4) /* Rx busy */ +#define KBDSTAT_RXF (1<<5) /* Rx full */ +#define KBDSTAT_TXB (1<<6) /* Tx busy */ +#define KBDSTAT_TXE (1<<7) /* Tx empty */ +#define KBDSTAT_STP (1<<8) /* Stop bit error */ +#define SACCKBD_DATA 0x08 +#define SACCKBD_CLKDIV 0x0c +#define KBDCLKDIV_DIV8 0 +#define KBDCLKDIV_DIV4 1 +#define KBDCLKDIV_DIV2 2 +#define SACCKBD_CLKPRECNT 0x10 +#define SACCKBD_KBDITR 0x14 /* Interrupt test */ + +#define SACCKBD_SIZE 0x18 + +#endif /* _ARM_SA11X0_SA1111_REG_H */ diff --git a/sys/arch/arm/sa11x0/sa11x0_ost.c b/sys/arch/arm/sa11x0/sa11x0_ost.c new file mode 100644 index 00000000000..76a02f3080b --- /dev/null +++ b/sys/arch/arm/sa11x0/sa11x0_ost.c @@ -0,0 +1,369 @@ +/* $NetBSD: sa11x0_ost.c,v 1.11 2003/07/15 00:24:51 lukem Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro and Ichiro FUKUHARA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: sa11x0_ost.c,v 1.11 2003/07/15 00:24:51 lukem Exp $"); +*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/time.h> +#include <sys/device.h> + +#include <machine/bus.h> +#include <machine/intr.h> + +#include <arm/cpufunc.h> + +#include <arm/sa11x0/sa11x0_reg.h> +#include <arm/sa11x0/sa11x0_var.h> +#include <arm/sa11x0/sa11x0_ostreg.h> + +static int saost_match(struct device *, void *, void *); +static void saost_attach(struct device *, struct device *, void *); + +int gettick(void); +static int clockintr(void *); +static int statintr(void *); +void rtcinit(void); + +struct saost_softc { + struct device sc_dev; + bus_addr_t sc_baseaddr; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + u_int32_t sc_clock_count; + u_int32_t sc_statclock_count; + u_int32_t sc_statclock_step; +}; + +static struct saost_softc *saost_sc = NULL; + +#define TIMER_FREQUENCY 3686400 /* 3.6864MHz */ +#define TICKS_PER_MICROSECOND (TIMER_FREQUENCY/1000000) + +#ifndef STATHZ +#define STATHZ 64 +#endif + +#if 0 +CFATTACH_DECL(saost, sizeof(struct saost_softc), + saost_match, saost_attach, NULL, NULL); +#endif + +struct cfattach saost_ca = { + sizeof (struct saost_softc), saost_match, saost_attach +}; + +struct cfdriver saost_cd = { + NULL, "saost", DV_DULL +}; + +static int +saost_match(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + return (1); +} + +void +saost_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct saost_softc *sc = (struct saost_softc*)self; + struct sa11x0_attach_args *sa = aux; + + printf("\n"); + + sc->sc_iot = sa->sa_iot; + sc->sc_baseaddr = sa->sa_addr; + + saost_sc = sc; + + if(bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, + &sc->sc_ioh)) + panic("%s: Cannot map registers", self->dv_xname); + + /* disable all channel and clear interrupt status */ + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 0); + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf); + + printf("%s: SA-11x0 OS Timer\n", sc->sc_dev.dv_xname); +} + +static int +clockintr(arg) + void *arg; +{ + struct clockframe *frame = arg; + u_int32_t oscr, nextmatch, oldmatch; + int s; + + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_SR, 1); + + /* schedule next clock intr */ + oldmatch = saost_sc->sc_clock_count; + nextmatch = oldmatch + TIMER_FREQUENCY / hz; + + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0, + nextmatch); + oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + + if ((nextmatch > oldmatch && + (oscr > nextmatch || oscr < oldmatch)) || + (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) { + /* + * we couldn't set the matching register in time. + * just set it to some value so that next interrupt happens. + * XXX is it possible to compansate lost interrupts? + */ + + s = splhigh(); + oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + nextmatch = oscr + 10; + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_MR0, nextmatch); + splx(s); + } + + saost_sc->sc_clock_count = nextmatch; + hardclock(frame); + + return(1); +} + +static int +statintr(arg) + void *arg; +{ + struct clockframe *frame = arg; + u_int32_t oscr, nextmatch, oldmatch; + int s; + + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_SR, 2); + + /* schedule next clock intr */ + oldmatch = saost_sc->sc_statclock_count; + nextmatch = oldmatch + saost_sc->sc_statclock_step; + + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1, + nextmatch); + oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + + if ((nextmatch > oldmatch && + (oscr > nextmatch || oscr < oldmatch)) || + (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) { + /* + * we couldn't set the matching register in time. + * just set it to some value so that next interrupt happens. + * XXX is it possible to compansate lost interrupts? + */ + + s = splhigh(); + oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + nextmatch = oscr + 10; + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_MR1, nextmatch); + splx(s); + } + + saost_sc->sc_statclock_count = nextmatch; + statclock(frame); + + return(1); +} + + +void +setstatclockrate(hz) + int hz; +{ + u_int32_t count; + + saost_sc->sc_statclock_step = TIMER_FREQUENCY / hz; + count = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR); + count += saost_sc->sc_statclock_step; + saost_sc->sc_statclock_count = count; + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_MR1, count); +} + +void +cpu_initclocks() +{ + stathz = STATHZ; + profhz = stathz; + saost_sc->sc_statclock_step = TIMER_FREQUENCY / stathz; + + printf("clock: hz=%d stathz = %d\n", hz, stathz); + + /* Use the channels 0 and 1 for hardclock and statclock, respectively */ + saost_sc->sc_clock_count = TIMER_FREQUENCY / hz; + saost_sc->sc_statclock_count = TIMER_FREQUENCY / stathz; + + sa11x0_intr_establish(0, 26, 1, IPL_CLOCK, clockintr, 0); + sa11x0_intr_establish(0, 27, 1, IPL_CLOCK, statintr, 0); + + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf); + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 3); + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0, + saost_sc->sc_clock_count); + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1, + saost_sc->sc_statclock_count); + + /* Zero the counter value */ + bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR, 0); +} + +int +gettick() +{ + int counter; + u_int savedints; + savedints = disable_interrupts(I32_bit); + + counter = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + + restore_interrupts(savedints); + return counter; +} + +void +microtime(tvp) + register struct timeval *tvp; +{ + int s, tm, deltatm; + static struct timeval lasttime; + + if(saost_sc == NULL) { + tvp->tv_sec = 0; + tvp->tv_usec = 0; + return; + } + + s = splhigh(); + tm = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, + SAOST_CR); + + deltatm = saost_sc->sc_clock_count - tm; + +#ifdef OST_DEBUG + printf("deltatm = %d\n",deltatm); +#endif + + *tvp = time; + tvp->tv_usec++; /* XXX */ + while (tvp->tv_usec >= 1000000) { + tvp->tv_sec++; + tvp->tv_usec -= 1000000; + } + + if (tvp->tv_sec == lasttime.tv_sec && + tvp->tv_usec <= lasttime.tv_usec && + (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) + { + tvp->tv_sec++; + tvp->tv_usec -= 1000000; + } + lasttime = *tvp; + splx(s); +} + +void +delay(usecs) + u_int usecs; +{ + u_int32_t tick, otick, delta; + int j, csec, usec; + + csec = usecs / 10000; + usec = usecs % 10000; + + usecs = (TIMER_FREQUENCY / 100) * csec + + (TIMER_FREQUENCY / 100) * usec / 10000; + + if (! saost_sc) { + /* clock isn't initialized yet */ + for(; usecs > 0; usecs--) + for(j = 100; j > 0; j--) + ; + return; + } + + otick = gettick(); + + while (1) { + for(j = 100; j > 0; j--) + ; + tick = gettick(); + delta = tick - otick; + if (delta > usecs) + break; + usecs -= delta; + otick = tick; + } +} + +void +resettodr() +{ +} + +void +inittodr(base) + time_t base; +{ + time.tv_sec = base; + time.tv_usec = 0; +} diff --git a/sys/arch/arm/sa11x0/sa11x0_ostreg.h b/sys/arch/arm/sa11x0/sa11x0_ostreg.h new file mode 100644 index 00000000000..0db7282c265 --- /dev/null +++ b/sys/arch/arm/sa11x0/sa11x0_ostreg.h @@ -0,0 +1,80 @@ +/* $NetBSD: sa11x0_ostreg.h,v 1.1 2001/07/08 23:37:53 rjs Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ichiro FUKUHARA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * SA-11x0 OS Timer Register + */ + +/* OS Timer Match Register */ +#define SAOST_MR0 0x00 +#define SAOST_MR1 0x04 +#define SAOST_MR2 0x08 +#define SAOST_MR3 0x0C + +/* OS Timer Count Register */ +#define SAOST_CR 0x10 + +/* OS Timer Status Register */ +#define SAOST_SR 0x14 +#define SR_CH0 (1<<0) +#define SR_CH1 (1<<1) +#define SR_CH2 (1<<2) +#define SR_CH3 (1<<3) + +/* OS Timer Watchdog Match Enable Register */ +#define SAOST_WR 0x18 + +/* OS Timer Interrupt Enable Register */ +#define SAOST_IR 0x1C + +/* + * SA-1110 Real Time Clock + */ + +/* RTC Alarm Register */ +#define SARTC_AR 0x00 + +/* RTC Counter Register */ +#define SARTC_CR 0x04 + +/* RTC Trim Register */ +#define SARTC_TR 0x08 + +/* RTC Status Register */ +#define SARTC_SR 0x0C + +/* end of sa11x0_ostreg.h */ diff --git a/sys/arch/arm/sa11x0/sa11x0_reg.h b/sys/arch/arm/sa11x0/sa11x0_reg.h new file mode 100644 index 00000000000..3c94c1725ee --- /dev/null +++ b/sys/arch/arm/sa11x0/sa11x0_reg.h @@ -0,0 +1,78 @@ +/* $NetBSD: sa11x0_reg.h,v 1.4 2002/07/19 18:26:56 ichiro Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_SA11X0_REG_H_ +#define _ARM_SA11X0_REG_H_ + +/* Physical register base addresses */ +#define SAOST_BASE 0x90000000 /* OS Timer */ +#define SARTC_BASE 0x90010000 /* Real-Time Clock */ +#define SAPMR_BASE 0x90020000 /* Power Manager */ +#define SARCR_BASE 0x90030000 /* Reset Controller */ +#define SAGPIO_BASE 0x90040000 /* GPIO */ +#define SAIPIC_BASE 0x90050000 /* Interrupt Controller */ +#define SAPPC_BASE 0x90060000 /* Peripheral Pin Controller */ +#define SAUDC_BASE 0x80000000 /* USB Device Controller*/ +#define SACOM1_BASE 0x80010000 /* GPCLK/UART 1 */ +#define SACOM3_HW_BASE 0x80050000 /* UART 3 */ +#define SAMCP_BASE 0x80060000 /* MCP Controller */ +#define SASSP_BASE 0x80070000 /* Synchronous serial port */ + +#define SADMAC_BASE 0xB0000000 /* DMA Controller */ +#define SALCD_BASE 0xB0100000 /* LCD */ + +/* Register base virtual addresses mapped by initarm() */ +#define SACOM3_BASE 0xd000d000 + +/* Interrupt controller registers */ +#define SAIPIC_NPORTS 9 +#define SAIPIC_IP 0x00 /* IRQ pending register */ +#define SAIPIC_MR 0x04 /* Mask register */ +#define SAIPIC_LR 0x08 /* Level register */ +#define SAIPIC_FP 0x10 /* FIQ pending register */ +#define SAIPIC_PR 0x20 /* Pending register */ +#define SAIPIC_CR 0x0C /* Control register */ + +/* width of interrupt controller */ +#define ICU_LEN 32 + +/* Reset controller registers */ +#define SARCR_RSRR 0x0 /* Software reset register */ +#define SARCR_RCSR 0x4 /* Reset status register */ +#define SARCR_TUCR 0x8 /* Test Unit control reg */ + +#endif /* _ARM_SA11X0_REG_H_ */ diff --git a/sys/arch/arm/sa11x0/sa11x0_var.h b/sys/arch/arm/sa11x0/sa11x0_var.h new file mode 100644 index 00000000000..5c966a0bd92 --- /dev/null +++ b/sys/arch/arm/sa11x0/sa11x0_var.h @@ -0,0 +1,76 @@ +/* $NetBSD: sa11x0_var.h,v 1.4 2003/04/14 14:18:41 rjs Exp $ */ + +/*- + * Copyright (c) 2001, The NetBSD Foundation, Inc. All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro and Ichiro FUKUHARA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _SA11X0_VAR_H +#define _SA11X0_VAR_H + +#include <sys/conf.h> +#include <sys/device.h> + +#include <machine/bus.h> + +struct sa11x0_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_space_handle_t sc_gpioh; + bus_space_handle_t sc_ppch; + bus_space_handle_t sc_dmach; + bus_space_handle_t sc_reseth; + u_int32_t sc_intrmask; +}; + +/* Attach args all devices */ + +typedef void *sa11x0_chipset_tag_t; + +struct sa11x0_attach_args { + sa11x0_chipset_tag_t sa_sc; + bus_space_tag_t sa_iot; /* Bus tag */ + bus_addr_t sa_addr; /* i/o address */ + bus_size_t sa_size; + + int sa_intr; + int sa_gpio; +}; + +void *sa11x0_intr_establish(sa11x0_chipset_tag_t, int, int, int, + int (*)(void *), void *); +void sa11x0_intr_disestablish(sa11x0_chipset_tag_t, void *); + +#endif /* _SA11X0_VAR_H */ diff --git a/sys/arch/arm/xscale/files.pxa2x0 b/sys/arch/arm/xscale/files.pxa2x0 new file mode 100644 index 00000000000..406c82f944c --- /dev/null +++ b/sys/arch/arm/xscale/files.pxa2x0 @@ -0,0 +1,59 @@ +# $NetBSD: files.pxa2x0,v 1.6 2004/05/01 19:09:14 thorpej Exp $ +# +# Configuration info for Intel PXA2[51]0 CPU support +# + +file arch/arm/arm/softintr.c # Use the generic ARM soft interrupt code. + +# PXA2[51]0's integrated peripherals bus. +define pxaip { [addr=-1], [size=0], [intr=-1], [index=-1]} +device pxaip +attach pxaip at mainbus +file arch/arm/xscale/pxa2x0.c +file arch/arm/arm/irq_dispatch.S +file arch/arm/xscale/pxa2x0_space.c +#file arch/arm/xscale/pxa2x0_freqchg.S +file arch/arm/xscale/pxa2x0_dma.c +#file arch/arm/xscale/pxa2x0_i2c.c + +# Cotulla integrated peripherals. + +# INTC controller +device pxaintc +attach pxaintc at pxaip +file arch/arm/xscale/pxa2x0_intr.c pxaintc needs-flag +#defflag opt_pxa2x0_gpio.h PXAGPIO_HAS_GPION_INTRS + +# GPIO controller +device pxagpio +attach pxagpio at pxaip +file arch/arm/xscale/pxa2x0_gpio.c pxagpio needs-flag + +# clock device +# PXA2x0's built-in timer is compatible to SA-1110. +device saost +attach saost at pxaip +file arch/arm/sa11x0/sa11x0_ost.c saost needs-flag + +# NS16550 compatible serial ports +attach com at pxaip with pxauart +file arch/arm/xscale/pxa2x0_com.c pxauart +file arch/arm/xscale/pxa2x0_a4x_space.c pxauart | obio +file arch/arm/xscale/pxa2x0_a4x_io.S pxauart | obio +#defflag opt_com.h FFUARTCONSOLE STUARTCONSOLE BTUARTCONSOLE + +# LCD controller +device lcd: wsemuldisplaydev, rasops16, rasops8, rasops4 +file arch/arm/xscale/pxa2x0_lcd.c lcd needs-flag + +include "dev/pcmcia/files.pcmcia" + +# PCMCIA controller +device pxapcic: pcmciabus +attach pxapcic at pxaip +file arch/arm/xscale/pxa2x0_pcic.c pxapcic + +# XXX this is a hack to use dev/pcmcia without fdc.c +device fdc + +file arch/arm/xscale/pxacom.c com & pxauart needs-flag diff --git a/sys/arch/arm/xscale/pxa2x0.c b/sys/arch/arm/xscale/pxa2x0.c new file mode 100644 index 00000000000..99d6dc4d569 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0.c @@ -0,0 +1,393 @@ +/* $NetBSD: pxa2x0.c,v 1.5 2003/12/12 16:42:44 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * Autoconfiguration support for the Intel PXA2[15]0 application + * processor. This code is derived from arm/sa11x0/sa11x0.c + */ + +/*- + * Copyright (c) 2001, The NetBSD Foundation, Inc. All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro and Ichiro FUKUHARA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + */ +/*- + * Copyright (c) 1999 + * Shin Takemura and PocketBSD Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the PocketBSD project + * and its contributors. + * 4. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0.c,v 1.5 2003/12/12 16:42:44 thorpej Exp $"); +*/ + +#include "pxaintc.h" +#include "pxagpio.h" +#if 0 +#include "pxadmac.h" /* Not yet */ +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/reboot.h> + +#include <machine/cpu.h> +#include <machine/bus.h> + +#include <arm/cpufunc.h> +#include <arm/mainbus/mainbus.h> +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0var.h> + +struct pxaip_softc { + struct device sc_dev; + bus_space_tag_t sc_bust; + bus_dma_tag_t sc_dmat; + bus_space_handle_t sc_bush_clk; +}; + +/* prototypes */ +static int pxaip_match(struct device *, void *, void *); +static void pxaip_attach(struct device *, struct device *, void *); +static int pxaip_search(struct device *, void *, void *); +static void pxaip_attach_critical(struct pxaip_softc *); +static int pxaip_print(void *, const char *); + +int pxaip_measure_cpuclock(struct pxaip_softc *); + +/* attach structures */ +#ifdef __NetBSD__ +CFATTACH_DECL(pxaip, sizeof(struct pxaip_softc), + pxaip_match, pxaip_attach, NULL, NULL); +#else +struct cfattach pxaip_ca = { + sizeof(struct pxaip_softc), pxaip_match, pxaip_attach +}; + +struct cfdriver pxaip_cd = { + NULL, "pxaip", DV_DULL +}; +#endif + +static struct pxaip_softc *pxaip_sc; + +static int +pxaip_match(struct device *parent, void *match, void *aux) +{ + + return 1; +} + +static void +pxaip_attach(struct device *parent, struct device *self, void *aux) +{ + struct pxaip_softc *sc = (struct pxaip_softc *)self; + int cpuclock; + + pxaip_sc = sc; + sc->sc_bust = &pxa2x0_bs_tag; + sc->sc_dmat = &pxa2x0_bus_dma_tag; + + printf(": PXA2x0 Onchip Peripheral Bus "); + + if (bus_space_map(sc->sc_bust, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE, + 0, &sc->sc_bush_clk)) + panic("pxaip_attach: failed to map CLKMAN"); + + /* + * Calculate clock speed + * This takes 2 secs at most. + */ +#if 0 + cpuclock = pxaip_measure_cpuclock(sc) / 1000; +#else + cpuclock = 398108; + +#endif + printf(" CPU clock = %d.%03d MHz\n", cpuclock/1000, cpuclock%1000 ); + + /* + * Attach critical devices + */ + pxaip_attach_critical(sc); + + /* + * Attach all other devices + */ + config_search(pxaip_search, self, sc); + +} + +static int +pxaip_search(struct device *parent, void *c, void *aux) +{ + struct pxaip_softc *sc = aux; + struct pxaip_attach_args aa; + struct cfdata *cf = c; + + aa.pxa_iot = sc->sc_bust; + aa.pxa_dmat = sc->sc_dmat; +#if 0 + aa.pxa_addr = cf->cf_addr; + aa.pxa_size = cf->cf_size; + aa.pxa_intr = cf->cf_intr; + aa.pxa_index = cf->cf_index; +#else + aa.pxa_addr = (cf->cf_loc)[0]; + aa.pxa_size = (cf->cf_loc)[1]; + aa.pxa_intr = (cf->cf_loc)[2]; + aa.pxa_index = (cf->cf_loc)[3]; +#endif + + config_found(parent, &aa, pxaip_print); + + return 0; +} + +static void +pxaip_attach_critical(struct pxaip_softc *sc) +{ + struct pxaip_attach_args aa; + + aa.pxa_iot = sc->sc_bust; + aa.pxa_dmat = sc->sc_dmat; + aa.pxa_addr = PXA2X0_INTCTL_BASE; + aa.pxa_size = PXA2X0_INTCTL_SIZE; + aa.pxa_intr = -1; + if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL) + panic("pxaip_attach_critical: failed to attach INTC!"); + +#if NPXAGPIO > 0 + aa.pxa_iot = sc->sc_bust; + aa.pxa_dmat = sc->sc_dmat; + aa.pxa_addr = PXA2X0_GPIO_BASE; + aa.pxa_size = PXA2X0_GPIO_SIZE; + aa.pxa_intr = -1; + if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL) + panic("pxaip_attach_critical: failed to attach GPIO!"); +#endif + +#if NPXADMAC > 0 + aa.pxa_iot = sc->sc_bust; + aa.pxa_dmat = sc->sc_dmat; + aa.pxa_addr = PXA2X0_DMAC_BASE; + aa.pxa_size = PXA2X0_DMAC_SIZE; + aa.pxa_intr = PXA2X0_INT_DMA; + if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL) + panic("pxaip_attach_critical: failed to attach DMAC!"); +#endif +} + +static int +pxaip_print(void *aux, const char *name) +{ + struct pxaip_attach_args *sa = (struct pxaip_attach_args*)aux; + + if (sa->pxa_addr != -1) { + printf(" addr 0x%lx", sa->pxa_addr); + if (sa->pxa_size > -1) + printf("-0x%lx", sa->pxa_addr + sa->pxa_size-1); + } + if (sa->pxa_intr != -1) + printf(" intr %d", sa->pxa_intr); + + return (UNCONF); +} + +static inline uint32_t +read_clock_counter(void) +{ + uint32_t x; + __asm __volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (x) ); + + return x; +} + +int +pxaip_measure_cpuclock(struct pxaip_softc *sc) +{ + uint32_t rtc0, rtc1, start, end; + uint32_t pmcr_save; + bus_space_handle_t ioh; + int irq; + + if (bus_space_map(sc->sc_bust, PXA2X0_RTC_BASE, PXA2X0_RTC_SIZE, 0, + &ioh)) + panic("pxaip_measure_cpuclock: can't map RTC"); + + irq = disable_interrupts(I32_bit|F32_bit); + + __asm __volatile( "mrc p14, 0, %0, c0, c0, 0" : "=r" (pmcr_save) ); + /* Enable clock counter */ + __asm __volatile( "mcr p14, 0, %0, c0, c0, 0" : : "r" (0x0001) ); + + rtc0 = bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR); + /* Wait for next second starts */ + while ((rtc1 = bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR)) == rtc0) + ; + start = read_clock_counter(); + while(rtc1 == bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR)) + ; /* Wait for 1sec */ + end = read_clock_counter(); + + __asm __volatile( "mcr p14, 0, %0, c0, c0, 0" : : "r" (pmcr_save) ); + restore_interrupts(irq); + + bus_space_unmap(sc->sc_bust, ioh, PXA2X0_RTC_SIZE); + + return end - start; +} + +void +pxa2x0_turbo_mode( int f ) +{ + __asm __volatile("mcr p14, 0, %0, c6, c0, 0" : : "r" (f)); +} + +void +pxa2x0_probe_sdram(vaddr_t memctl_va, paddr_t *start, paddr_t *size) +{ + u_int32_t mdcnfg, dwid, dcac, drac, dnb; + int i; + + mdcnfg = *((volatile u_int32_t *)(memctl_va + MEMCTL_MDCNFG)); + + /* + * Scan all 4 SDRAM banks + */ + for (i = 0; i < PXA2X0_SDRAM_BANKS; i++) { + start[i] = 0; + size[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("pxa2x0_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 */ + + size[i] = (paddr_t)(dwid * dcac * drac * dnb); + start[i] = PXA2X0_SDRAM0_START + (i * PXA2X0_SDRAM_BANK_SIZE); + } +} + +void +pxa2x0_clkman_config(u_int clk, int enable) +{ + struct pxaip_softc *sc; + u_int32_t rv; + + KDASSERT(pxaip_sc != NULL); + sc = pxaip_sc; + + rv = bus_space_read_4(sc->sc_bust, sc->sc_bush_clk, CLKMAN_CKEN); + rv &= ~clk; + + if (enable) + rv |= clk; + + bus_space_write_4(sc->sc_bust, sc->sc_bush_clk, CLKMAN_CKEN, rv); +} diff --git a/sys/arch/arm/xscale/pxa2x0_a4x_io.S b/sys/arch/arm/xscale/pxa2x0_a4x_io.S new file mode 100644 index 00000000000..475aae4610f --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_a4x_io.S @@ -0,0 +1,103 @@ +/* $NetBSD: pxa2x0_a4x_io.S,v 1.1 2002/10/19 19:31:39 bsh Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * There are simple bus space functions for IO registers mapped at + * 32-bit aligned positions. offset is multiplied by 4. + */ + +#include <machine/asm.h> + +/* + * bus_space I/O functions with offset*4 + */ + +/* + * read single + */ + +ENTRY(a4x_bs_r_1) + ldrb r0, [r1, r2, LSL #2] + mov pc, lr + +ENTRY(a4x_bs_r_2) + mov r2, r2, LSL #2 + ldrh r0, [r1, r2] + mov pc, lr + +ENTRY(a4x_bs_r_4) + ldr r0, [r1, r2, LSL #2] + mov pc, lr + +/* + * write single + */ + +ENTRY(a4x_bs_w_1) + strb r3, [r1, r2, LSL #2] + mov pc, lr + +ENTRY(a4x_bs_w_2) + mov r2, r2, LSL #2 + strh r3, [r1, r2] + mov pc, lr + +ENTRY(a4x_bs_w_4) + str r3, [r1, r2, LSL #2] + mov pc, lr + +/* + * read multiple + */ +ENTRY(a4x_bs_rm_1) + mov r2, r2, LSL #2 + b generic_bs_rm_1 + +ENTRY(a4x_bs_rm_2) + mov r2, r2, LSL #2 + b generic_armv4_bs_rm_2 + + + +/* + * write multiple + */ +ENTRY(a4x_bs_wm_1) + mov r2, r2, LSL #2 + b generic_bs_wm_1 + +ENTRY(a4x_bs_wm_2) + mov r2, r2, LSL #2 + b generic_armv4_bs_wm_2 diff --git a/sys/arch/arm/xscale/pxa2x0_a4x_space.c b/sys/arch/arm/xscale/pxa2x0_a4x_space.c new file mode 100644 index 00000000000..e2f0ac82e04 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_a4x_space.c @@ -0,0 +1,138 @@ +/* $NetBSD: pxa2x0_a4x_space.c,v 1.2 2003/07/15 00:24:54 lukem Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Bus space tag for 8/16-bit devices on 32-bit bus. + * all registers are located at the address of multiple of 4. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_a4x_space.c,v 1.2 2003/07/15 00:24:54 lukem Exp $"); +*/ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(pxa2x0); +bs_protos(a4x); +bs_protos(generic); +bs_protos(generic_armv4); +bs_protos(bs_notimpl); + +struct bus_space pxa2x0_a4x_bs_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + pxa2x0_bs_map, + pxa2x0_bs_unmap, + pxa2x0_bs_subregion, + + /* allocation/deallocation */ + pxa2x0_bs_alloc, /* not implemented */ + pxa2x0_bs_free, /* not implemented */ + + /* get kernel virtual address */ + pxa2x0_bs_vaddr, + + /* mmap */ + bs_notimpl_bs_mmap, + + /* barrier */ + pxa2x0_bs_barrier, + + /* read (single) */ + a4x_bs_r_1, + a4x_bs_r_2, + a4x_bs_r_4, + bs_notimpl_bs_r_8, + + /* read multiple */ + a4x_bs_rm_1, + a4x_bs_rm_2, + bs_notimpl_bs_rm_4, + bs_notimpl_bs_rm_8, + + /* read region */ + bs_notimpl_bs_rr_1, + bs_notimpl_bs_rr_2, + bs_notimpl_bs_rr_4, + bs_notimpl_bs_rr_8, + + /* write (single) */ + a4x_bs_w_1, + a4x_bs_w_2, + a4x_bs_w_4, + bs_notimpl_bs_w_8, + + /* write multiple */ + a4x_bs_wm_1, + a4x_bs_wm_2, + bs_notimpl_bs_wm_4, + bs_notimpl_bs_wm_8, + + /* write region */ + bs_notimpl_bs_wr_1, + bs_notimpl_bs_wr_2, + bs_notimpl_bs_wr_4, + bs_notimpl_bs_wr_8, + + /* set multiple */ + bs_notimpl_bs_sm_1, + bs_notimpl_bs_sm_2, + bs_notimpl_bs_sm_4, + bs_notimpl_bs_sm_8, + + /* set region */ + bs_notimpl_bs_sr_1, + bs_notimpl_bs_sr_2, + bs_notimpl_bs_sr_4, + bs_notimpl_bs_sr_8, + + /* copy */ + bs_notimpl_bs_c_1, + bs_notimpl_bs_c_2, + bs_notimpl_bs_c_4, + bs_notimpl_bs_c_8, +}; + + + diff --git a/sys/arch/arm/xscale/pxa2x0_com.c b/sys/arch/arm/xscale/pxa2x0_com.c new file mode 100644 index 00000000000..6ad04cdd01f --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_com.c @@ -0,0 +1,149 @@ +/* $NetBSD: pxa2x0_com.c,v 1.4 2003/07/15 00:24:55 lukem Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_com.c,v 1.4 2003/07/15 00:24:55 lukem Exp $"); +*/ + +#ifndef COM_PXA2X0 +#error "You must use options COM_PXA2X0 to get PXA2x0 serial port support" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/termios.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <arm/xscale/pxacomreg.h> +#include <arm/xscale/pxacomvar.h> + +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0var.h> + +static int pxauart_match(struct device *, void *, void *); +static void pxauart_attach(struct device *, struct device *, void *); + +#ifdef __NetBSD__ +CFATTACH_DECL(pxauart, sizeof(struct com_softc), + pxauart_match, pxauart_attach, NULL, NULL); +#else +struct cfattach pxauart_ca = { + sizeof (struct com_softc), pxauart_match, pxauart_attach +}; + +struct cfdriver pxauart_cd = { + NULL, "pxauart", DV_DULL +}; +#endif + +static int +pxauart_match(struct device *parent, void *cf, void *aux) +{ + struct pxaip_attach_args *pxa = aux; + bus_space_tag_t bt = &pxa2x0_a4x_bs_tag; /* XXX: This sucks */ + bus_space_handle_t bh; + int rv; + + switch (pxa->pxa_addr) { + case PXA2X0_FFUART_BASE: + if (pxa->pxa_intr != PXA2X0_INT_FFUART) + return (0); + break; + + case PXA2X0_STUART_BASE: + if (pxa->pxa_intr != PXA2X0_INT_STUART) + return (0); + break; + + case PXA2X0_BTUART_BASE: /* XXX: Config file option ... */ + if (pxa->pxa_intr != PXA2X0_INT_BTUART) + return (0); + break; + + default: + return (0); + } + + pxa->pxa_size = 0x20; + + { + extern bus_addr_t comconsaddr; + + if (comconsaddr == pxa->pxa_addr) + return (1); + } + + if (bus_space_map(bt, pxa->pxa_addr, pxa->pxa_size, 0, &bh)) + return (0); + + /* Make sure the UART is enabled */ + bus_space_write_1(bt, bh, com_ier, IER_EUART); + + rv = comprobe1(bt, bh); + bus_space_unmap(bt, bh, pxa->pxa_size); + + return (rv); +} + +static void +pxauart_attach(struct device *parent, struct device *self, void *aux) +{ + struct com_softc *sc = (struct com_softc *)self; + struct pxaip_attach_args *pxa = aux; + + sc->sc_iot = &pxa2x0_a4x_bs_tag; /* XXX: This sucks */ + sc->sc_iobase = pxa->pxa_addr; + sc->sc_frequency = PXA2X0_COM_FREQ; + +#if 0 + if (com_is_console(sc->sc_iot, sc->sc_iobase, &sc->sc_ioh) == 0 && + bus_space_map(sc->sc_iot, sc->sc_iobase, pxa->pxa_size, 0, + &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } +#endif + bus_space_map(sc->sc_iot, sc->sc_iobase, pxa->pxa_size, 0, &sc->sc_ioh); + + com_attach_subr(sc); + + pxa2x0_intr_establish(pxa->pxa_intr, IPL_SERIAL, comintr, sc); +} diff --git a/sys/arch/arm/xscale/pxa2x0_dma.c b/sys/arch/arm/xscale/pxa2x0_dma.c new file mode 100644 index 00000000000..14c655e2486 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_dma.c @@ -0,0 +1,75 @@ +/* $NetBSD: pxa2x0_dma.c,v 1.3 2003/08/07 16:58:35 bsh Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * bus dma tag for PXA2[15]0 processor. + * (Currently used only for LCD frame buffer) + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_dma.c,v 1.3 2003/08/07 16:58:35 bsh Exp $"); +*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> + +#include <uvm/uvm_extern.h> + +#define _ARM32_BUS_DMA_PRIVATE +#include <machine/bus.h> + +struct arm32_bus_dma_tag pxa2x0_bus_dma_tag = { + 0, + 0, + NULL, + _bus_dmamap_create, + _bus_dmamap_destroy, + _bus_dmamap_load, + _bus_dmamap_load_mbuf, + _bus_dmamap_load_uio, + _bus_dmamap_load_raw, + _bus_dmamap_unload, + _bus_dmamap_sync, + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap, +}; + diff --git a/sys/arch/arm/xscale/pxa2x0_gpio.c b/sys/arch/arm/xscale/pxa2x0_gpio.c new file mode 100644 index 00000000000..f7b97502ff8 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_gpio.c @@ -0,0 +1,518 @@ +/* $NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $"); +*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0var.h> +#include <arm/xscale/pxa2x0_gpio.h> + +struct gpio_irq_handler { + struct gpio_irq_handler *gh_next; + int (*gh_func)(void *); + void *gh_arg; + int gh_spl; + u_int gh_gpio; +}; + +struct pxagpio_softc { + struct device sc_dev; + bus_space_tag_t sc_bust; + bus_space_handle_t sc_bush; + void *sc_irqcookie[3]; + u_int32_t sc_mask[3]; +#ifdef PXAGPIO_HAS_GPION_INTRS + struct gpio_irq_handler *sc_handlers[GPIO_NPINS]; +#else + struct gpio_irq_handler *sc_handlers[2]; +#endif +}; + +static int pxagpio_match(struct device *, void *, void *); +static void pxagpio_attach(struct device *, struct device *, void *); + +#ifdef __NetBSD__ +CFATTACH_DECL(pxagpio, sizeof(struct pxagpio_softc), + pxagpio_match, pxagpio_attach, NULL, NULL); +#else +struct cfattach pxagpio_ca = { + sizeof (struct pxagpio_softc), pxagpio_match, pxagpio_attach +}; + +struct cfdriver pxagpio_cd = { + NULL, "pxagpio", DV_DULL +}; + +#endif + +static struct pxagpio_softc *pxagpio_softc; +static vaddr_t pxagpio_regs; +#define GPIO_BOOTSTRAP_REG(reg) \ + (*((volatile u_int32_t *)(pxagpio_regs + (reg)))) + +static int gpio_intr0(void *); +static int gpio_intr1(void *); +#ifdef PXAGPIO_HAS_GPION_INTRS +static int gpio_dispatch(struct pxagpio_softc *, int); +static int gpio_intrN(void *); +#endif + +static __inline u_int32_t +pxagpio_reg_read(struct pxagpio_softc *sc, int reg) +{ + if (__predict_true(sc != NULL)) + return (bus_space_read_4(sc->sc_bust, sc->sc_bush, reg)); + else + if (pxagpio_regs) + return (GPIO_BOOTSTRAP_REG(reg)); + panic("pxagpio_reg_read: not bootstrapped"); +} + +static __inline void +pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val) +{ + if (__predict_true(sc != NULL)) + bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, val); + else + if (pxagpio_regs) + GPIO_BOOTSTRAP_REG(reg) = val; + else + panic("pxagpio_reg_write: not bootstrapped"); + return; +} + +static int +pxagpio_match(struct device *parent, void *cf, void *aux) +{ + struct pxaip_attach_args *pxa = aux; + + if (pxagpio_softc != NULL || pxa->pxa_addr != PXA2X0_GPIO_BASE) + return (0); + + pxa->pxa_size = PXA2X0_GPIO_SIZE; + + return (1); +} + +void +pxagpio_attach(struct device *parent, struct device *self, void *aux) +{ + struct pxagpio_softc *sc = (struct pxagpio_softc *)self; + struct pxaip_attach_args *pxa = aux; + + sc->sc_bust = pxa->pxa_iot; + + printf(": GPIO Controller\n"); + + if (bus_space_map(sc->sc_bust, pxa->pxa_addr, pxa->pxa_size, 0, + &sc->sc_bush)) { + printf("%s: Can't map registers!\n", sc->sc_dev.dv_xname); + return; + } + + memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers)); + + /* + * Disable all GPIO interrupts + */ + pxagpio_reg_write(sc, GPIO_GRER0, 0); + pxagpio_reg_write(sc, GPIO_GRER1, 0); + pxagpio_reg_write(sc, GPIO_GRER2, 0); + pxagpio_reg_write(sc, GPIO_GFER0, 0); + pxagpio_reg_write(sc, GPIO_GFER1, 0); + pxagpio_reg_write(sc, GPIO_GFER2, 0); + pxagpio_reg_write(sc, GPIO_GEDR0, ~0); + pxagpio_reg_write(sc, GPIO_GEDR1, ~0); + pxagpio_reg_write(sc, GPIO_GEDR2, ~0); + +#ifdef PXAGPIO_HAS_GPION_INTRS + sc->sc_irqcookie[2] = pxa2x0_intr_establish(PXA2X0_INT_GPION, IPL_BIO, + gpio_intrN, sc); + if (sc->sc_irqcookie[2] == NULL) { + printf("%s: failed to hook main GPIO interrupt\n", + sc->sc_dev.dv_xname); + return; + } + +#endif + + sc->sc_irqcookie[0] = sc->sc_irqcookie[1] = NULL; + + pxagpio_softc = sc; +} + +void +pxa2x0_gpio_bootstrap(vaddr_t gpio_regs) +{ + + pxagpio_regs = gpio_regs; +} + +void * +pxa2x0_gpio_intr_establish(u_int gpio, int level, int spl, int (*func)(void *), + void *arg, char *name) +{ + struct pxagpio_softc *sc = pxagpio_softc; + struct gpio_irq_handler *gh; + u_int32_t bit, reg; + +#ifdef DEBUG +#ifdef PXAGPIO_HAS_GPION_INTRS + if (gpio >= GPIO_NPINS) + panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio); +#else + if (gpio > 1) + panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio); +#endif +#endif + + if (!GPIO_IS_GPIO_IN(pxa2x0_gpio_get_function(gpio))) + panic("pxa2x0_gpio_intr_establish: Pin %d not GPIO_IN", gpio); + + switch (level) { + case IST_EDGE_FALLING: + case IST_EDGE_RISING: + case IST_EDGE_BOTH: + break; + + default: + panic("pxa2x0_gpio_intr_establish: bad level: %d", level); + break; + } + + MALLOC(gh, struct gpio_irq_handler *, sizeof(struct gpio_irq_handler), + M_DEVBUF, M_NOWAIT); + + gh->gh_func = func; + gh->gh_arg = arg; + gh->gh_spl = spl; + gh->gh_gpio = gpio; + + gh->gh_next = sc->sc_handlers[gpio]; + sc->sc_handlers[gpio] = gh; + + if (gpio == 0) { + KDASSERT(sc->sc_irqcookie[0] == NULL); + sc->sc_irqcookie[0] = pxa2x0_intr_establish(PXA2X0_INT_GPIO0, + spl, gpio_intr0, sc); + KDASSERT(sc->sc_irqcookie[0]); + } else + if (gpio == 1) { + KDASSERT(sc->sc_irqcookie[1] == NULL); + sc->sc_irqcookie[1] = pxa2x0_intr_establish(PXA2X0_INT_GPIO1, + spl, gpio_intr1, sc); + KDASSERT(sc->sc_irqcookie[1]); + } + + bit = GPIO_BIT(gpio); + sc->sc_mask[GPIO_BANK(gpio)] |= bit; + + switch (level) { + case IST_EDGE_FALLING: + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio)); + pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), reg | bit); + break; + + case IST_EDGE_RISING: + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio)); + pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), reg | bit); + break; + + case IST_EDGE_BOTH: + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio)); + pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), reg | bit); + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio)); + pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), reg | bit); + break; + } + + return (gh); +} + +void +pxa2x0_gpio_intr_disestablish(void *cookie) +{ + struct pxagpio_softc *sc = pxagpio_softc; + struct gpio_irq_handler *gh = cookie; + u_int32_t bit, reg; + + bit = GPIO_BIT(gh->gh_gpio); + + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio)); + reg &= ~bit; + pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio), reg); + reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio)); + reg &= ~bit; + pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio), reg); + + pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gh->gh_gpio), bit); + + sc->sc_mask[GPIO_BANK(gh->gh_gpio)] &= ~bit; + sc->sc_handlers[gh->gh_gpio] = NULL; + + if (gh->gh_gpio == 0) { +#if 0 + pxa2x0_intr_disestablish(sc->sc_irqcookie[0]); + sc->sc_irqcookie[0] = NULL; +#else + panic("pxa2x0_gpio_intr_disestablish: can't unhook GPIO#0"); +#endif + } else + if (gh->gh_gpio == 1) { +#if 0 + pxa2x0_intr_disestablish(sc->sc_irqcookie[1]); + sc->sc_irqcookie[0] = NULL; +#else + panic("pxa2x0_gpio_intr_disestablish: can't unhook GPIO#0"); +#endif + } + + FREE(gh, M_DEVBUF); +} + +static int +gpio_intr0(void *arg) +{ + struct pxagpio_softc *sc = arg; + +#ifdef DIAGNOSTIC + if (sc->sc_handlers[0] == NULL) { + printf("%s: stray GPIO#0 edge interrupt\n", + sc->sc_dev.dv_xname); + return (0); + } +#endif + + bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 0), + GPIO_BIT(0)); + + return ((sc->sc_handlers[0]->gh_func)(sc->sc_handlers[0]->gh_arg)); +} + +static int +gpio_intr1(void *arg) +{ + struct pxagpio_softc *sc = arg; + +#ifdef DIAGNOSTIC + if (sc->sc_handlers[1] == NULL) { + printf("%s: stray GPIO#1 edge interrupt\n", + sc->sc_dev.dv_xname); + return (0); + } +#endif + + bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 1), + GPIO_BIT(1)); + + return ((sc->sc_handlers[1]->gh_func)(sc->sc_handlers[1]->gh_arg)); +} + +#ifdef PXAGPIO_HAS_GPION_INTRS +static int +gpio_dispatch(struct pxagpio_softc *sc, int gpio_base) +{ + struct gpio_irq_handler **ghp, *gh; + int i, s, handled, pins; + u_int32_t gedr, mask; + int bank; + + /* Fetch bitmap of pending interrupts on this GPIO bank */ + gedr = pxagpio_reg_read(sc, GPIO_REG(GPIO_GEDR0, gpio_base)); + + /* Don't handle GPIO 0/1 here */ + if (gpio_base == 0) + gedr &= ~(GPIO_BIT(0) | GPIO_BIT(1)); + + /* Bail early if there are no pending interrupts in this bank */ + if (gedr == 0) + return (0); + + /* Acknowledge pending interrupts. */ + pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio_base), gedr); + + bank = GPIO_BANK(gpio_base); + + /* + * We're only interested in those for which we have a handler + * registered + */ +#ifdef DEBUG + if ((gedr & sc->sc_mask[bank]) == 0) { + printf("%s: stray GPIO interrupt. Bank %d, GEDR 0x%08x, mask 0x%08x\n", + sc->sc_dev.dv_xname, bank, gedr, sc->sc_mask[bank]); + return (1); /* XXX: Pretend we dealt with it */ + } +#endif + + gedr &= sc->sc_mask[bank]; + ghp = &sc->sc_handlers[gpio_base]; + pins = (gpio_base < 64) ? 32 : 17; + handled = 0; + + for (i = 0, mask = 1; i < pins && gedr; i++, ghp++, mask <<= 1) { + if ((gedr & mask) == 0) + continue; + gedr &= ~mask; + + if ((gh = *ghp) == NULL) { + printf("%s: unhandled GPIO interrupt. GPIO#%d\n", + sc->sc_dev.dv_xname, gpio_base + i); + continue; + } + + s = _splraise(gh->gh_spl); + do { + handled |= (gh->gh_func)(gh->gh_arg); + gh = gh->gh_next; + } while (gh != NULL); + splx(s); + } + + return (handled); +} + +static int +gpio_intrN(void *arg) +{ + struct pxagpio_softc *sc = arg; + int handled; + + handled = gpio_dispatch(sc, 0); + handled |= gpio_dispatch(sc, 32); + handled |= gpio_dispatch(sc, 64); + + return (handled); +} +#endif /* PXAGPIO_HAS_GPION_INTRS */ + +u_int +pxa2x0_gpio_get_function(u_int gpio) +{ + struct pxagpio_softc *sc = pxagpio_softc; + u_int32_t rv, io; + + KDASSERT(gpio < GPIO_NPINS); + + rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio); + rv = GPIO_FN(rv); + + io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)); + if (io & GPIO_BIT(gpio)) + rv |= GPIO_OUT; + + io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio)); + if (io & GPIO_BIT(gpio)) + rv |= GPIO_SET; + + return (rv); +} + +u_int +pxa2x0_gpio_set_function(u_int gpio, u_int fn) +{ + struct pxagpio_softc *sc = pxagpio_softc; + u_int32_t rv, bit; + u_int oldfn; + + KDASSERT(gpio < GPIO_NPINS); + + oldfn = pxa2x0_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, GPIO_REG(GPIO_GPSR0, gpio), bit); + else + pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit); + + /* + * 2. Configure the pin as an input or output as appropriate + */ + rv = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit; + if (GPIO_FN_IS_OUT(fn)) + rv |= bit; + pxagpio_reg_write(sc, 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); +} diff --git a/sys/arch/arm/xscale/pxa2x0_gpio.h b/sys/arch/arm/xscale/pxa2x0_gpio.h new file mode 100644 index 00000000000..50b64023a18 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_gpio.h @@ -0,0 +1,62 @@ +/* $wasabi$ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PXA2X0_GPIO_H +#define _PXA2X0_GPIO_H + +/* + * If you want to fiddle with GPIO registers before the + * driver has been autoconfigured (e.g. from initarm()), + * call this function with the virtual address of the + * GPIO controller's registers + */ +extern void pxa2x0_gpio_bootstrap(vaddr_t); + +/* + * GPIO pin function query/manipulation functions + */ +extern u_int pxa2x0_gpio_get_function(u_int); +extern u_int pxa2x0_gpio_set_function(u_int, u_int); + +/* + * Establish/Disestablish interrupt handlers for GPIO pins + */ +extern void *pxa2x0_gpio_intr_establish(u_int, int, int, + int (*)(void *), void *, char *); +extern void pxa2x0_gpio_intr_disestablish(void *); + +#endif /* _PXA2X0_GPIO_H */ diff --git a/sys/arch/arm/xscale/pxa2x0_intr.c b/sys/arch/arm/xscale/pxa2x0_intr.c new file mode 100644 index 00000000000..91ded6e782a --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_intr.c @@ -0,0 +1,465 @@ +/* $NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * IRQ handler for the Intel PXA2X0 processor. + * It has integrated interrupt controller. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $"); +*/ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/lock.h> + +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0var.h> +#include <arm/xscale/pxa2x0_intr.h> +#include <arm/sa11x0/sa11x0_var.h> + +/* + * INTC autoconf glue + */ +static int pxaintc_match(struct device *, void *, void *); +static void pxaintc_attach(struct device *, struct device *, void *); + +#ifdef __NetBSD__ +CFATTACH_DECL(pxaintc, sizeof(struct device), + pxaintc_match, pxaintc_attach, NULL, NULL); +#else +struct cfattach pxaintc_ca = { + sizeof(struct device), pxaintc_match, pxaintc_attach +}; + +struct cfdriver pxaintc_cd = { + NULL, "pxaintc", DV_DULL +}; + +#endif + +static int pxaintc_attached; + +static int stray_interrupt(void *); +static void init_interrupt_masks(void); + +/* + * interrupt dispatch table. + */ +#ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ +struct intrhand { + TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */ + int (*ih_func)(void *); /* handler */ + void *ih_arg; /* arg for handler */ +}; +#endif + +static struct { +#ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ + TAILQ_HEAD(,intrhand) list; +#else + pxa2x0_irq_handler_t func; +#endif + void *cookie; /* NULL for stackframe */ + /* struct evbnt ev; */ +} handler[ICU_LEN]; + +__volatile int softint_pending; +__volatile int current_spl_level; +__volatile int intr_mask; +/* interrupt masks for each level */ +int pxa2x0_imask[NIPL]; +static int extirq_level[ICU_LEN]; + + +static int +pxaintc_match(struct device *parent, void *cf, void *aux) +{ + struct pxaip_attach_args *pxa = aux; + + if (pxaintc_attached || pxa->pxa_addr != PXA2X0_INTCTL_BASE) + return (0); + + return (1); +} + +void +pxaintc_attach(struct device *parent, struct device *self, void *args) +{ + int i; + + pxaintc_attached = 1; + + printf(": Interrupt Controller\n"); + +#define SAIPIC_ICCR 0x14 + + write_icu(SAIPIC_ICCR, 1); + write_icu(SAIPIC_MR, 0); + + for(i = 0; i < sizeof handler / sizeof handler[0]; ++i){ + handler[i].func = stray_interrupt; + handler[i].cookie = (void *)(u_int32_t) i; + extirq_level[i] = IPL_SERIAL; + } + + init_interrupt_masks(); + + _splraise(IPL_SERIAL); + enable_interrupts(I32_bit); +} + +/* + * Invoked very early on from the board-specific initarm(), in order to + * inform us the virtual address of the interrupt controller's registers. + */ +vaddr_t pxaic_base; +void +pxa2x0_intr_bootstrap(vaddr_t addr) +{ + + pxaic_base = addr; +} + +static __inline void +__raise(int ipl) +{ + + if (current_spl_level < ipl) + pxa2x0_setipl(ipl); +} + + +/* + * Map a software interrupt queue to an interrupt priority level. + */ +static const int si_to_ipl[SI_NQUEUES] = { + IPL_SOFT, /* SI_SOFT */ + IPL_SOFTCLOCK, /* SI_SOFTCLOCK */ + IPL_SOFTNET, /* SI_SOFTNET */ + IPL_SOFTSERIAL, /* SI_SOFTSERIAL */ +}; + +/* + * called from irq_entry. + */ +void +pxa2x0_irq_handler(void *arg) +{ + struct clockframe *frame = arg; + uint32_t irqbits; + int irqno; + int saved_spl_level; + + saved_spl_level = current_spl_level; + + /* get pending IRQs */ + irqbits = read_icu(SAIPIC_IP); + + while ((irqno = find_first_bit(irqbits)) >= 0) { + /* XXX: Shuould we handle IRQs in priority order? */ + + /* raise spl to stop interrupts of lower priorities */ + if (saved_spl_level < extirq_level[irqno]) + pxa2x0_setipl(extirq_level[irqno]); + +#ifdef notyet + /* Enable interrupt */ +#endif +#ifndef MULTIPLE_HANDLERS_ON_ONE_IRQ + (* handler[irqno].func)( + handler[irqno].cookie == 0 + ? frame : handler[irqno].cookie ); +#else + /* process all handlers for this interrupt. + XXX not yet */ +#endif + +#ifdef notyet + /* Disable interrupt */ +#endif + + irqbits &= ~(1<<irqno); + } + + /* restore spl to that was when this interrupt happen */ + pxa2x0_setipl(saved_spl_level); + + if(softint_pending & intr_mask) + pxa2x0_do_pending(); +} + +static int +stray_interrupt(void *cookie) +{ + int irqno = (int)cookie; + printf("stray interrupt %d\n", irqno); + + if (PXA2X0_IRQ_MIN <= irqno && irqno < ICU_LEN){ + int save = disable_interrupts(I32_bit); + write_icu(SAIPIC_MR, + read_icu(SAIPIC_MR) & ~(1U<<irqno)); + restore_interrupts(save); + } + + return 0; +} + + + +/* + * Interrupt Mask Handling + */ + +void +pxa2x0_update_intr_masks(int irqno, int level) +{ + int mask = 1U<<irqno; + int psw = disable_interrupts(I32_bit); + int i; + + for(i = 0; i < level; ++i) + pxa2x0_imask[i] |= mask; /* Enable interrupt at lower level */ + + for( ; i < NIPL-1; ++i) + pxa2x0_imask[i] &= ~mask; /* Disable itnerrupt at upper level */ + + /* + * Enforce a heirarchy that gives "slow" device (or devices with + * limited input buffer space/"real-time" requirements) a better + * chance at not dropping data. + */ + pxa2x0_imask[IPL_BIO] &= pxa2x0_imask[IPL_SOFTNET]; + pxa2x0_imask[IPL_NET] &= pxa2x0_imask[IPL_BIO]; + pxa2x0_imask[IPL_SOFTSERIAL] &= pxa2x0_imask[IPL_NET]; + pxa2x0_imask[IPL_TTY] &= pxa2x0_imask[IPL_SOFTSERIAL]; + + /* + * splvm() blocks all interrupts that use the kernel memory + * allocation facilities. + */ + pxa2x0_imask[IPL_VM] &= pxa2x0_imask[IPL_TTY]; + + /* + * Audio devices are not allowed to perform memory allocation + * in their interrupt routines, and they have fairly "real-time" + * requirements, so give them a high interrupt priority. + */ + pxa2x0_imask[IPL_AUDIO] &= pxa2x0_imask[IPL_VM]; + + /* + * splclock() must block anything that uses the scheduler. + */ + pxa2x0_imask[IPL_CLOCK] &= pxa2x0_imask[IPL_AUDIO]; + + /* + * splhigh() must block "everything". + */ + pxa2x0_imask[IPL_HIGH] &= pxa2x0_imask[IPL_STATCLOCK]; + + /* + * XXX We need serial drivers to run at the absolute highest priority + * in order to avoid overruns, so serial > high. + */ + pxa2x0_imask[IPL_SERIAL] &= pxa2x0_imask[IPL_HIGH]; + + write_icu(SAIPIC_MR, pxa2x0_imask[current_spl_level]); + + restore_interrupts(psw); +} + + +static void +init_interrupt_masks(void) +{ + + memset(pxa2x0_imask, 0, sizeof(pxa2x0_imask)); + + /* + * IPL_NONE has soft interrupts enabled only, at least until + * hardware handlers are installed. + */ + pxa2x0_imask[IPL_NONE] = + SI_TO_IRQBIT(SI_SOFT) | + SI_TO_IRQBIT(SI_SOFTCLOCK) | + SI_TO_IRQBIT(SI_SOFTNET) | + SI_TO_IRQBIT(SI_SOFTSERIAL); + + /* + * Initialize the soft interrupt masks to block themselves. + */ + pxa2x0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT); + pxa2x0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK); + pxa2x0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET); + pxa2x0_imask[IPL_SOFTSERIAL] = ~SI_TO_IRQBIT(SI_SOFTSERIAL); + + pxa2x0_imask[IPL_SOFT] &= pxa2x0_imask[IPL_NONE]; + + /* + * splsoftclock() is the only interface that users of the + * generic software interrupt facility have to block their + * soft intrs, so splsoftclock() must also block IPL_SOFT. + */ + pxa2x0_imask[IPL_SOFTCLOCK] &= pxa2x0_imask[IPL_SOFT]; + + /* + * splsoftnet() must also block splsoftclock(), since we don't + * want timer-driven network events to occur while we're + * processing incoming packets. + */ + pxa2x0_imask[IPL_SOFTNET] &= pxa2x0_imask[IPL_SOFTCLOCK]; +} + +void +pxa2x0_do_pending(void) +{ + static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED; + int oldirqstate, spl_save; + + if (__cpu_simple_lock_try(&processing) == 0) + return; + + spl_save = current_spl_level; + + oldirqstate = disable_interrupts(I32_bit); + +#if 1 +#define DO_SOFTINT(si,ipl) \ + if ((softint_pending & intr_mask) & SI_TO_IRQBIT(si)) { \ + softint_pending &= ~SI_TO_IRQBIT(si); \ + __raise(ipl); \ + restore_interrupts(oldirqstate); \ + softintr_dispatch(si); \ + oldirqstate = disable_interrupts(I32_bit); \ + pxa2x0_setipl(spl_save); \ + } + + do { + DO_SOFTINT(SI_SOFTSERIAL,IPL_SOFTSERIAL); + DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET); + DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK); + DO_SOFTINT(SI_SOFT, IPL_SOFT); + } while( softint_pending & intr_mask ); +#else + while( (si = find_first_bit(softint_pending & intr_mask)) >= 0 ){ + softint_pending &= ~SI_TO_IRQBIT(si); + __raise(si_to_ipl(si)); + restore_interrupts(oldirqstate); + softintr_dispatch(si); + oldirqstate = disable_interrupts(I32_bit); + pxa2x0_setipl(spl_save); + } +#endif + + __cpu_simple_unlock(&processing); + + restore_interrupts(oldirqstate); +} + + +#undef splx +void +splx(int ipl) +{ + + pxa2x0_splx(ipl); +} + +#undef _splraise +int +_splraise(int ipl) +{ + + return pxa2x0_splraise(ipl); +} + +#undef _spllower +int +_spllower(int ipl) +{ + + return pxa2x0_spllower(ipl); +} + +#undef _setsoftintr +void +_setsoftintr(int si) +{ + + return pxa2x0_setsoftintr(si); +} + +void * +pxa2x0_intr_establish(int irqno, int level, + int (*func)(void *), void *cookie) +{ + int psw; + + if (irqno < PXA2X0_IRQ_MIN || irqno >= ICU_LEN) + panic("intr_establish: bogus irq number %d", irqno); + + psw = disable_interrupts(I32_bit); + + handler[irqno].cookie = cookie; + handler[irqno].func = func; + extirq_level[irqno] = level; + pxa2x0_update_intr_masks(irqno, level); + + intr_mask = pxa2x0_imask[current_spl_level]; + + restore_interrupts(psw); + + return (&handler[irqno]); +} + +/* + * Glue for drivers of sa11x0 compatible integrated logics. + */ +void * +sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level, + int (*ih_fun)(void *), void *ih_arg) +{ + + return pxa2x0_intr_establish(irq, level, ih_fun, ih_arg); +} diff --git a/sys/arch/arm/xscale/pxa2x0_intr.h b/sys/arch/arm/xscale/pxa2x0_intr.h new file mode 100644 index 00000000000..e2927875cf0 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_intr.h @@ -0,0 +1,192 @@ +/* $NetBSD: pxa2x0_intr.h,v 1.4 2003/07/05 06:53:08 dogcow Exp $ */ + +/* Derived from i80321_intr.h */ + +/* + * 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. + */ + +#ifndef _PXA2X0_INTR_H_ +#define _PXA2X0_INTR_H_ + +#define ARM_IRQ_HANDLER _C_LABEL(pxa2x0_irq_handler) + +#ifndef _LOCORE + +#define __NEWINTR /* enables new hooks in cpu_fork()/cpu_switch() */ + +#include <arm/armreg.h> +#include <arm/cpufunc.h> +#if 0 +#include <arm/cpu.h> +#include <machine/atomic.h> +#endif +#include <machine/intr.h> +#include <arm/softintr.h> + +#include <arm/xscale/pxa2x0reg.h> + +extern vaddr_t pxaic_base; /* Shared with pxa2x0_irq.S */ +#define read_icu(offset) (*(volatile uint32_t *)(pxaic_base+(offset))) +#define write_icu(offset,value) \ + (*(volatile uint32_t *)(pxaic_base+(offset))=(value)) + +extern __volatile int current_spl_level; +extern __volatile int intr_mask; +extern __volatile int softint_pending; +extern int pxa2x0_imask[]; +void pxa2x0_do_pending(void); + +#define SI_TO_IRQBIT(si) (1U<<(si)) +#if 0 +/* + * Cotulla's integrated ICU doesn't have IRQ0..7, so + * we map software interrupts to bit 0..3 + */ + +static __inline void +pxa2x0_setipl(int new) +{ + current_spl_level = new; + intr_mask = pxa2x0_imask[current_spl_level]; + write_icu( SAIPIC_MR, intr_mask ); +} + + +static __inline void +pxa2x0_splx(int new) +{ + int psw; + + psw = disable_interrupts(I32_bit); + pxa2x0_setipl(new); + restore_interrupts(psw); + + /* If there are software interrupts to process, do it. */ + if (softint_pending & intr_mask) + pxa2x0_do_pending(); +} + + +static __inline int +pxa2x0_splraise(int ipl) +{ + int old, psw; + + old = current_spl_level; + if( ipl > current_spl_level ){ + psw = disable_interrupts(I32_bit); + pxa2x0_setipl(ipl); + restore_interrupts(psw); + } + + return (old); +} + +static __inline int +pxa2x0_spllower(int ipl) +{ + int old = current_spl_level; + int psw = disable_interrupts(I32_bit); + pxa2x0_splx(ipl); + restore_interrupts(psw); + return(old); +} + +static __inline void +pxa2x0_setsoftintr(int si) +{ + atomic_set_bit( (u_int *)&softint_pending, SI_TO_IRQBIT(si) ); + + /* Process unmasked pending soft interrupts. */ + if ( softint_pending & intr_mask ) + pxa2x0_do_pending(); +} +#endif +void pxa2x0_setipl(int new); +void pxa2x0_splx(int new); +int pxa2x0_splraise(int ipl); +int pxa2x0_spllower(int ipl); +void pxa2x0_setsoftintr(int si); + + +/* + * An useful function for interrupt handlers. + * XXX: This shouldn't be here. + */ +static __inline int +find_first_bit( uint32_t bits ) +{ + int count; + + /* since CLZ is available only on ARMv5, this isn't portable + * to all ARM CPUs. This file is for PXA2[15]0 processor. + */ + asm( "clz %0, %1" : "=r" (count) : "r" (bits) ); + return 31-count; +} + + +int _splraise(int); +int _spllower(int); +void splx(int); +void _setsoftintr(int); + +#if !defined(EVBARM_SPL_NOINLINE) + +#define splx(new) pxa2x0_splx(new) +#define _spllower(ipl) pxa2x0_spllower(ipl) +#define _splraise(ipl) pxa2x0_splraise(ipl) +#define _setsoftintr(si) pxa2x0_setsoftintr(si) + +#endif /* !EVBARM_SPL_NOINTR */ + +/* + * This function *MUST* be called very early on in a port's + * initarm() function, before ANY spl*() functions are called. + * + * The parameter is the virtual address of the PXA2x0's Interrupt + * Controller registers. + */ +void pxa2x0_intr_bootstrap(vaddr_t); + +void pxa2x0_irq_handler(void *); +void *pxa2x0_intr_establish(int irqno, int level, + int (*func)(void *), void *cookie); +void pxa2x0_update_intr_masks(int irqno, int level); +extern __volatile int current_spl_level; + +#endif /* ! _LOCORE */ + +#endif /* _PXA2X0_INTR_H_ */ diff --git a/sys/arch/arm/xscale/pxa2x0_lcd.c b/sys/arch/arm/xscale/pxa2x0_lcd.c new file mode 100644 index 00000000000..7dac0e6c77f --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_lcd.c @@ -0,0 +1,743 @@ +/* $NetBSD: pxa2x0_lcd.c,v 1.8 2003/10/03 07:24:05 bsh Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Support PXA2[15]0's integrated LCD controller. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.8 2003/10/03 07:24:05 bsh Exp $"); +*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/kernel.h> /* for cold */ + +#include <uvm/uvm_extern.h> + +#include <dev/cons.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/wscons/wscons_callbacks.h> +#include <dev/rasops/rasops.h> +#include <dev/wsfont/wsfont.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <arm/cpufunc.h> + +#include <arm/xscale/pxa2x0var.h> +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0_lcd.h> +#include <arm/xscale/pxa2x0_gpio.h> + +#include "wsdisplay.h" + +int lcdintr(void *); + +void +pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc *sc, + const struct lcd_panel_geometry *info) +{ + int lines; + bus_space_tag_t iot = sc->iot; + bus_space_handle_t ioh = sc->ioh; + uint32_t ccr0; + + sc->geometry = info; + + ccr0 = LCCR0_IMASK; + if (info->panel_info & LCDPANEL_ACTIVE) + ccr0 |= LCCR0_PAS; /* active mode */ + if ((info->panel_info & (LCDPANEL_DUAL|LCDPANEL_ACTIVE)) + == LCDPANEL_DUAL) + ccr0 |= LCCR0_SDS; /* dual panel */ + if (info->panel_info & LCDPANEL_MONOCHROME) + ccr0 |= LCCR0_CMS; + bus_space_write_4(iot, ioh, LCDC_LCCR0, ccr0); + + bus_space_write_4(iot, ioh, LCDC_LCCR1, + (info->panel_width-1) + | ((info->hsync_pulse_width-1)<<10) + | ((info->end_line_wait-1)<<16) + | ((info->beg_line_wait-1)<<24)); + + if (info->panel_info & LCDPANEL_DUAL) + lines = info->panel_height/2 + info->extra_lines; + else + lines = info->panel_height + info->extra_lines; + + bus_space_write_4(iot, ioh, LCDC_LCCR2, + (lines-1) + | (info->vsync_pulse_width<<10) + | (info->end_frame_wait<<16) + | (info->beg_frame_wait<<24)); + + bus_space_write_4(iot, ioh, LCDC_LCCR3, + (info->pixel_clock_div<<0) + | (info->ac_bias << 8) + | ((info->panel_info & + (LCDPANEL_VSP|LCDPANEL_HSP|LCDPANEL_PCP|LCDPANEL_OEP)) + <<20) + | (4 << 24) /* 16bpp */ + | ((info->panel_info & LCDPANEL_DPC) ? (1<<27) : 0) + ); +} + +void +pxa2x0_lcd_attach_sub(struct pxa2x0_lcd_softc *sc, + struct pxaip_attach_args *pxa, const struct lcd_panel_geometry *geom) +{ + bus_space_tag_t iot = pxa->pxa_iot; + bus_space_handle_t ioh; + int error, nldd; + + sc->n_screens = 0; + LIST_INIT(&sc->screens); + + /* map controller registers */ + error = bus_space_map(iot, PXA2X0_LCDC_BASE, + PXA2X0_LCDC_SIZE, 0, &ioh); + if (error) { + printf(": failed to map registers %d", error); + return; + } + + sc->iot = iot; + sc->ioh = ioh; + sc->dma_tag = &pxa2x0_bus_dma_tag; + + sc->ih = pxa2x0_intr_establish(17, IPL_BIO, lcdintr, sc); + if (sc->ih == NULL) + printf("%s: unable to establish interrupt at irq %d", + sc->dev.dv_xname, 17); + + /* Initialize LCD controller */ + + /* enable clock */ + pxa2x0_clkman_config(CKEN_LCD, 1); + + bus_space_write_4(iot, ioh, LCDC_LCCR0, LCCR0_IMASK); + + /* + * setup GP[77:58] for LCD + */ + /* Always use [FLP]CLK, ACBIAS */ + pxa2x0_gpio_set_function(74, GPIO_ALT_FN_2_OUT); + pxa2x0_gpio_set_function(75, GPIO_ALT_FN_2_OUT); + pxa2x0_gpio_set_function(76, GPIO_ALT_FN_2_OUT); + pxa2x0_gpio_set_function(77, GPIO_ALT_FN_2_OUT); + + if ((geom->panel_info & LCDPANEL_ACTIVE) || + ((geom->panel_info & (LCDPANEL_MONOCHROME|LCDPANEL_DUAL)) == + LCDPANEL_DUAL)) { + /* active and color dual panel need L_DD[15:0] */ + nldd = 16; + } else + if ((geom->panel_info & LCDPANEL_DUAL) || + !(geom->panel_info & LCDPANEL_MONOCHROME)) { + /* dual or color need L_DD[7:0] */ + nldd = 8; + } else { + /* Otherwise just L_DD[3:0] */ + nldd = 4; + } + + while (nldd--) + pxa2x0_gpio_set_function(58 + nldd, GPIO_ALT_FN_2_OUT); + + pxa2x0_lcd_geometry(sc, geom); +} + + +int +lcdintr(void *arg) +{ + struct pxa2x0_lcd_softc *sc = arg; + bus_space_tag_t iot = sc->iot; + bus_space_handle_t ioh = sc->ioh; + + static uint32_t status; + + status = bus_space_read_4(iot, ioh, LCDC_LCSR); + /* Clear stickey status bits */ + bus_space_write_4(iot, ioh, LCDC_LCSR, status); + + return 1; +} + +void +pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *sc, + struct pxa2x0_lcd_screen *scr) +{ + uint32_t tmp; + bus_space_tag_t iot = sc->iot; + bus_space_handle_t ioh = sc->ioh; + int val, save; + + save = disable_interrupts(I32_bit); + + switch (scr->depth) { + case 1: val = 0; break; + case 2: val = 1; break; + case 4: val = 2; break; + case 8: val = 3; break; + case 16: /* FALLTHROUGH */ + default: + val = 4; break; + } + + tmp = bus_space_read_4(iot, ioh, LCDC_LCCR3); + bus_space_write_4(iot, ioh, LCDC_LCCR3, + (tmp & ~LCCR3_BPP) | (val << LCCR3_BPP_SHIFT)); + + bus_space_write_4(iot, ioh, LCDC_FDADR0, + scr->depth == 16 ? scr->dma_desc_pa : + scr->dma_desc_pa + 2 * sizeof (struct lcd_dma_descriptor)); + bus_space_write_4(iot, ioh, LCDC_FDADR1, + scr->dma_desc_pa + 1 * sizeof (struct lcd_dma_descriptor)); + + /* clear status */ + bus_space_write_4(iot, ioh, LCDC_LCSR, 0); + + delay(1000); /* ??? */ + + /* Enable LCDC */ + tmp = bus_space_read_4(iot, ioh, LCDC_LCCR0); + /*tmp &= ~LCCR0_SFM;*/ + bus_space_write_4(iot, ioh, LCDC_LCCR0, tmp | LCCR0_ENB); + + restore_interrupts(save); + +} + + +#if NWSDISPLAY > 0 +static void +pxa2x0_lcd_stop_dma(struct pxa2x0_lcd_softc *sc) +{ + /* Stop LCD DMA after current frame */ + bus_space_write_4(sc->iot, sc->ioh, LCDC_LCCR0, + LCCR0_DIS | + bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)); + + /* wait for disabling done. + XXX: use interrupt. */ + while (LCCR0_ENB & + bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)) + ; + + bus_space_write_4(sc->iot, sc->ioh, LCDC_LCCR0, + ~LCCR0_DIS & + bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0)); +} +#endif + +#define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b) +#define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1) + +#define L 0x1f /* low intensity */ +#define H 0x3f /* hight intensity */ + +static uint16_t basic_color_map[] = { + rgb( 0, 0, 0), /* black */ + rgb( L, 0, 0), /* red */ + rgb( 0, L, 0), /* green */ + rgb( L, L, 0), /* brown */ + rgb( 0, 0, L), /* blue */ + rgb( L, 0, L), /* magenta */ + rgb( 0, L, L), /* cyan */ + _rgb(0x1c,0x38,0x1c), /* white */ + + rgb( L, L, L), /* black */ + rgb( H, 0, 0), /* red */ + rgb( 0, H, 0), /* green */ + rgb( H, H, 0), /* brown */ + rgb( 0, 0, H), /* blue */ + rgb( H, 0, H), /* magenta */ + rgb( 0, H, H), /* cyan */ + rgb( H, H, H) +}; + +#undef H +#undef L + +static void +init_pallet(uint16_t *buf, int depth) +{ + int i; + + /* convert RGB332 to RGB565 */ + switch (depth) { + case 8: + case 4: +#if 0 + for (i=0; i <= 255; ++i) { + buf[i] = ((9 * ((i>>5) & 0x07)) <<11) | + ((9 * ((i>>2) & 0x07)) << 5) | + ((21 * (i & 0x03))/2); + } +#else + memcpy(buf, basic_color_map, sizeof basic_color_map); + for (i=16; i < (1<<depth); ++i) + buf[i] = 0xffff; +#endif + break; + case 16: + /* pallet is not needed */ + break; + default: + /* other depths are not supported */ + break; + } +} + +struct pxa2x0_lcd_screen * +pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc *sc, + int depth) +{ + struct pxa2x0_lcd_screen *scr = NULL; + int width, height; + bus_size_t size; + int error, pallet_size; + int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); + struct lcd_dma_descriptor *desc; + paddr_t buf_pa, desc_pa; + + width = sc->geometry->panel_width; + height = sc->geometry->panel_height; + pallet_size = 0; + + switch (depth) { + case 1: + case 2: + case 4: + case 8: + pallet_size = (1<<depth) * sizeof (uint16_t); + /* FALLTHROUGH */ + case 16: + size = roundup(width,4)*depth/8 * height; + break; + default: + printf("%s: Unknown depth (%d)\n", sc->dev.dv_xname, depth); + return NULL; + } + + scr = malloc(sizeof *scr, M_DEVBUF, + (cold ? M_NOWAIT : M_WAITOK)); + + if (scr == NULL) + return NULL; + + bzero (scr, sizeof *scr); + + scr->nsegs = 0; + scr->depth = depth; + scr->buf_size = size; + scr->buf_va = NULL; + size = roundup(size,16) + 3 * sizeof (struct lcd_dma_descriptor) + + pallet_size; + + error = bus_dmamem_alloc(sc->dma_tag, size, 16, 0, + scr->segs, 1, &(scr->nsegs), busdma_flag); + + if (error || scr->nsegs != 1) { + /* XXX: Actually we can handle nsegs>1 case by means + of multiple DMA descriptors for a panel. it will + makes code here a bit hairly */ + goto bad; + } + + error = bus_dmamem_map(sc->dma_tag, scr->segs, scr->nsegs, + size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT); + if (error) + goto bad; + + + memset (scr->buf_va, 0, scr->buf_size); + + /* map memory for DMA */ + if (bus_dmamap_create(sc->dma_tag, 1024*1024*2, 1, + 1024*1024*2, 0, busdma_flag, &scr->dma)) + goto bad; + error = bus_dmamap_load(sc->dma_tag, scr->dma, + scr->buf_va, size, NULL, busdma_flag); + if (error) { + goto bad; + } + + buf_pa = scr->segs[0].ds_addr; + desc_pa = buf_pa + roundup(size, PAGE_SIZE) - 3*sizeof *desc; + + /* make descriptors at the top of mapped memory */ + desc = (struct lcd_dma_descriptor *)( + (caddr_t)(scr->buf_va) + roundup(size, PAGE_SIZE) - + 3*sizeof *desc); + + desc[0].fdadr = desc_pa; + desc[0].fsadr = buf_pa; + desc[0].ldcmd = scr->buf_size; + + if (pallet_size) { + init_pallet((uint16_t *)((char *)desc - pallet_size), depth); + + desc[2].fdadr = desc_pa; /* chain to panel 0 */ + desc[2].fsadr = desc_pa - pallet_size; + desc[2].ldcmd = pallet_size | LDCMD_PAL; + } + + if (sc->geometry->panel_info & LCDPANEL_DUAL) { + /* Dual panel */ + desc[1].fdadr = desc_pa + sizeof *desc; + desc[1].fsadr = buf_pa + scr->buf_size/2; + desc[0].ldcmd = desc[1].ldcmd = scr->buf_size/2; + + } + +#if 0 + desc[0].ldcmd |= LDCMD_SOFINT; + desc[1].ldcmd |= LDCMD_SOFINT; +#endif + + scr->dma_desc = desc; + scr->dma_desc_pa = desc_pa; + scr->map_size = size; /* used when unmap this. */ + + LIST_INSERT_HEAD(&(sc->screens), scr, link); + sc->n_screens++; + + return scr; + + bad: + if (scr) { + if (scr->buf_va) + bus_dmamem_unmap(sc->dma_tag, scr->buf_va, size); + if (scr->nsegs) + bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs); + free(scr, M_DEVBUF); + } + return NULL; +} + + +#if NWSDISPLAY > 0 + +/* + * Initialize struct wsscreen_descr based on values calculated by + * raster operation subsystem. + */ +int +pxa2x0_lcd_setup_wsscreen(struct pxa2x0_wsscreen_descr *descr, + const struct lcd_panel_geometry *geom, + const char *fontname) +{ + int width = geom->panel_width; + int height = geom->panel_height; + int cookie = -1; + struct rasops_info rinfo; + + memset(&rinfo, 0, sizeof rinfo); + +#if 0 + if (fontname) { + wsfont_init(); + cookie = wsfont_find((char *)fontname, 0, 0, 0, + WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R); + if (cookie < 0 || + wsfont_lock(cookie, &rinfo.ri_font)) + return -1; + } + else { + /* let rasops_init() choose any font */ + } +#endif + + /* let rasops_init calculate # of cols and rows in character */ + rinfo.ri_flg = 0; + rinfo.ri_depth = descr->depth; + rinfo.ri_bits = NULL; + rinfo.ri_width = width; + rinfo.ri_height = height; + rinfo.ri_stride = width * rinfo.ri_depth / 8; + rinfo.ri_wsfcookie = cookie; + + rasops_init(&rinfo, 100, 100); + + descr->c.nrows = rinfo.ri_rows; + descr->c.ncols = rinfo.ri_cols; + descr->c.capabilities = rinfo.ri_caps; + + + return cookie; +} + + +int +pxa2x0_lcd_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + struct pxa2x0_lcd_softc *sc = v; + struct pxa2x0_lcd_screen *scr = cookie, *old; + + old = sc->active; + if (old == scr) + return 0; + + if (old) + pxa2x0_lcd_stop_dma(sc); + + pxa2x0_lcd_start_dma(sc, scr); + + sc->active = scr; + return 0; +} + +int +pxa2x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type, + void **cookiep, int *curxp, int *curyp, long *attrp) +{ + struct pxa2x0_lcd_softc *sc = v; + struct pxa2x0_lcd_screen *scr; + struct pxa2x0_wsscreen_descr *type = (struct pxa2x0_wsscreen_descr *)_type; + + scr = pxa2x0_lcd_new_screen(sc, type->depth); + if (scr == NULL) + return -1; + + /* + * initialize raster operation for this screen. + */ + scr->rinfo.ri_flg = 0; + scr->rinfo.ri_depth = type->depth; + scr->rinfo.ri_bits = scr->buf_va; + scr->rinfo.ri_width = sc->geometry->panel_width; + scr->rinfo.ri_height = sc->geometry->panel_height; + scr->rinfo.ri_stride = scr->rinfo.ri_width * scr->rinfo.ri_depth / 8; + scr->rinfo.ri_wsfcookie = -1; /* XXX */ + + rasops_init(&scr->rinfo, type->c.nrows, type->c.ncols); + + scr->rinfo.ri_ops.alloc_attr(&scr->rinfo, 0, 0, 0, attrp); + + + *cookiep = scr; + *curxp = 0; + *curyp = 0; + + return 0; +} + + +void +pxa2x0_lcd_free_screen(void *v, void *cookie) +{ + struct pxa2x0_lcd_softc *sc = v; + struct pxa2x0_lcd_screen *scr = cookie; + + LIST_REMOVE(scr, link); + sc->n_screens--; + if (scr == sc->active) { + /* at first, we need to stop LCD DMA */ + sc->active = NULL; + + printf("lcd_free on active screen\n"); + + pxa2x0_lcd_stop_dma(sc); + } + + if (scr->buf_va) + bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size); + + if (scr->nsegs > 0) + bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs); + + free(scr, M_DEVBUF); +} + +int +pxa2x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct pxa2x0_lcd_softc *sc = v; + struct wsdisplay_fbinfo *wsdisp_info; + uint32_t ccr0; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ + return 0; + + case WSDISPLAYIO_GINFO: + wsdisp_info = (struct wsdisplay_fbinfo *)data; + + wsdisp_info->height = sc->geometry->panel_height; + wsdisp_info->width = sc->geometry->panel_width; + wsdisp_info->depth = 16; /* XXX */ + wsdisp_info->cmsize = 0; + return 0; + + case WSDISPLAYIO_GETCMAP: + case WSDISPLAYIO_PUTCMAP: + return EINVAL; /* XXX Colormap */ + + case WSDISPLAYIO_SVIDEO: + if (*(int *)data == WSDISPLAYIO_VIDEO_ON) { + /* turn it on */ + } + else { + /* start LCD shutdown */ + /* sleep until interrupt */ + } + return 0; + + case WSDISPLAYIO_GVIDEO: + ccr0 = bus_space_read_4(sc->iot, sc->ioh, LCDC_LCCR0); + *(u_int *)data = (ccr0 & (LCCR0_ENB|LCCR0_DIS)) == LCCR0_ENB ? + WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; + return 0; + + + + case WSDISPLAYIO_GCURPOS: + case WSDISPLAYIO_SCURPOS: + case WSDISPLAYIO_GCURMAX: + case WSDISPLAYIO_GCURSOR: + case WSDISPLAYIO_SCURSOR: + return -1; /* XXX */ + } + + return -1; +} + +paddr_t +pxa2x0_lcd_mmap(void *v, off_t offset, int prot) +{ + struct pxa2x0_lcd_softc *sc = v; + struct pxa2x0_lcd_screen *screen = sc->active; /* ??? */ + + if (screen == NULL) + return -1; + + return bus_dmamem_mmap(sc->dma_tag, screen->segs, screen->nsegs, + offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT); + return -1; +} + + +static void +pxa2x0_lcd_cursor(void *cookie, int on, int row, int col) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col); +} + +static int +pxa2x0_lcd_mapchar(void *cookie, int c, unsigned int *cp) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + return (* scr->rinfo.ri_ops.mapchar)(&scr->rinfo, c, cp); +} + +static void +pxa2x0_lcd_putchar(void *cookie, int row, int col, u_int uc, long attr) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.putchar)(&scr->rinfo, + row, col, uc, attr); +} + +static void +pxa2x0_lcd_copycols(void *cookie, int row, int src, int dst, int num) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.copycols)(&scr->rinfo, + row, src, dst, num); +} + +static void +pxa2x0_lcd_erasecols(void *cookie, int row, int col, int num, long attr) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.erasecols)(&scr->rinfo, + row, col, num, attr); +} + +static void +pxa2x0_lcd_copyrows(void *cookie, int src, int dst, int num) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.copyrows)(&scr->rinfo, + src, dst, num); +} + +static void +pxa2x0_lcd_eraserows(void *cookie, int row, int num, long attr) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + (* scr->rinfo.ri_ops.eraserows)(&scr->rinfo, + row, num, attr); +} + +static int +pxa2x0_lcd_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr) +{ + struct pxa2x0_lcd_screen *scr = cookie; + + return scr->rinfo.ri_ops.alloc_attr(&scr->rinfo, fg, bg, flg, attr); +} + + +const struct wsdisplay_emulops pxa2x0_lcd_emulops = { + pxa2x0_lcd_cursor, + pxa2x0_lcd_mapchar, + pxa2x0_lcd_putchar, + pxa2x0_lcd_copycols, + pxa2x0_lcd_erasecols, + pxa2x0_lcd_copyrows, + pxa2x0_lcd_eraserows, + pxa2x0_lcd_alloc_attr +}; + +#endif /* NWSDISPLAY > 0 */ diff --git a/sys/arch/arm/xscale/pxa2x0_lcd.h b/sys/arch/arm/xscale/pxa2x0_lcd.h new file mode 100644 index 00000000000..7750f2f3ba1 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_lcd.h @@ -0,0 +1,149 @@ +/* $NetBSD: pxa2x0_lcd.h,v 1.2 2003/06/17 09:43:14 bsh Exp $ */ +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _ARM_XSCALE_PXA2X0_LCD_H +#define _ARM_XSCALE_PXA2X0_LCD_H + +#include <dev/rasops/rasops.h> +#include <machine/bus.h> + +/* LCD Contoroller */ + +struct lcd_dma_descriptor { + uint32_t fdadr; /* next frame descriptor */ + uint32_t fsadr; /* frame start address */ + uint32_t fidr; /* frame ID */ + uint32_t ldcmd; /* DMA command */ +#define LDCMD_PAL (1U<<26) /* Pallet buffer */ +#define LDCMD_SOFINT (1U<<22) /* Start of Frame interrupt */ +#define LDCMD_EOFINT (1U<<21) /* End of Frame interrupt */ +}; + + +struct pxa2x0_lcd_screen { + LIST_ENTRY(pxa2x0_lcd_screen) link; + + /* Frame buffer */ + bus_dmamap_t dma; + bus_dma_segment_t segs[1]; + int nsegs; + size_t buf_size; + size_t map_size; + void *buf_va; + int depth; + + /* DMA frame descriptor */ + struct lcd_dma_descriptor *dma_desc; + paddr_t dma_desc_pa; + + /* rasterop */ + struct rasops_info rinfo; +}; + +struct pxa2x0_lcd_softc { + struct device dev; + /* control register */ + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_dma_tag_t dma_tag; + + const struct lcd_panel_geometry *geometry; + + int n_screens; + LIST_HEAD(, pxa2x0_lcd_screen) screens; + struct pxa2x0_lcd_screen *active; + void *ih; /* interrupt handler */ +}; + +void pxa2x0_lcd_attach_sub(struct pxa2x0_lcd_softc *, struct pxaip_attach_args *, + const struct lcd_panel_geometry *); +void pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *, struct pxa2x0_lcd_screen *); + +struct lcd_panel_geometry { + short panel_width; + short panel_height; + short extra_lines; + + short panel_info; +#define LCDPANEL_VSP (1<<0) /* L_FCLK pin is active low */ +#define LCDPANEL_HSP (1<<1) /* L_LCLK pin is active low */ +#define LCDPANEL_PCP (1<<2) /* use L_PCLK falling edge */ +#define LCDPANEL_OEP (1<<3) /* L_BIAS pin is active low */ +#define LCDPANEL_DPC (1<<4) /* double pixel clock mode */ + +#define LCDPANEL_DUAL (1<<5) /* Dual or single */ +#define LCDPANEL_SINGLE 0 +#define LCDPANEL_ACTIVE (1<<6) /* Active or Passive */ +#define LCDPANEL_PASSIVE 0 +#define LCDPANEL_MONOCHROME (1<<7) /* depth=1 */ + + short pixel_clock_div; /* pixel clock divider */ + short ac_bias; /* AC bias pin frequency */ + + short hsync_pulse_width; /* Horizontao sync pulse width */ + short beg_line_wait; /* beginning of line wait (BLW) */ + short end_line_wait; /* end of line pxel wait (ELW) */ + + short vsync_pulse_width; /* vertical sync pulse width */ + short beg_frame_wait; /* beginning of frame wait (BFW) */ + short end_frame_wait; /* end of frame wait (EFW) */ +}; + +void pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc *, + const struct lcd_panel_geometry *); +struct pxa2x0_lcd_screen *pxa2x0_lcd_new_screen( + struct pxa2x0_lcd_softc *, int depth); + +/* + * we need bits-per-pixel value to configure wsdisplay screen + */ +struct pxa2x0_wsscreen_descr { + struct wsscreen_descr c; /* standard descriptor */ + int depth; /* bits per pixel */ +}; + +int pxa2x0_lcd_setup_wsscreen(struct pxa2x0_wsscreen_descr *, + const struct lcd_panel_geometry *, const char * ); + +int pxa2x0_lcd_show_screen(void *, void *, int, void (*)(void *, int, int), void *); +int pxa2x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p); +paddr_t pxa2x0_lcd_mmap(void *, off_t, int); +int pxa2x0_lcd_alloc_screen(void *, const struct wsscreen_descr *, + void **, int *, int *, long *); +void pxa2x0_lcd_free_screen(void *, void *); + +extern const struct wsdisplay_emulops pxa2x0_lcd_emulops; + +#endif /* _ARM_XSCALE_PXA2X0_LCD_H */ diff --git a/sys/arch/arm/xscale/pxa2x0_space.c b/sys/arch/arm/xscale/pxa2x0_space.c new file mode 100644 index 00000000000..30690b5707d --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0_space.c @@ -0,0 +1,267 @@ +/* $NetBSD: pxa2x0_space.c,v 1.5 2004/06/07 19:45:22 nathanw Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ichiro FUKUHARA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * bus_space functions for Intel PXA2[51]0 application processor. + * Derived from i80321_space.c. + */ + +#include <sys/cdefs.h> +/* +__KERNEL_RCSID(0, "$NetBSD: pxa2x0_space.c,v 1.5 2004/06/07 19:45:22 nathanw Exp $"); +*/ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(pxa2x0); +bs_protos(generic); +bs_protos(generic_armv4); +bs_protos(bs_notimpl); + +struct bus_space pxa2x0_bs_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + pxa2x0_bs_map, + pxa2x0_bs_unmap, + pxa2x0_bs_subregion, + + /* allocation/deallocation */ + pxa2x0_bs_alloc, /* not implemented */ + pxa2x0_bs_free, /* not implemented */ + + /* get kernel virtual address */ + pxa2x0_bs_vaddr, + + /* mmap */ + bs_notimpl_bs_mmap, + + /* barrier */ + pxa2x0_bs_barrier, + + /* read (single) */ + generic_bs_r_1, + generic_armv4_bs_r_2, + generic_bs_r_4, + bs_notimpl_bs_r_8, + + /* read multiple */ + generic_bs_rm_1, + generic_armv4_bs_rm_2, + generic_bs_rm_4, + bs_notimpl_bs_rm_8, + + /* read region */ + generic_bs_rr_1, + generic_armv4_bs_rr_2, + generic_bs_rr_4, + bs_notimpl_bs_rr_8, + + /* write (single) */ + generic_bs_w_1, + generic_armv4_bs_w_2, + generic_bs_w_4, + bs_notimpl_bs_w_8, + + /* write multiple */ + generic_bs_wm_1, + generic_armv4_bs_wm_2, + generic_bs_wm_4, + bs_notimpl_bs_wm_8, + + /* write region */ + generic_bs_wr_1, + generic_armv4_bs_wr_2, + generic_bs_wr_4, + bs_notimpl_bs_wr_8, + + /* set multiple */ + bs_notimpl_bs_sm_1, + bs_notimpl_bs_sm_2, + bs_notimpl_bs_sm_4, + bs_notimpl_bs_sm_8, + + /* set region */ + generic_bs_sr_1, + generic_armv4_bs_sr_2, + bs_notimpl_bs_sr_4, + bs_notimpl_bs_sr_8, + + /* copy */ + bs_notimpl_bs_c_1, + generic_armv4_bs_c_2, + bs_notimpl_bs_c_4, + bs_notimpl_bs_c_8, +}; + +int +pxa2x0_bs_map(void *t, bus_addr_t bpa, bus_size_t size, + int flag, bus_space_handle_t *bshp) +{ + u_long startpa, endpa, pa; + vaddr_t va; + pt_entry_t *pte; + + if ((u_long)bpa > (u_long)KERNEL_BASE) { + /* Some IO registers (ex. UART ports for console) + are mapped to fixed address by board specific + routine. */ + *bshp = bpa; + return(0); + } + + startpa = trunc_page(bpa); + endpa = round_page(bpa + size); + + /* XXX use extent manager to check duplicate mapping */ + + va = uvm_km_valloc(kernel_map, endpa - startpa); + if (! va) + return(ENOMEM); + + *bshp = (bus_space_handle_t)(va + (bpa - startpa)); + + for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { + pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE); + if ((flag & BUS_SPACE_MAP_CACHEABLE) == 0) { + pte = vtopte(va); + *pte &= ~L2_S_CACHE_MASK; + PTE_SYNC(pte); + /* XXX: pmap_kenter_pa() also does PTE_SYNC(). a bit of + * waste. + */ + } + } + pmap_update(pmap_kernel()); + + return(0); +} + +void +pxa2x0_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + if (bsh > (u_long)KERNEL_BASE) + return; + + uvm_km_free(kernel_map, bsh, size); +} + + +int +pxa2x0_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + + *nbshp = bsh + offset; + return (0); +} + +void +pxa2x0_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t len, int flags) +{ + + /* Nothing to do. */ +} + +void * +pxa2x0_bs_vaddr(void *t, bus_space_handle_t bsh) +{ + + return ((void *)bsh); +} + + +int +pxa2x0_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *bpap, bus_space_handle_t *bshp) +{ + + panic("pxa2x0_io_bs_alloc(): not implemented\n"); +} + +void +pxa2x0_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + + panic("pxa2x0_io_bs_free(): not implemented\n"); +} + diff --git a/sys/arch/arm/xscale/pxa2x0reg.h b/sys/arch/arm/xscale/pxa2x0reg.h new file mode 100644 index 00000000000..53b8bde042d --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0reg.h @@ -0,0 +1,612 @@ +/* $NetBSD: pxa2x0reg.h,v 1.4 2003/06/11 20:43:01 scw Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * 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_PXA2X0REG_H_ +#define _ARM_XSCALE_PXA2X0REG_H_ + +/* Borrow some register definitions from sa11x0 */ +#include <arm/sa11x0/sa11x0_reg.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_PCMCIA_SLOT0 0x20000000 +#define PXA2X0_PCMCIA_SLOT1 0x30000000 + +#define PXA2X0_PERIPH_START 0x40000000 +/* #define PXA2X0_MEMCTL_START 0x48000000 */ +#define PXA2X0_PERIPH_END 0x480fffff + +#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_BTUART_BASE 0x40200000 /* Bluetooth UART */ +#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_ICP_BASE 0x40800000 +#define PXA2X0_RTC_BASE 0x40900000 +#define PXA2X0_RTC_SIZE 0x10 +#define PXA2X0_OST_BASE 0x40a00000 /* OS Timer */ +#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 PXA2X0_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_LCDC_BASE 0x44000000 /* LCD Controller */ +#define PXA2X0_LCDC_SIZE 0x220 +#define PXA2X0_MEMCTL_BASE 0x48000000 /* Memory Controller */ +#define PXA2X0_MEMCTL_SIZE 0x48 + +/* width of interrupt controller */ +#define ICU_LEN 32 /* but [0..7,15,16] is not used */ +#define ICU_INT_HWMASK 0xffffff00 +#define PXA2X0_IRQ_MIN 8 /* 0..7 are not used by integrated + peripherals */ + +#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_STARTINR (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 pxa2x0_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_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.768KHz oscillator status */ +#define OSCC_OON (1<<1) /* 32.768KHz 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] */ + +#define GPIO_REG(r, pin) ((r) + (((pin) / 32) * 4)) +#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 GPIO_NPINS 85 + +/* + * 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_FBR0 0x020 /* DMA ch0 frame branch register */ +#define LCDC_FBR1 0x024 /* DMA ch1 frame branch register */ +#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_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 */ + +/* + * 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 */ +#endif /* _ARM_XSCALE_PXA2X0REG_H_ */ diff --git a/sys/arch/arm/xscale/pxa2x0var.h b/sys/arch/arm/xscale/pxa2x0var.h new file mode 100644 index 00000000000..b4daaf821d3 --- /dev/null +++ b/sys/arch/arm/xscale/pxa2x0var.h @@ -0,0 +1,89 @@ +/* $NetBSD: pxa2x0var.h,v 1.2 2003/06/05 13:48:28 scw Exp $ */ + +/* + * Copyright (c) 2002 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Genetec Corporation. + * 4. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _ARM_XSCALE_PXA2X0VAR_H_ +#define _ARM_XSCALE_PXA2X0VAR_H_ + +#include <arm/sa11x0/sa11x0_var.h> + +/* PXA2X0's integrated peripheral bus. */ + +typedef int (* pxa2x0_irq_handler_t)(void *); + +struct pxaip_attach_args { + struct sa11x0_attach_args pxa_sa; + bus_dma_tag_t pxa_dmat; + int pxa_index; /* to specify device by index number */ + +#define pxa_iot pxa_sa.sa_iot +#define pxa_addr pxa_sa.sa_addr +#define pxa_size pxa_sa.sa_size +#define pxa_intr pxa_sa.sa_intr +}; + +#define cf_addr cf_loc[0] +#define cf_size cf_loc[1] +#define cf_intr cf_loc[2] +#define cf_index cf_loc[3] + + +extern struct bus_space pxa2x0_bs_tag; +extern struct arm32_bus_dma_tag pxa2x0_bus_dma_tag; +extern struct bus_space pxa2x0_a4x_bs_tag; + +/* misc. */ +extern void pxa2x0_fcs_init(void); +extern void pxa2x0_freq_change(int); +extern void pxa2x0_turbo_mode(int); +extern int pxa2x0_i2c_master_tx( int, uint8_t *, int ); + +/* + * Probe the memory controller to deterimine which SDRAM are + * populated, and what size of SDRAM is present in each bank. + * + * This routine should be called from a port's initarm() + * function, with the first parameter set to the address + * of the memory controller's registers. + */ +extern void pxa2x0_probe_sdram(vaddr_t, paddr_t *, psize_t *); + +/* + * Configure one or more clock enables in the Clock Manager's + * CKEN register. + */ +extern void pxa2x0_clkman_config(u_int, int); + +#endif /* _ARM_XSCALE_PXA2X0VAR_H_ */ diff --git a/sys/arch/arm/xscale/pxapcicvar.h b/sys/arch/arm/xscale/pxapcicvar.h new file mode 100644 index 00000000000..fadc3fdf4a4 --- /dev/null +++ b/sys/arch/arm/xscale/pxapcicvar.h @@ -0,0 +1,87 @@ +struct pxapcic_socket { + struct pxapcic_softc *sc; + int socket; /* socket number */ + struct device *pcmcia; + /* + struct pxapcic_tag *pcictag; + */ + + int flags; + + int power_capability; + + void *pcictag_cookie; /* opaque data for pcictag functions */ +}; + +/* event */ +#define PXAPCIC_EVENT_INSERTION 0 +#define PXAPCIC_EVENT_REMOVAL 1 + +/* laststatus */ +#define PXAPCIC_FLAG_CARDD 0 +#define PXAPCIC_FLAG_CARDP 1 + +struct pxapcic_tag { + int (*read)(struct pxapcic_socket *, int); + void (*write)(struct pxapcic_socket *, int, int); + void (*set_power)(struct pxapcic_socket *, int); + void (*clear_intr)(int); + void *(*intr_establish)(struct pxapcic_socket *, int, + int (*)(void *), void *); + void (*intr_disestablish)(struct pxapcic_socket *, void *); +}; + + +struct pxapcic_softc { + struct device sc_dev; + struct pxapcic_socket sc_socket[2]; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_scooph; + + struct proc *sc_event_thread; + void *sc_irq; + int sc_gpio; + int sc_shutdown; +}; + + +#define SCOOP_REG_MCR 0x00 +#define SCOOP_REG_CDR 0x04 +#define SCOOP_REG_CSR 0x08 +#define SCOOP_REG_CPR 0x0C +#define SCOOP_REG_CCR 0x10 +#define SCOOP_REG_IRR 0x14 +#define SCOOP_REG_IRM 0x14 +#define SCOOP_REG_IMR 0x18 +#define SCOOP_REG_ISR 0x1C +#define SCOOP_REG_GPCR 0x20 +#define SCOOP_REG_GPWR 0x24 +#define SCOOP_REG_GPRR 0x28 + +#define SCP_CDR_DETECT 0x0002 + +#define SCP_CSR_READY 0x0002 +#define SCP_CSR_MISSING 0x0004 +#define SCP_CSR_WPROT 0x0008 +#define SCP_CSR_BVD1 0x0010 +#define SCP_CSR_BVD2 0x0020 +#define SCP_CSR_3V 0x0040 +#define SCP_CSR_PWR 0x0080 + +#define SCP_CPR_OFF 0x0000 +#define SCP_CPR_3V 0x0001 +#define SCP_CPR_5V 0x0002 +#define SCP_CPR_PWR 0x0080 + + +#define SCP_MCR_IOCARD 0x0010 +#define SCP_CCR_RESET 0x0080 + +#define SCP_IMR_READY 0x0002 +#define SCP_IMR_DETECT 0x0004 +#define SCP_IMR_WRPROT 0x0008 +#define SCP_IMR_STSCHG 0x0010 +#define SCP_IMR_BATWARN 0x0020 +#define SCP_IMR_UNKN0 0x0040 +#define SCP_IMR_UNKN1 0x0080 |