diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /cpu/arm920t | |
download | FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2 FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip |
init commit via android 4.4 uboot
Diffstat (limited to 'cpu/arm920t')
104 files changed, 29094 insertions, 0 deletions
diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile new file mode 100755 index 0000000..8f256e9 --- /dev/null +++ b/cpu/arm920t/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.o +OBJS = cpu.o interrupts.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/at91rm9200/Makefile b/cpu/arm920t/at91rm9200/Makefile new file mode 100755 index 0000000..aec9cb6 --- /dev/null +++ b/cpu/arm920t/at91rm9200/Makefile @@ -0,0 +1,44 @@ +# +# (C) Copyright 2000-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = bcm5221.o dm9161.o ether.o i2c.o interrupts.o \ + lxt972.o serial.o usb_ohci.o +SOBJS = lowlevel_init.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/at91rm9200/arm920t/Makefile b/cpu/arm920t/at91rm9200/arm920t/Makefile new file mode 100755 index 0000000..0a5169f --- /dev/null +++ b/cpu/arm920t/at91rm9200/arm920t/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# Some descriptions of such software. Copyright (c) 2008 WonderMedia Technologies, Inc. +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software Foundation, +# either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +# +# WonderMedia Technologies, Inc. +# 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +# + +include $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.o +OBJS = cpu.o interrupts.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/at91rm9200/arm920t/config.mk b/cpu/arm920t/at91rm9200/arm920t/config.mk new file mode 100755 index 0000000..35d5369 --- /dev/null +++ b/cpu/arm920t/at91rm9200/arm920t/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# Some descriptions of such software. Copyright (c) 2008 WonderMedia Technologies, Inc. +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software Foundation, +# either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +# +# WonderMedia Technologies, Inc. +# 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +# + +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +PLATFORM_CPPFLAGS += -march=armv6 +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) diff --git a/cpu/arm920t/at91rm9200/arm920t/cpu.c b/cpu/arm920t/at91rm9200/arm920t/cpu.c new file mode 100755 index 0000000..b39587e --- /dev/null +++ b/cpu/arm920t/at91rm9200/arm920t/cpu.c @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <arm920t.h> + +#ifdef CONFIG_USE_IRQ +DECLARE_GLOBAL_DATA_PTR; +#endif + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1(void) +{ + unsigned long value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c1, c0, 0 @ read control reg\n" + : "=r" (value) + : + : "memory"); + +#ifdef MMU_DEBUG + printf("p15/c1 is = %08lx\n", value); +#endif + return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1(unsigned long value) +{ +#ifdef MMU_DEBUG + printf("write %08lx to p15/c1\n", value); +#endif + __asm__ __volatile__( + "mcr p15, 0, %0, c1, c0, 0 @ write it back\n" + : + : "r" (value) + : "memory"); + + read_p15_c1(); +} + +static void cp_delay(void) +{ + volatile int i; + + /* copro seems to need some delay between reading and writing */ + for (i = 0; i < 100; i++) + ; +} + +/* See also ARM920T Technical reference Manual */ +#define C1_MMU (1<<0) /* mmu off/on */ +#define C1_ALIGN (1<<1) /* alignment faults off/on */ +#define C1_DC (1<<2) /* dcache off/on */ + +#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ +#define C1_SYS_PROT (1<<8) /* system protection */ +#define C1_ROM_PROT (1<<9) /* ROM protection */ +#define C1_IC (1<<12) /* icache off/on */ +#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ + + +int cpu_init(void) +{ + /* + * setup up stacks if necessary + */ +#ifdef CONFIG_USE_IRQ + IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; + FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; +#endif + return 0; +} + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + unsigned long i; + + disable_interrupts(); + + /* turn off I/D-cache */ + asm ("mrc p15, 0, %0, c1, c0, 0" : "=r" (i)); + i &= ~(C1_DC | C1_IC); + asm ("mcr p15, 0, %0, c1, c0, 0" : : "r" (i)); + + /* flush I/D-cache */ + i = 0; + asm ("mcr p15, 0, %0, c7, c7, 0" : : "r" (i)); + + return 0; +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + disable_interrupts(); + reset_cpu(0); + /*NOTREACHED*/ + return 0; +} + +void icache_enable(void) +{ + ulong reg; + + reg = read_p15_c1(); /* get control reg. */ + cp_delay(); + write_p15_c1(reg | C1_IC); +} + +void icache_disable(void) +{ + ulong reg; + + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg & ~C1_IC); +} + +int icache_status(void) +{ + return (read_p15_c1() & C1_IC) != 0; +} + +#ifdef USE_920T_MMU +/* It makes no sense to use the dcache if the MMU is not enabled */ +void dcache_enable(void) +{ + ulong reg; + + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg | C1_DC); +} + +void dcache_disable(void) +{ + ulong reg; + + reg = read_p15_c1(); + cp_delay(); + reg &= ~C1_DC; + write_p15_c1(reg); +} + +int dcache_status(void) +{ + return (read_p15_c1() & C1_DC) != 0; +} +#endif diff --git a/cpu/arm920t/at91rm9200/arm920t/interrupts.c b/cpu/arm920t/at91rm9200/arm920t/interrupts.c new file mode 100755 index 0000000..e90e385 --- /dev/null +++ b/cpu/arm920t/at91rm9200/arm920t/interrupts.c @@ -0,0 +1,174 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +#include <common.h> +#include <arm920t.h> +#include <asm/proc-armv/ptrace.h> + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts(void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + : "=r" (temp) + : + : "memory"); +} + + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts(void) +{ + unsigned long old, temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts(void) +{ + return; +} +int disable_interrupts(void) +{ + return 0; +} +#endif + + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(0); +} + +void show_regs(struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes(regs); + + printf("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer(regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf(" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled(regs) ? "on" : "off", + fast_interrupts_enabled(regs) ? "on" : "off", + processor_modes[processor_mode(regs)], + thumb_mode(regs) ? " (T)" : ""); +} + +void do_undefined_instruction(struct pt_regs *pt_regs) +{ + printf("undefined instruction\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_software_interrupt(struct pt_regs *pt_regs) +{ + printf("software interrupt\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_prefetch_abort(struct pt_regs *pt_regs) +{ + printf("prefetch abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_data_abort(struct pt_regs *pt_regs) +{ + printf("data abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_not_used(struct pt_regs *pt_regs) +{ + printf("not used\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_fiq(struct pt_regs *pt_regs) +{ + printf("fast interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_irq(struct pt_regs *pt_regs) +{ +#if defined(CONFIG_USE_IRQ) && defined(CONFIG_ARCH_INTEGRATOR) + /* ASSUMED to be a timer interrupt */ + /* Just clear it - count handled in */ + /* integratorap.c */ + *(volatile ulong*)(CFG_TIMERBASE + 0x0C) = 0; +#else + printf("interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +#endif +} diff --git a/cpu/arm920t/at91rm9200/arm920t/start.S b/cpu/arm920t/at91rm9200/arm920t/start.S new file mode 100755 index 0000000..66c12bf --- /dev/null +++ b/cpu/arm920t/at91rm9200/arm920t/start.S @@ -0,0 +1,441 @@ +/* + * armboot - Startup Code for ARM920 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + + +#include <config.h> +#include <version.h> + + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * These are defined in the board-specific linker script. + */ +.globl _bss_start +_bss_start: + .word __bss_start + +.globl _bss_end +_bss_end: + .word _end + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + +/* turn off the watchdog */ +#if defined(CONFIG_S3C2400) +# define pWTCON 0x15300000 +# define INTMSK 0x14400008 /* Interupt-Controller base addresses */ +# define CLKDIVN 0x14800014 /* clock divisor register */ +#elif defined(CONFIG_S3C2410) +# define pWTCON 0x53000000 +# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ +# define INTSUBMSK 0x4A00001C +# define CLKDIVN 0x4C000014 /* clock divisor register */ +#endif + +#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) + ldr r0, =pWTCON + mov r1, #0x0 + str r1, [r0] + + /* + * mask all IRQs by setting all bits in the INTMR - default + */ + mov r1, #0xffffffff + ldr r0, =INTMSK + str r1, [r0] +# if defined(CONFIG_S3C2410) + ldr r1, =0x3ff + ldr r0, =INTSUBMSK + str r1, [r0] +# endif + + /* FCLK:HCLK:PCLK = 1:2:4 */ + /* default FCLK is 120 MHz ! */ + ldr r0, =CLKDIVN + mov r1, #3 + str r1, [r0] +#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */ + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate: /* relocate U-Boot to RAM */ + adr r0, _start /* r0 <- current position of code */ + ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ + cmp r0, r1 /* don't reloc during debug */ + beq stack_setup + + ldr r2, _armboot_start + ldr r3, _bss_start + sub r2, r3, r2 /* r2 <- size of armboot */ + add r2, r0, r2 /* r2 <- source end address */ + +copy_loop: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end addreee [r2] */ + ble copy_loop +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + + /* Set up the stack */ +stack_setup: + ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ + sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ + sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ +#ifdef CONFIG_USE_IRQ + sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) +#endif + sub sp, r0, #12 /* leave 3 words for abort-stack */ + +clear_bss: + ldr r0, _bss_start /* find start of bss segment */ + ldr r1, _bss_end /* stop here */ + mov r2, #0x00000000 /* clear */ + +clbss_l:str r2, [r0] /* clear loop... */ + add r0, r0, #4 + cmp r0, r1 + ble clbss_l + +#if 0 + /* try doing this stuff after the relocation */ + ldr r0, =pWTCON + mov r1, #0x0 + str r1, [r0] + + /* + * mask all IRQs by setting all bits in the INTMR - default + */ + mov r1, #0xffffffff + ldr r0, =INTMR + str r1, [r0] + + /* FCLK:HCLK:PCLK = 1:2:4 */ + /* default FCLK is 120 MHz ! */ + ldr r0, =CLKDIVN + mov r1, #3 + str r1, [r0] + /* END stuff after relocation */ +#endif + + ldr pc, _start_armboot + +_start_armboot: .word start_armboot + + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +cpu_init_crit: + + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + +#if defined (CONFIG_WMT) + bic r0, r0, #0x00000300 @ clear bits 9:8 (---- --RS) + bic r0, r0, #0x0000000F @ clear bits 3:0 (---- WCAM) + orr r0, r0, #0x00002000 @ set bit 13 (--V--) +#else + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) +#endif + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + bl lowlevel_init + mov lr, ip + mov pc, lr + + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + ldr r2, _armboot_start + sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) + sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack + ldmia r2, {r2 - r3} @ get pc, cpsr + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, _armboot_start @ setup our mode stack + sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) + sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif diff --git a/cpu/arm920t/at91rm9200/bcm5221.c b/cpu/arm920t/at91rm9200/bcm5221.c new file mode 100755 index 0000000..6db1435 --- /dev/null +++ b/cpu/arm920t/at91rm9200/bcm5221.c @@ -0,0 +1,232 @@ +/* + * Broadcom BCM5221 Ethernet PHY + * + * (C) Copyright 2005 REA Elektronik GmbH <www.rea.de> + * Anders Larsen <alarsen@rea.de> + * + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <at91rm9200_net.h> +#include <net.h> +#include <bcm5221.h> + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* + * Name: + * bcm5221_IsPhyConnected + * Description: + * Reads the 2 PHY ID registers + * Arguments: + * p_mac - pointer to AT91S_EMAC struct + * Return value: + * TRUE - if id read successfully + * FALSE- if error + */ +unsigned int bcm5221_IsPhyConnected (AT91PS_EMAC p_mac) +{ + unsigned short Id1, Id2; + + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacReadPhy (p_mac, BCM5221_PHYID1, &Id1); + at91rm9200_EmacReadPhy (p_mac, BCM5221_PHYID2, &Id2); + at91rm9200_EmacDisableMDIO (p_mac); + + if ((Id1 == (BCM5221_PHYID1_OUI >> 6)) && + ((Id2 >> 10) == (BCM5221_PHYID1_OUI & BCM5221_LSB_MASK))) + return TRUE; + + return FALSE; +} + +/* + * Name: + * bcm5221_GetLinkSpeed + * Description: + * Link parallel detection status of MAC is checked and set in the + * MAC configuration registers + * Arguments: + * p_mac - pointer to MAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +unsigned char bcm5221_GetLinkSpeed (AT91PS_EMAC p_mac) +{ + unsigned short stat1, stat2; + + if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMSR, &stat1)) + return FALSE; + + if (!(stat1 & BCM5221_LINK_STATUS)) /* link status up? */ + return FALSE; + + if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_ACSR, &stat2)) + return FALSE; + + if ((stat1 & BCM5221_100BASE_TX_FD) && (stat2 & BCM5221_100) && (stat2 & BCM5221_FDX)) { + /*set Emac for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; + return TRUE; + } + + if ((stat1 & BCM5221_10BASE_T_FD) && !(stat2 & BCM5221_100) && (stat2 & BCM5221_FDX)) { + /*set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_FD; + return TRUE; + } + + if ((stat1 & BCM5221_100BASE_TX_HD) && (stat2 & BCM5221_100) && !(stat2 & BCM5221_FDX)) { + /*set MII for 100BaseTX and Half Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_SPD; + return TRUE; + } + + if ((stat1 & BCM5221_10BASE_T_HD) && !(stat2 & BCM5221_100) && !(stat2 & BCM5221_FDX)) { + /*set MII for 10BaseT and Half Duplex */ + p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); + return TRUE; + } + return FALSE; +} + + +/* + * Name: + * bcm5221_InitPhy + * Description: + * MAC starts checking its link by using parallel detection and + * Autonegotiation and the same is set in the MAC configuration registers + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +unsigned char bcm5221_InitPhy (AT91PS_EMAC p_mac) +{ + unsigned char ret = TRUE; + unsigned short IntValue; + + at91rm9200_EmacEnableMDIO (p_mac); + + if (!bcm5221_GetLinkSpeed (p_mac)) { + /* Try another time */ + ret = bcm5221_GetLinkSpeed (p_mac); + } + + /* Disable PHY Interrupts */ + at91rm9200_EmacReadPhy (p_mac, BCM5221_INTR, &IntValue); + /* clear FDX LED and INTR Enable */ + IntValue &= ~(BCM5221_FDX_LED | BCM5221_INTR_ENABLE); + /* set FDX, SPD, Link, INTR masks */ + IntValue |= (BCM5221_FDX_MASK | BCM5221_SPD_MASK | + BCM5221_LINK_MASK | BCM5221_INTR_MASK); + at91rm9200_EmacWritePhy (p_mac, BCM5221_INTR, &IntValue); + at91rm9200_EmacDisableMDIO (p_mac); + + return (ret); +} + + +/* + * Name: + * bcm5221_AutoNegotiate + * Description: + * MAC Autonegotiates with the partner status of same is set in the + * MAC configuration registers + * Arguments: + * dev - pointer to struct net_device + * Return value: + * TRUE - if link status set successfully + * FALSE - if link status not set + */ +unsigned char bcm5221_AutoNegotiate (AT91PS_EMAC p_mac, int *status) +{ + unsigned short value; + unsigned short PhyAnar; + unsigned short PhyAnalpar; + + /* Set bcm5221 control register */ + if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMCR, &value)) + return FALSE; + value &= ~BCM5221_AUTONEG; /* remove autonegotiation enable */ + value |= BCM5221_ISOLATE; /* Electrically isolate PHY */ + if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value)) + return FALSE; + + /* Set the Auto_negotiation Advertisement Register */ + /* MII advertising for 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */ + PhyAnar = BCM5221_TX_FDX | BCM5221_TX_HDX | + BCM5221_10_FDX | BCM5221_10_HDX | BCM5221_AN_IEEE_802_3; + if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_ANAR, &PhyAnar)) + return FALSE; + + /* Read the Control Register */ + if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMCR, &value)) + return FALSE; + + value |= BCM5221_SPEED_SELECT | BCM5221_AUTONEG | BCM5221_DUPLEX_MODE; + if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value)) + return FALSE; + /* Restart Auto_negotiation */ + value |= BCM5221_RESTART_AUTONEG; + value &= ~BCM5221_ISOLATE; + if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value)) + return FALSE; + + /*check AutoNegotiate complete */ + udelay (10000); + at91rm9200_EmacReadPhy (p_mac, BCM5221_BMSR, &value); + if (!(value & BCM5221_AUTONEG_COMP)) + return FALSE; + + /* Get the AutoNeg Link partner base page */ + if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_ANLPAR, &PhyAnalpar)) + return FALSE; + + if ((PhyAnar & BCM5221_TX_FDX) && (PhyAnalpar & BCM5221_TX_FDX)) { + /*set MII for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; + return TRUE; + } + + if ((PhyAnar & BCM5221_10_FDX) && (PhyAnalpar & BCM5221_10_FDX)) { + /*set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_FD; + return TRUE; + } + return FALSE; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/at91rm9200/dm9161.c b/cpu/arm920t/at91rm9200/dm9161.c new file mode 100755 index 0000000..4b13c23 --- /dev/null +++ b/cpu/arm920t/at91rm9200/dm9161.c @@ -0,0 +1,225 @@ +/* + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <at91rm9200_net.h> +#include <net.h> +#include <dm9161.h> + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* + * Name: + * dm9161_IsPhyConnected + * Description: + * Reads the 2 PHY ID registers + * Arguments: + * p_mac - pointer to AT91S_EMAC struct + * Return value: + * TRUE - if id read successfully + * FALSE- if error + */ +unsigned int dm9161_IsPhyConnected (AT91PS_EMAC p_mac) +{ + unsigned short Id1, Id2; + + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID1, &Id1); + at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID2, &Id2); + at91rm9200_EmacDisableMDIO (p_mac); + + if ((Id1 == (DM9161_PHYID1_OUI >> 6)) && + ((Id2 >> 10) == (DM9161_PHYID1_OUI & DM9161_LSB_MASK))) + return TRUE; + + return FALSE; +} + +/* + * Name: + * dm9161_GetLinkSpeed + * Description: + * Link parallel detection status of MAC is checked and set in the + * MAC configuration registers + * Arguments: + * p_mac - pointer to MAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +UCHAR dm9161_GetLinkSpeed (AT91PS_EMAC p_mac) +{ + unsigned short stat1, stat2; + + if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &stat1)) + return FALSE; + + if (!(stat1 & DM9161_LINK_STATUS)) /* link status up? */ + return FALSE; + + if (!at91rm9200_EmacReadPhy (p_mac, DM9161_DSCSR, &stat2)) + return FALSE; + + if ((stat1 & DM9161_100BASE_TX_FD) && (stat2 & DM9161_100FDX)) { + /*set Emac for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; + return TRUE; + } + + if ((stat1 & DM9161_10BASE_T_FD) && (stat2 & DM9161_10FDX)) { + /*set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_FD; + return TRUE; + } + + if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) { + /*set MII for 100BaseTX and Half Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_SPD; + return TRUE; + } + + if ((stat1 & DM9161_10BASE_T_HD) && (stat2 & DM9161_10HDX)) { + /*set MII for 10BaseT and Half Duplex */ + p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); + return TRUE; + } + return FALSE; +} + + +/* + * Name: + * dm9161_InitPhy + * Description: + * MAC starts checking its link by using parallel detection and + * Autonegotiation and the same is set in the MAC configuration registers + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +UCHAR dm9161_InitPhy (AT91PS_EMAC p_mac) +{ + UCHAR ret = TRUE; + unsigned short IntValue; + + at91rm9200_EmacEnableMDIO (p_mac); + + if (!dm9161_GetLinkSpeed (p_mac)) { + /* Try another time */ + ret = dm9161_GetLinkSpeed (p_mac); + } + + /* Disable PHY Interrupts */ + at91rm9200_EmacReadPhy (p_mac, DM9161_MDINTR, &IntValue); + /* set FDX, SPD, Link, INTR masks */ + IntValue |= (DM9161_FDX_MASK | DM9161_SPD_MASK | + DM9161_LINK_MASK | DM9161_INTR_MASK); + at91rm9200_EmacWritePhy (p_mac, DM9161_MDINTR, &IntValue); + at91rm9200_EmacDisableMDIO (p_mac); + + return (ret); +} + + +/* + * Name: + * dm9161_AutoNegotiate + * Description: + * MAC Autonegotiates with the partner status of same is set in the + * MAC configuration registers + * Arguments: + * dev - pointer to struct net_device + * Return value: + * TRUE - if link status set successfully + * FALSE - if link status not set + */ +UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status) +{ + unsigned short value; + unsigned short PhyAnar; + unsigned short PhyAnalpar; + + /* Set dm9161 control register */ + if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value)) + return FALSE; + value &= ~DM9161_AUTONEG; /* remove autonegotiation enable */ + value |= DM9161_ISOLATE; /* Electrically isolate PHY */ + if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) + return FALSE; + + /* Set the Auto_negotiation Advertisement Register */ + /* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */ + PhyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX | + DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3; + if (!at91rm9200_EmacWritePhy (p_mac, DM9161_ANAR, &PhyAnar)) + return FALSE; + + /* Read the Control Register */ + if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value)) + return FALSE; + + value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE; + if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) + return FALSE; + /* Restart Auto_negotiation */ + value |= DM9161_RESTART_AUTONEG; + value &= ~DM9161_ISOLATE; + if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) + return FALSE; + + /*check AutoNegotiate complete */ + udelay (10000); + at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &value); + if (!(value & DM9161_AUTONEG_COMP)) + return FALSE; + + /* Get the AutoNeg Link partner base page */ + if (!at91rm9200_EmacReadPhy (p_mac, DM9161_ANLPAR, &PhyAnalpar)) + return FALSE; + + if ((PhyAnar & DM9161_TX_FDX) && (PhyAnalpar & DM9161_TX_FDX)) { + /*set MII for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; + return TRUE; + } + + if ((PhyAnar & DM9161_10_FDX) && (PhyAnalpar & DM9161_10_FDX)) { + /*set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_FD; + return TRUE; + } + return FALSE; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/at91rm9200/ether.c b/cpu/arm920t/at91rm9200/ether.c new file mode 100755 index 0000000..67008d0 --- /dev/null +++ b/cpu/arm920t/at91rm9200/ether.c @@ -0,0 +1,299 @@ +/* + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <at91rm9200_net.h> +#include <net.h> +#include <miiphy.h> + +/* ----- Ethernet Buffer definitions ----- */ + +typedef struct { + unsigned long addr, size; +} rbf_t; + +#define RBF_ADDR 0xfffffffc +#define RBF_OWNER (1<<0) +#define RBF_WRAP (1<<1) +#define RBF_BROADCAST (1<<31) +#define RBF_MULTICAST (1<<30) +#define RBF_UNICAST (1<<29) +#define RBF_EXTERNAL (1<<28) +#define RBF_UNKOWN (1<<27) +#define RBF_SIZE 0x07ff +#define RBF_LOCAL4 (1<<26) +#define RBF_LOCAL3 (1<<25) +#define RBF_LOCAL2 (1<<24) +#define RBF_LOCAL1 (1<<23) + +#define RBF_FRAMEMAX 64 +#define RBF_FRAMELEN 0x600 + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* alignment as per Errata #11 (64 bytes) is insufficient! */ +rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512))); +rbf_t *rbfp; + +unsigned char rbf_framebuf[RBF_FRAMEMAX][RBF_FRAMELEN] __attribute((aligned(4))); + +/* structure to interface the PHY */ +AT91S_PhyOps PhyOps; + +AT91PS_EMAC p_mac; + +/*********** EMAC Phy layer Management functions *************************/ +/* + * Name: + * at91rm9200_EmacEnableMDIO + * Description: + * Enables the MDIO bit in MAC control register + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * none + */ +void at91rm9200_EmacEnableMDIO (AT91PS_EMAC p_mac) +{ + /* Mac CTRL reg set for MDIO enable */ + p_mac->EMAC_CTL |= AT91C_EMAC_MPE; /* Management port enable */ +} + +/* + * Name: + * at91rm9200_EmacDisableMDIO + * Description: + * Disables the MDIO bit in MAC control register + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * none + */ +void at91rm9200_EmacDisableMDIO (AT91PS_EMAC p_mac) +{ + /* Mac CTRL reg set for MDIO disable */ + p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; /* Management port disable */ +} + + +/* + * Name: + * at91rm9200_EmacReadPhy + * Description: + * Reads data from the PHY register + * Arguments: + * dev - pointer to struct net_device + * RegisterAddress - unsigned char + * pInput - pointer to value read from register + * Return value: + * TRUE - if data read successfully + */ +UCHAR at91rm9200_EmacReadPhy (AT91PS_EMAC p_mac, + unsigned char RegisterAddress, + unsigned short *pInput) +{ + p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | + (AT91C_EMAC_RW_R) | + (RegisterAddress << 18) | + (AT91C_EMAC_CODE_802_3); + + udelay (10000); + + *pInput = (unsigned short) p_mac->EMAC_MAN; + + return TRUE; +} + + +/* + * Name: + * at91rm9200_EmacWritePhy + * Description: + * Writes data to the PHY register + * Arguments: + * dev - pointer to struct net_device + * RegisterAddress - unsigned char + * pOutput - pointer to value to be written in the register + * Return value: + * TRUE - if data read successfully + */ +UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac, + unsigned char RegisterAddress, + unsigned short *pOutput) +{ + p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | + AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W | + (RegisterAddress << 18) | *pOutput; + + udelay (10000); + + return TRUE; +} + +int eth_init (bd_t * bd) +{ + int ret; + int i; + + p_mac = AT91C_BASE_EMAC; + + /* PIO Disable Register */ + *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER | + AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV | + AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | + AT91C_PA7_ETXCK_EREFCK; + +#ifdef CONFIG_AT91C_USE_RMII + *AT91C_PIOB_PDR = AT91C_PB19_ERXCK; + *AT91C_PIOB_BSR = AT91C_PB19_ERXCK; +#else + *AT91C_PIOB_PDR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | + AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER | + AT91C_PB13_ETX3 | AT91C_PB12_ETX2; + + /* Select B Register */ + *AT91C_PIOB_BSR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | + AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | + AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; +#endif + + *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */ + + p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */ + + /* Init Ehternet buffers */ + for (i = 0; i < RBF_FRAMEMAX; i++) { + rbfdt[i].addr = (unsigned long)rbf_framebuf[i]; + rbfdt[i].size = 0; + } + rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP; + rbfp = &rbfdt[0]; + + p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) + | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]); + p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]); + + p_mac->EMAC_RBQP = (long) (&rbfdt[0]); + p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); + + p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC) + & ~AT91C_EMAC_CLK; + +#ifdef CONFIG_AT91C_USE_RMII + p_mac->EMAC_CFG |= AT91C_EMAC_RMII; +#endif + +#if (AT91C_MASTER_CLOCK > 40000000) + /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ + p_mac->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; +#endif + + p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE; + + at91rm9200_GetPhyInterface (& PhyOps); + + if (!PhyOps.IsPhyConnected (p_mac)) + printf ("PHY not connected!!\n\r"); + + /* MII management start from here */ + if (!(p_mac->EMAC_SR & AT91C_EMAC_LINK)) { + if (!(ret = PhyOps.Init (p_mac))) { + printf ("MAC: error during MII initialization\n"); + return 0; + } + } else { + printf ("No link\n\r"); + return 0; + } + + return 0; +} + +int eth_send (volatile void *packet, int length) +{ + while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)); + p_mac->EMAC_TAR = (long) packet; + p_mac->EMAC_TCR = length; + while (p_mac->EMAC_TCR & 0x7ff); + p_mac->EMAC_TSR |= AT91C_EMAC_COMP; + return 0; +} + +int eth_rx (void) +{ + int size; + + if (!(rbfp->addr & RBF_OWNER)) + return 0; + + size = rbfp->size & RBF_SIZE; + NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size); + + rbfp->addr &= ~RBF_OWNER; + if (rbfp->addr & RBF_WRAP) + rbfp = &rbfdt[0]; + else + rbfp++; + + p_mac->EMAC_RSR |= AT91C_EMAC_REC; + + return size; +} + +void eth_halt (void) +{ +}; + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +int at91rm9200_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short * value) +{ + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacReadPhy (p_mac, reg, value); + at91rm9200_EmacDisableMDIO (p_mac); + return 0; +} + +int at91rm9200_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacWritePhy (p_mac, reg, &value); + at91rm9200_EmacDisableMDIO (p_mac); + return 0; +} + +#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */ + +int at91rm9200_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write); +#endif + return 0; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/at91rm9200/i2c.c b/cpu/arm920t/at91rm9200/i2c.c new file mode 100755 index 0000000..2565998 --- /dev/null +++ b/cpu/arm920t/at91rm9200/i2c.c @@ -0,0 +1,206 @@ +/* + * i2c Support for Atmel's AT91RM9200 Two-Wire Interface + * + * (c) Rick Bronson + * + * Borrowed heavily from original work by: + * Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> + * + * Modified to work with u-boot by (C) 2004 Gary Jennejohn garyj@denx.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ +#include <common.h> + +#ifdef CONFIG_HARD_I2C + +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#include <at91rm9200_i2c.h> + +/* define DEBUG */ + +/* + * Poll the i2c status register until the specified bit is set. + * Returns 0 if timed out (100 msec) + */ +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) { + int loop_cntr = 10000; + do { + udelay(10); + } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0)); + + return (loop_cntr > 0); +} + +/* + * Generic i2c master transfer entrypoint + * + * rw == 1 means that this is a read + */ +static int +at91_xfer(unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len, int rw) +{ + AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; + int length; + unsigned char *buf; + /* Set the TWI Master Mode Register */ + twi->TWI_MMR = (chip << 16) | (alen << 8) + | ((rw == 1) ? AT91C_TWI_MREAD : 0); + + /* Set TWI Internal Address Register with first messages data field */ + if (alen > 0) + twi->TWI_IADR = addr; + + length = len; + buf = buffer; + if (length && buf) { /* sanity check */ + if (rw) { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) { + debug ("at91_i2c: timeout 1\n"); + return 1; + } + *buf++ = twi->TWI_RHR; + } + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + debug ("at91_i2c: timeout 2\n"); + return 1; + } + } else { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + twi->TWI_THR = *buf++; + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) { + debug ("at91_i2c: timeout 3\n"); + return 1; + } + } + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + debug ("at91_i2c: timeout 4\n"); + return 1; + } + } + } + return 0; +} + +int +i2c_probe(unsigned char chip) +{ + char buffer[1]; + + return at91_xfer(chip, 0, 0, buffer, 1, 1); +} + +int +i2c_read (unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len) +{ +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* we only allow one address byte */ + if (alen > 1) + return 1; + /* XXX assume an ATMEL AT24C16 */ + if (alen == 1) { +#if 0 /* EEPROM code already sets this correctly */ + chip |= (addr >> 8) & 0xff; +#endif + addr = addr & 0xff; + } +#endif + return at91_xfer(chip, addr, alen, buffer, len, 1); +} + +int +i2c_write(unsigned char chip, unsigned int addr, int alen, + unsigned char *buffer, int len) +{ +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + int i; + unsigned char *buf; + + /* we only allow one address byte */ + if (alen > 1) + return 1; + /* XXX assume an ATMEL AT24C16 */ + if (alen == 1) { + buf = buffer; + /* do single byte writes */ + for (i = 0; i < len; i++) { +#if 0 /* EEPROM code already sets this correctly */ + chip |= (addr >> 8) & 0xff; +#endif + addr = addr & 0xff; + if (at91_xfer(chip, addr, alen, buf++, 1, 0)) + return 1; + addr++; + } + return 0; + } +#endif + return at91_xfer(chip, addr, alen, buffer, len, 0); +} + +/* + * Main initialization routine + */ +void +i2c_init(int speed, int slaveaddr) +{ + AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; + + *AT91C_PIOA_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PIOA_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PIOA_MDER = AT91C_PA25_TWD | AT91C_PA26_TWCK; + *AT91C_PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */ + + twi->TWI_IDR = 0x3ff; /* Disable all interrupts */ + twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */ + twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */ + + /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ + twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8); + + debug ("Found AT91 i2c\n"); + return; +} + +uchar i2c_reg_read(uchar i2c_addr, uchar reg) +{ + char buf; + + i2c_read(i2c_addr, reg, 1, &buf, 1); + + return(buf); +} + +void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) +{ + i2c_write(i2c_addr, reg, 1, &val, 1); +} + +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/arm920t/at91rm9200/interrupts.c b/cpu/arm920t/at91rm9200/interrupts.c new file mode 100755 index 0000000..1054602 --- /dev/null +++ b/cpu/arm920t/at91rm9200/interrupts.c @@ -0,0 +1,210 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +/*#include <asm/io.h>*/ +#include <asm/arch/hardware.h> +/*#include <asm/proc/ptrace.h>*/ + +/* the number of clocks per CFG_HZ */ +#define TIMER_LOAD_VAL (CFG_HZ_CLOCK/CFG_HZ) + +/* macro to read the 16 bit timer */ +#define READ_TIMER (tmr->TC_CV & 0x0000ffff) +AT91PS_TC tmr; + +static ulong timestamp; +static ulong lastinc; + +int interrupt_init (void) +{ + tmr = AT91C_BASE_TC0; + + /* enables TC1.0 clock */ + *AT91C_PMC_PCER = 1 << AT91C_ID_TC0; /* enable clock */ + + *AT91C_TCB0_BCR = 0; + *AT91C_TCB0_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_NONE | AT91C_TCB_TC2XC2S_NONE; + tmr->TC_CCR = AT91C_TC_CLKDIS; +#define AT91C_TC_CMR_CPCTRG (1 << 14) + /* set to MCLK/2 and restart the timer when the vlaue in TC_RC is reached */ + tmr->TC_CMR = AT91C_TC_TIMER_DIV1_CLOCK | AT91C_TC_CMR_CPCTRG; + + tmr->TC_IDR = ~0ul; + tmr->TC_RC = TIMER_LOAD_VAL; + lastinc = 0; + tmr->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; + timestamp = 0; + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay (unsigned long usec) +{ + udelay_masked(usec); +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastinc = READ_TIMER; + timestamp = 0; +} + +ulong get_timer_raw (void) +{ + ulong now = READ_TIMER; + + if (now >= lastinc) { + /* normal mode */ + timestamp += now - lastinc; + } else { + /* we have an overflow ... */ + timestamp += now + TIMER_LOAD_VAL - lastinc; + } + lastinc = now; + + return timestamp; +} + +ulong get_timer_masked (void) +{ + return get_timer_raw()/TIMER_LOAD_VAL; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + tmo = CFG_HZ_CLOCK / 1000; + tmo *= usec; + tmo /= 1000; + + endtime = get_timer_raw () + tmo; + + do { + ulong now = get_timer_raw (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out + * or toggle a GPIO pin on the AT91RM9200DK board + */ +void reset_cpu (ulong ignored) +{ + +#ifdef CONFIG_DBGU + AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; +#endif +#ifdef CONFIG_USART0 + AT91PS_USART us = AT91C_BASE_US0; +#endif +#ifdef CONFIG_USART1 + AT91PS_USART us = AT91C_BASE_US1; +#endif +#ifdef CONFIG_AT91RM9200DK + AT91PS_PIO pio = AT91C_BASE_PIOA; +#endif + + /*shutdown the console to avoid strange chars during reset */ + us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); + +#ifdef CONFIG_AT91RM9200DK + /* Clear PA19 to trigger the hard reset */ + pio->PIO_CODR = 0x00080000; + pio->PIO_OER = 0x00080000; + pio->PIO_PER = 0x00080000; +#endif + + /* this is the way Linux does it */ + + /* FIXME: + * These defines should be moved into + * include/asm-arm/arch-at91rm9200/AT91RM9200.h + * as soon as the whitespace fix gets applied. + */ + #define AT91C_ST_RSTEN (0x1 << 16) + #define AT91C_ST_EXTEN (0x1 << 17) + #define AT91C_ST_WDRST (0x1 << 0) + #define ST_WDMR *((unsigned long *)0xfffffd08) /* watchdog mode register */ + #define ST_CR *((unsigned long *)0xfffffd00) /* system clock control register */ + + ST_WDMR = AT91C_ST_RSTEN | AT91C_ST_EXTEN | 1 ; + ST_CR = AT91C_ST_WDRST; + + while (1); + /* Never reached */ +} diff --git a/cpu/arm920t/at91rm9200/lowlevel_init.S b/cpu/arm920t/at91rm9200/lowlevel_init.S new file mode 100755 index 0000000..1902bd0 --- /dev/null +++ b/cpu/arm920t/at91rm9200/lowlevel_init.S @@ -0,0 +1,205 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the at91rm9200dk board by + * (C) Copyright 2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +/* + * some parameters for the board + * + * This is based on rm9200dk.cfg for the BDI2000 from ABATRON which in + * turn is based on the boot.bin code from ATMEL + * + */ + +/* flash */ +#define MC_PUIA 0xFFFFFF10 +#define MC_PUP 0xFFFFFF50 +#define MC_PUER 0xFFFFFF54 +#define MC_ASR 0xFFFFFF04 +#define MC_AASR 0xFFFFFF08 +#define EBI_CFGR 0xFFFFFF64 +#define SMC2_CSR 0xFFFFFF70 + +/* clocks */ +#define PLLAR 0xFFFFFC28 +#define PLLBR 0xFFFFFC2C +#define MCKR 0xFFFFFC30 + +#define AT91C_BASE_CKGR 0xFFFFFC20 +#define CKGR_MOR 0 + +/* sdram */ +#define PIOC_ASR 0xFFFFF870 +#define PIOC_BSR 0xFFFFF874 +#define PIOC_PDR 0xFFFFF804 +#define EBI_CSA 0xFFFFFF60 +#define SDRC_CR 0xFFFFFF98 +#define SDRC_MR 0xFFFFFF90 +#define SDRC_TR 0xFFFFFF94 + + +_MTEXT_BASE: +#undef START_FROM_MEM +#ifdef START_FROM_MEM + .word TEXT_BASE-PHYS_FLASH_1 +#else + .word TEXT_BASE +#endif + +.globl lowlevel_init +lowlevel_init: + /* Get the CKGR Base Address */ + ldr r1, =AT91C_BASE_CKGR + /* Main oscillator Enable register */ +#ifdef CFG_USE_MAIN_OSCILLATOR + ldr r0, =0x0000FF01 /* Enable main oscillator, OSCOUNT = 0xFF */ +#else + ldr r0, =0x0000FF00 /* Disable main oscillator, OSCOUNT = 0xFF */ +#endif + str r0, [r1, #CKGR_MOR] + /* Add loop to compensate Main Oscillator startup time */ + ldr r0, =0x00000010 +LoopOsc: + subs r0, r0, #1 + bhi LoopOsc + + /* memory control configuration */ + /* this isn't very elegant, but what the heck */ + ldr r0, =SMRDATA + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + add r2, r0, #80 +0: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 0b + /* delay - this is all done by guess */ + ldr r0, =0x00010000 +1: + subs r0, r0, #1 + bhi 1b + ldr r0, =SMRDATA1 + ldr r1, _MTEXT_BASE + sub r0, r0, r1 + add r2, r0, #176 +2: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 2b + + /* switch from FastBus to Asynchronous clock mode */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0xC0000000 @ set bit 31 (iA) and 30 (nF) + mcr p15, 0, r0, c1, c0, 0 + + /* everything is fine now */ + mov pc, lr + + .ltorg + +SMRDATA: + .word MC_PUIA + .word MC_PUIA_VAL + .word MC_PUP + .word MC_PUP_VAL + .word MC_PUER + .word MC_PUER_VAL + .word MC_ASR + .word MC_ASR_VAL + .word MC_AASR + .word MC_AASR_VAL + .word EBI_CFGR + .word EBI_CFGR_VAL + .word SMC2_CSR + .word SMC2_CSR_VAL + .word PLLAR + .word PLLAR_VAL + .word PLLBR + .word PLLBR_VAL + .word MCKR + .word MCKR_VAL + /* SMRDATA is 80 bytes long */ + /* here there's a delay of 100 */ +SMRDATA1: + .word PIOC_ASR + .word PIOC_ASR_VAL + .word PIOC_BSR + .word PIOC_BSR_VAL + .word PIOC_PDR + .word PIOC_PDR_VAL + .word EBI_CSA + .word EBI_CSA_VAL + .word SDRC_CR + .word SDRC_CR_VAL + .word SDRC_MR + .word SDRC_MR_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL1 + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL2 + .word SDRAM1 + .word SDRAM_VAL + .word SDRC_TR + .word SDRC_TR_VAL + .word SDRAM + .word SDRAM_VAL + .word SDRC_MR + .word SDRC_MR_VAL3 + .word SDRAM + .word SDRAM_VAL + /* SMRDATA1 is 176 bytes long */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/cpu/arm920t/at91rm9200/lxt972.c b/cpu/arm920t/at91rm9200/lxt972.c new file mode 100755 index 0000000..f12c59c --- /dev/null +++ b/cpu/arm920t/at91rm9200/lxt972.c @@ -0,0 +1,191 @@ +/* + * + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Adapted for KwikByte KB920x board: 22APR2005 + */ + +#include <common.h> +#include <at91rm9200_net.h> +#include <net.h> +#include <lxt971a.h> + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* + * Name: + * lxt972_IsPhyConnected + * Description: + * Reads the 2 PHY ID registers + * Arguments: + * p_mac - pointer to AT91S_EMAC struct + * Return value: + * TRUE - if id read successfully + * FALSE- if error + */ +unsigned int lxt972_IsPhyConnected (AT91PS_EMAC p_mac) +{ + unsigned short Id1, Id2; + + at91rm9200_EmacEnableMDIO (p_mac); + at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_ID1, &Id1); + at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_ID2, &Id2); + at91rm9200_EmacDisableMDIO (p_mac); + + if ((Id1 == (0x0013)) && ((Id2 & 0xFFF0) == 0x78E0)) + return TRUE; + + return FALSE; +} + +/* + * Name: + * lxt972_GetLinkSpeed + * Description: + * Link parallel detection status of MAC is checked and set in the + * MAC configuration registers + * Arguments: + * p_mac - pointer to MAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +UCHAR lxt972_GetLinkSpeed (AT91PS_EMAC p_mac) +{ + unsigned short stat1; + + if (!at91rm9200_EmacReadPhy (p_mac, PHY_LXT971_STAT2, &stat1)) + return FALSE; + + if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link status up? */ + return FALSE; + + if (stat1 & PHY_LXT971_STAT2_100BTX) { + + if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { + + /*set Emac for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; + } else { + + /*set Emac for 100BaseTX and Half Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_SPD; + } + + return TRUE; + + } else { + + if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { + + /*set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & + ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) + | AT91C_EMAC_FD; + } else { + + /*set MII for 10BaseT and Half Duplex */ + p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); + } + + return TRUE; + } + + return FALSE; +} + + +/* + * Name: + * lxt972_InitPhy + * Description: + * MAC starts checking its link by using parallel detection and + * Autonegotiation and the same is set in the MAC configuration registers + * Arguments: + * p_mac - pointer to struct AT91S_EMAC + * Return value: + * TRUE - if link status set succesfully + * FALSE - if link status not set + */ +UCHAR lxt972_InitPhy (AT91PS_EMAC p_mac) +{ + UCHAR ret = TRUE; + + at91rm9200_EmacEnableMDIO (p_mac); + + if (!lxt972_GetLinkSpeed (p_mac)) { + /* Try another time */ + ret = lxt972_GetLinkSpeed (p_mac); + } + + /* Disable PHY Interrupts */ + at91rm9200_EmacWritePhy (p_mac, PHY_LXT971_INT_ENABLE, 0); + + at91rm9200_EmacDisableMDIO (p_mac); + + return (ret); +} + + +/* + * Name: + * lxt972_AutoNegotiate + * Description: + * MAC Autonegotiates with the partner status of same is set in the + * MAC configuration registers + * Arguments: + * dev - pointer to struct net_device + * Return value: + * TRUE - if link status set successfully + * FALSE - if link status not set + */ +UCHAR lxt972_AutoNegotiate (AT91PS_EMAC p_mac, int *status) +{ + unsigned short value; + + /* Set lxt972 control register */ + if (!at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_CTRL, &value)) + return FALSE; + + /* Restart Auto_negotiation */ + value |= PHY_COMMON_CTRL_RES_AUTO; + if (!at91rm9200_EmacWritePhy (p_mac, PHY_COMMON_CTRL, &value)) + return FALSE; + + /*check AutoNegotiate complete */ + udelay (10000); + at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_STAT, &value); + if (!(value & PHY_COMMON_STAT_AN_COMP)) + return FALSE; + + return (lxt972_GetLinkSpeed (p_mac)); +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/at91rm9200/serial.c b/cpu/arm920t/at91rm9200/serial.c new file mode 100755 index 0000000..a281932 --- /dev/null +++ b/cpu/arm920t/at91rm9200/serial.c @@ -0,0 +1,112 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) +#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1 +#endif + +/* ggi thunder */ +#ifdef CONFIG_DBGU +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; +#endif +#ifdef CONFIG_USART0 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US0; +#endif +#ifdef CONFIG_USART1 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US1; +#endif + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + int baudrate; + + if ((baudrate = gd->baudrate) <= 0) + baudrate = CONFIG_BAUDRATE; + /* MASTER_CLOCK/(16 * baudrate) */ + us->US_BRGR = (AT91C_MASTER_CLOCK >> 4) / (unsigned)baudrate; +} + +int serial_init (void) +{ + /* make any port initializations specific to this port */ +#ifdef CONFIG_DBGU + *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; /* PA 31 & 30 */ + *AT91C_PMC_PCER = 1 << AT91C_ID_SYS; /* enable clock */ +#endif +#ifdef CONFIG_USART0 + *AT91C_PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART0; /* enable clock */ +#endif +#ifdef CONFIG_USART1 + *AT91C_PIOB_PDR = AT91C_PB21_TXD1 | AT91C_PB20_RXD1; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART1; /* enable clock */ +#endif + serial_setbrg (); + + us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; + us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; + us->US_MR = + (AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | + AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT); + us->US_IMR = ~0ul; + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + serial_putc ('\r'); + while ((us->US_CSR & AT91C_US_TXRDY) == 0); + us->US_THR = c; +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + while ((us->US_CSR & AT91C_US_RXRDY) == 0); + return us->US_RHR; +} + +int serial_tstc (void) +{ + return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY); +} diff --git a/cpu/arm920t/at91rm9200/usb_ohci.c b/cpu/arm920t/at91rm9200/usb_ohci.c new file mode 100755 index 0000000..5b2c56c --- /dev/null +++ b/cpu/arm920t/at91rm9200/usb_ohci.c @@ -0,0 +1,1635 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200. + * + * (C) Copyright 2003 + * Gary Jennejohn, DENX Software Engineering <gj@denx.de> + * + * Note: Much of this code has been derived from Linux 2.4 + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell + * + * Modified for the MP2USB by (C) Copyright 2005 Eric Benard + * ebenard@eukrea.com - based on s3c24x0's driver + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +/* + * IMPORTANT NOTES + * 1 - you MUST define LITTLEENDIAN in the configuration file for the + * board or this driver will NOT work! + * 2 - this driver is intended for use with USB Mass Storage Devices + * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! + * 3 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG + * to activate workaround for bug #41 or this driver will NOT work! + */ + +#include <common.h> +/* #include <pci.h> no PCI on the S3C24X0 */ + +#ifdef CONFIG_USB_OHCI + +#include <asm/arch/hardware.h> + +#include <malloc.h> +#include <usb.h> +#include "usb_ohci.h" + +#define OHCI_USE_NPS /* force NoPowerSwitching mode */ +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define readl(a) (*((vu_long *)(a))) +#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) + +#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#undef DEBUG +#ifdef DEBUG +#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while(0) +#endif /* DEBUG */ +#define err(format, arg...) printf("ERROR: " format "\n", ## arg) +#undef SHOW_INFO +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format "\n", ## arg) +#else +#define info(format, arg...) do {} while(0) +#endif + +#define m16_swap(x) swap_16(x) +#define m32_swap(x) swap_32(x) + +/* global ohci_t */ +static ohci_t gohci; +/* this must be aligned to a 256 byte boundary */ +struct ohci_hcca ghcca[1]; +/* a pointer to the aligned storage */ +struct ohci_hcca *phcca; +/* this allocates EDs for all possible endpoints */ +struct ohci_device ohci_dev; +/* urb_priv */ +urb_priv_t urb_priv; +/* RHSC flag */ +int got_rhsc; +/* device which was disconnected */ +struct usb_device *devgone; + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define OHCI_QUIRK_AMD756 0xabcd +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + + +/* forward declaration */ +static int hc_interrupt (void); +static void +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (urb_priv_t * urb) +{ + int i; + int last; + struct td * td; + + last = urb->length - 1; + if (last >= 0) { + for (i = 0; i <= last; i++) { + td = urb->td[i]; + if (td) { + td->usb_dev = NULL; + urb->td[i] = NULL; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) +{ + urb_priv_t * purb = &urb_priv; + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); + } + if (transfer_len > 0 && buffer) { + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t *ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *)m32_swap(ed_p); + printf (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printf ("\n"); + } +} + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + ed_t *edp = (ed_t *)value; + + if (value) { + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); + } +} + +static char * hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +/* dump control and status registers */ +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); +#ifdef CONFIG_AT91C_PQFP_UHPBUG + ndp = (ndp == 2) ? 1:0; +#endif + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + ohci_t *ohci; + ed_t * ed; + urb_priv_t *purb_priv; + int i, size = 0; + + ohci = &gohci; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + err("sohci_submit_job: EPIPE"); + return -1; + } + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (dev, pipe))) { + err("sohci_submit_job: ENOMEM"); + return -1; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + } + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d", size, N_URB_TD); + return -1; + } + purb_priv = &urb_priv; + purb_priv->pipe = pipe; + + /* fill the private part of the URB */ + purb_priv->length = size; + purb_priv->ed = ed; + purb_priv->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + purb_priv->td[i] = td_alloc (dev); + if (!purb_priv->td[i]) { + purb_priv->length = i; + urb_free_priv (purb_priv); + err("sohci_submit_job: ENOMEM"); + return -1; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (purb_priv); + err("sohci_submit_job: EINVAL"); + return -1; + } + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t *ohci = &gohci; + + return m16_swap (ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +static int ep_unlink (ohci_t *ohci, ed_t *ed) +{ + ed->hwINFO |= m32_swap (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +{ + td_t *td; + ed_t *ed_ret; + volatile ed_t *ed; + + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + err("ep_add_ed: pending delete"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (usb_dev); + ed->hwTailP = m32_swap (td); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + ohci_dev.ed_cnt++; + } + + ed->hwINFO = m32_swap (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) +{ + volatile td_t *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + + if (index > urb_priv->length) { + err("index > length"); + return; + } + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->data = (__u32)data; +#ifdef OHCI_FILL_TRACE + if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); + printf("\n"); + } +#endif + if (!len) + data = 0; + + td->hwINFO = m32_swap (info); + td->hwCBP = m32_swap (data); + if (data) + td->hwBE = m32_swap (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = m32_swap (td_pt); + td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +{ + ohci_t *ohci = &gohci; + int data_len = transfer_len; + void *data; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + } + urb->td_cnt = 0; + if (data_len) + data = buffer; + else + data = 0; + + switch (usb_pipetype (pipe)) { + case PIPE_BULK: + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + cnt++; + + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, setup, 8, dev, cnt++, urb); + if (data_len > 0) { + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, dev, cnt++, urb); + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + } + if (urb->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + urb_priv_t *lurb_priv = &urb_priv; + + tdINFO = m32_swap (td->hwINFO); + tdBE = m32_swap (td->hwBE); + tdCBP = m32_swap (td->hwCBP); + + + if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + lurb_priv->actual_length += tdBE - td->data + 1; + else + lurb_priv->actual_length += tdCBP - td->data; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t *ohci) +{ + __u32 td_list_hc; + td_t *td_rev = NULL; + td_t *td_list = NULL; + urb_priv_t *lurb_priv = NULL; + + td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = (td_t *)td_list_hc; + + if (TD_CC_GET (m32_swap (td_list->hwINFO))) { + lurb_priv = &urb_priv; + dbg(" USB-error/status: %x : %p", + TD_CC_GET (m32_swap (td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & m32_swap (0x1)) { + if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { + td_list->ed->hwHeadP = + (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) | + (td_list->ed->hwHeadP & m32_swap (0x2)); + lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= m32_swap (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; + } + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* td done list */ +static int dl_done_list (ohci_t *ohci, td_t *td_list) +{ + td_t *td_list_next = NULL; + ed_t *ed; + int cc = 0; + int stat = 0; + /* urb_t *urb; */ + urb_priv_t *lurb_priv; + __u32 tdINFO, edHeadP, edTailP; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + lurb_priv = &urb_priv; + tdINFO = m32_swap (td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length(td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (cc != 0) { + dbg("ConditionCode %#x", cc); + stat = cc_to_error[cc]; + } + + if (ed->state != ED_NEW) { + edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; + edTailP = m32_swap (ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + + td_list = td_list_next; + } + return stat; +} + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'O', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#ifdef DEBUG +#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#else +#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#endif +#define RD_RH_STAT roothub_status(&gohci) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) + +/* request to virtual root hub */ + +int rh_check_port_status(ohci_t *controller) +{ + __u32 temp, ndp, i; + int res; + + res = -1; + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); +#ifdef CONFIG_AT91C_PQFP_UHPBUG + ndp = (ndp == 2) ? 1:0; +#endif + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + /* check for a device disconnect */ + if (((temp & (RH_PS_PESC | RH_PS_CSC)) == + (RH_PS_PESC | RH_PS_CSC)) && + ((temp & RH_PS_CCS) == 0)) { + res = i; + break; + } + } + return res; +} + +static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *cmd) +{ + void * data = buffer; + int leni = transfer_len; + int len = 0; + int stat = 0; + __u32 datab[4]; + __u8 *data_buf = (__u8 *)datab; + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + +#ifdef DEBUG +urb_priv.actual_length = 0; +pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + info("Root-Hub submit IRQ: NOT implemented"); + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = m16_swap (cmd->value); + wIndex = m16_swap (cmd->index); + wLength = m16_swap (cmd->length); + + info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", + dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = m16_swap (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = m32_swap ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); + } + break; + + case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if(wValue==0x0300) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); + } + if(wValue==0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); + } + default: + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a (&gohci); + + data_buf [0] = 9; /* min length; */ + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; +#ifdef CONFIG_AT91C_PQFP_UHPBUG + data_buf [2] = (data_buf [2] == 2) ? 1:0; +#endif + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + /* corresponds to data_buf[4-7] */ + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (&gohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); + } + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + dbg ("unsupported root hub command"); + stat = USB_ST_STALLED; + } + +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#else + wait_ms(1); +#endif + + len = min_t(int, len, leni); + if (data != data_buf) + memcpy (data, data_buf, len); + dev->act_len = len; + dev->status = stat; + +#ifdef DEBUG + if (transfer_len) + urb_priv.actual_length = transfer_len; + pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); +#else + wait_ms(1); +#endif + + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/* common code for handling submit messages - used for all but root hub */ +/* accesses. */ +int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + int stat = 0; + int maxsize = usb_maxpacket(dev, pipe); + int timeout; + + /* device pulled? Shortcut the action. */ + if (devgone == dev) { + dev->status = USB_ST_CRC_ERR; + return 0; + } + +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_common_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + + if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { + err("sohci_submit_job failed"); + return -1; + } + + wait_ms(10); + /* ohci_dump_status(&gohci); */ + + /* allow more time for a BULK device to react - some are slow */ +#define BULK_TO 5000 /* timeout in milliseconds */ + if (usb_pipetype (pipe) == PIPE_BULK) + timeout = BULK_TO; + else + timeout = 100; + + /* wait for it to complete */ + for (;;) { + /* check whether the controller is done */ + stat = hc_interrupt(); + if (stat < 0) { + stat = USB_ST_CRC_ERR; + break; + } + if (stat >= 0 && stat != 0xff) { + /* 0xff is returned for an SF-interrupt */ + break; + } + if (--timeout) { + wait_ms(1); + } else { + err("CTL:TIMEOUT "); + stat = USB_ST_CRC_ERR; + break; + } + } + /* we got an Root Hub Status Change interrupt */ + if (got_rhsc) { +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#endif + got_rhsc = 0; + /* abuse timeout */ + timeout = rh_check_port_status(&gohci); + if (timeout >= 0) { +#if 0 /* this does nothing useful, but leave it here in case that changes */ + /* the called routine adds 1 to the passed value */ + usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); +#endif + /* + * XXX + * This is potentially dangerous because it assumes + * that only one device is ever plugged in! + */ + devgone = dev; + } + } + + dev->status = stat; + dev->act_len = transfer_len; + +#ifdef DEBUG + pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + + /* free TDs in urb_priv */ + urb_free_priv (&urb_priv); + return 0; +} + +/* submit routines called from usb.c */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + info("submit_bulk_msg"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + int maxsize = usb_maxpacket(dev, pipe); + + info("submit_control_msg"); +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_control_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { + gohci.rh.dev = dev; + /* root hub - redirect */ + return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, + setup); + } + + return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg"); + return -1; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (ohci_t *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + dbg("%s\n", __FUNCTION__); + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + info("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n", + ohci->slot_name, + readl(&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); + + /* HC Reset requires max 10 us delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + __u32 mask; + unsigned int fminterval; + + ohci->disabled = 1; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* disable all interrupts */ + mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | + OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | + OHCI_INTR_OC | OHCI_INTR_MIE); + writel (mask, &ohci->regs->intrdisable); + /* clear all interrupts */ + mask &= ~OHCI_INTR_MIE; + writel (mask, &ohci->regs->intrstatus); + /* Choose the interrupts we care about now - but w/o MIE */ + mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrenable); + +#ifdef OHCI_USE_NPS + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + +#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) + /* POTPGT delay is bits 24-31, in 2 ms units. */ + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->rh.devnum = 0; + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static int +hc_interrupt (void) +{ + ohci_t *ohci = &gohci; + struct ohci_regs *regs = ohci->regs; + int ints; + int stat = -1; + + if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + } else { + ints = readl (®s->intrstatus); + } + + /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + + if (ints & OHCI_INTR_RHSC) { + got_rhsc = 1; + } + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->slot_name); + /* e.g. due to PCI Master/Target Abort */ + +#ifdef DEBUG + ohci_dump (ohci, 1); +#else + wait_ms(1); +#endif + /* FIXME: be optimistic, hope that bug won't repeat often. */ + /* Make some non-interrupt context restart the controller. */ + /* Count and limit the retries though; either hardware or */ + /* software errors can go forever... */ + hc_reset (ohci); + return -1; + } + + if (ints & OHCI_INTR_WDH) { + wait_ms(1); + writel (OHCI_INTR_WDH, ®s->intrdisable); + stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun\n"); + writel (OHCI_INTR_SO, ®s->intrenable); + stat = -1; + } + + /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ + if (ints & OHCI_INTR_SF) { + unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1; + wait_ms(1); + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list[frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); + stat = 0xff; + } + + writel (ints, ®s->intrstatus); + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t *ohci) +{ + dbg ("USB HC release ohci usb-%s", ohci->slot_name); + + if (!ohci->disabled) + hc_reset (ohci); +} + +/*-------------------------------------------------------------------------*/ + +/* + * low level initalisation routine, called from usb.c + */ +static char ohci_inited = 0; + +int usb_lowlevel_init(void) +{ + /* + * Enable USB host clock. + */ + *AT91C_PMC_SCER = AT91C_PMC_UHP; /* 48MHz clock enabled for UHP */ + *AT91C_PMC_PCER = 1 << AT91C_ID_UHP; /* Peripheral Clock Enable Register */ + + memset (&gohci, 0, sizeof (ohci_t)); + memset (&urb_priv, 0, sizeof (urb_priv_t)); + + /* align the storage */ + if ((__u32)&ghcca[0] & 0xff) { + err("HCCA not aligned!!"); + return -1; + } + phcca = &ghcca[0]; + info("aligned ghcca %p", phcca); + memset(&ohci_dev, 0, sizeof(struct ohci_device)); + if ((__u32)&ohci_dev.ed[0] & 0x7) { + err("EDs not aligned!!"); + return -1; + } + memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); + if ((__u32)gtd & 0x7) { + err("TDs not aligned!!"); + return -1; + } + ptd = gtd; + gohci.hcca = phcca; + memset (phcca, 0, sizeof (struct ohci_hcca)); + + gohci.disabled = 1; + gohci.sleeping = 0; + gohci.irq = -1; + gohci.regs = (struct ohci_regs *)AT91_USB_HOST_BASE; + + gohci.flags = 0; + gohci.slot_name = "at91rm9200"; + + if (hc_reset (&gohci) < 0) { + hc_release_ohci (&gohci); + /* Initialization failed */ + *AT91C_PMC_PCER = AT91C_ID_UHP; + *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */ + return -1; + } + + /* FIXME this is a second HC reset; why?? */ +/* writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); + wait_ms (10);*/ + + if (hc_start (&gohci) < 0) { + err ("can't start usb-%s", gohci.slot_name); + hc_release_ohci (&gohci); + /* Initialization failed */ + *AT91C_PMC_PCER = AT91C_ID_UHP; + *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */ + return -1; + } + +#ifdef DEBUG + ohci_dump (&gohci, 1); +#else + wait_ms(1); +#endif + ohci_inited = 1; + return 0; +} + +int usb_lowlevel_stop(void) +{ + /* this gets called really early - before the controller has */ + /* even been initialized! */ + if (!ohci_inited) + return 0; + /* TODO release any interrupts, etc. */ + /* call hc_release_ohci() here ? */ + hc_reset (&gohci); + /* may not want to do this */ + *AT91C_PMC_PCER = 1 << AT91C_ID_UHP; + *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */ + return 0; +} + +#endif /* CONFIG_USB_OHCI */ diff --git a/cpu/arm920t/at91rm9200/usb_ohci.h b/cpu/arm920t/at91rm9200/usb_ohci.h new file mode 100755 index 0000000..ecb4e93 --- /dev/null +++ b/cpu/arm920t/at91rm9200/usb_ohci.h @@ -0,0 +1,419 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> + * + * usb-ohci.h + */ + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ + /* No Error */ 0, + /* CRC Error */ USB_ST_CRC_ERR, + /* Bit Stuff */ USB_ST_BIT_ERR, + /* Data Togg */ USB_ST_CRC_ERR, + /* Stall */ USB_ST_STALLED, + /* DevNotResp */ -1, + /* PIDCheck */ USB_ST_BIT_ERR, + /* UnExpPID */ USB_ST_BIT_ERR, + /* DataOver */ USB_ST_BUF_ERR, + /* DataUnder */ USB_ST_BUF_ERR, + /* reservd */ -1, + /* reservd */ -1, + /* BufferOver */ USB_ST_BUF_ERR, + /* BuffUnder */ USB_ST_BUF_ERR, + /* Not Access */ -1, + /* Not Access */ -1 +}; + +/* ED States */ + +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed *ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed *ed_rm_list; + + struct usb_device *usb_dev; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW[MAXPSW]; + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct usb_device *usb_dev; + int transfer_len; + __u32 data; + + __u32 unused2[2]; +} __attribute((aligned(32))); +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *dev; /* was urb */ + void *int_addr; + int send; + int interval; +}; + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +#define N_URB_TD 48 +typedef struct +{ + ed_t *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + int state; + unsigned long pipe; + int actual_length; + td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t *ed_bulktail; /* last endpoint of bulk list */ + ed_t *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_device *dev[32]; + struct virt_root_hub rh; + + const char *slot_name; +} ohci_t; + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; +}; + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); + +/*-------------------------------------------------------------------------*/ + +/* we need more TDs than EDs */ +#define NUM_TD 64 + +/* +1 so we can align the storage */ +td_t gtd[NUM_TD+1]; +/* pointers to aligned storage */ +td_t *ptd; + +/* TDs ... */ +static inline struct td * +td_alloc (struct usb_device *usb_dev) +{ + int i; + struct td *td; + + td = NULL; + for (i = 0; i < NUM_TD; i++) + { + if (ptd[i].usb_dev == NULL) + { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + + return td; +} + +static inline void +ed_free (struct ed *ed) +{ + ed->usb_dev = NULL; +} diff --git a/cpu/arm920t/config.mk b/cpu/arm920t/config.mk new file mode 100755 index 0000000..14e0cd7 --- /dev/null +++ b/cpu/arm920t/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# Some descriptions of such software. Copyright (c) 2008 WonderMedia Technologies, Inc. +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software Foundation, +# either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +# +# WonderMedia Technologies, Inc. +# 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +# + +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +PLATFORM_CPPFLAGS += -march=armv7-a +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) diff --git a/cpu/arm920t/cpu.c b/cpu/arm920t/cpu.c new file mode 100755 index 0000000..cbfbb3f --- /dev/null +++ b/cpu/arm920t/cpu.c @@ -0,0 +1,204 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <arm920t.h> + +#ifdef CONFIG_USE_IRQ +DECLARE_GLOBAL_DATA_PTR; +#endif + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1 (void) +{ + unsigned long value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c1, c0, 0 @ read control reg\n" + : "=r" (value) + : + : "memory"); + +#ifdef MMU_DEBUG + printf ("p15/c1 is = %08lx\n", value); +#endif + return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1 (unsigned long value) +{ +#ifdef MMU_DEBUG + printf ("write %08lx to p15/c1\n", value); +#endif + __asm__ __volatile__( + "mcr p15, 0, %0, c1, c0, 0 @ write it back\n" + : + : "r" (value) + : "memory"); + + read_p15_c1 (); +} + +static void cp_delay (void) +{ + volatile int i; + + /* copro seems to need some delay between reading and writing */ + for (i = 0; i < 100; i++); +} + +/* See also ARM920T Technical reference Manual */ +#define C1_MMU (1<<0) /* mmu off/on */ +#define C1_ALIGN (1<<1) /* alignment faults off/on */ +#define C1_DC (1<<2) /* dcache off/on */ + +#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ +#define C1_SYS_PROT (1<<8) /* system protection */ +#define C1_ROM_PROT (1<<9) /* ROM protection */ +#define C1_IC (1<<12) /* icache off/on */ +#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ + + +int cpu_init (void) +{ + /* + * setup up stacks if necessary + */ +#ifdef CONFIG_USE_IRQ + IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; + FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; +#endif + return 0; +} + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + unsigned long i; + + disable_interrupts (); + + /* turn off I/D-cache */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + i &= ~(C1_DC | C1_IC); + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + + i = 0; + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); /* invalidate icache */ + asm ("mcr p15, 0, %0, c7, c5, 6": :"r" (i)); /* invalidate BP array */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* DSB */ + asm ("mcr p15, 0, %0, c7, c5, 4": :"r" (i)); /* ISB */ + + return (0); +} + +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + disable_interrupts (); + reset_cpu (0); + /*NOTREACHED*/ + return (0); +} + +void icache_enable (void) +{ + ulong reg; + + reg = read_p15_c1 (); /* get control reg. */ + cp_delay (); + write_p15_c1 (reg | C1_IC); +} + +void icache_disable (void) +{ + ulong reg; + + reg = read_p15_c1 (); + cp_delay (); + write_p15_c1 (reg & ~C1_IC); +} + +int icache_status (void) +{ + return (read_p15_c1 () & C1_IC) != 0; +} + +#ifdef USE_920T_MMU +/* It makes no sense to use the dcache if the MMU is not enabled */ +void dcache_enable (void) +{ + ulong reg; + + reg = read_p15_c1 (); + cp_delay (); + write_p15_c1 (reg | C1_DC); +} + +void dcache_disable (void) +{ + ulong reg; + + reg = read_p15_c1 (); + cp_delay (); + reg &= ~C1_DC; + write_p15_c1 (reg); +} + +int dcache_status (void) +{ + return (read_p15_c1 () & C1_DC) != 0; +} +#endif diff --git a/cpu/arm920t/imx/Makefile b/cpu/arm920t/imx/Makefile new file mode 100755 index 0000000..8865f82 --- /dev/null +++ b/cpu/arm920t/imx/Makefile @@ -0,0 +1,42 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = generic.o interrupts.o serial.o speed.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/imx/generic.c b/cpu/arm920t/imx/generic.c new file mode 100755 index 0000000..aa7c8c1 --- /dev/null +++ b/cpu/arm920t/imx/generic.c @@ -0,0 +1,90 @@ +/* + * arch/arm/mach-imx/generic.c + * + * author: Sascha Hauer + * Created: april 20th, 2004 + * Copyright: Synertronixx GmbH + * + * Common code for i.MX machines + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> + +#ifdef CONFIG_IMX + +#include <asm/arch/imx-regs.h> + +void imx_gpio_mode(int gpio_mode) +{ + unsigned int pin = gpio_mode & GPIO_PIN_MASK; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10; + unsigned int tmp; + + /* Pullup enable */ + if(gpio_mode & GPIO_PUEN) + PUEN(port) |= (1<<pin); + else + PUEN(port) &= ~(1<<pin); + + /* Data direction */ + if(gpio_mode & GPIO_OUT) + DDIR(port) |= 1<<pin; + else + DDIR(port) &= ~(1<<pin); + + /* Primary / alternate function */ + if(gpio_mode & GPIO_AF) + GPR(port) |= (1<<pin); + else + GPR(port) &= ~(1<<pin); + + /* use as gpio? */ + if( ocr == 3 ) + GIUS(port) |= (1<<pin); + else + GIUS(port) &= ~(1<<pin); + + /* Output / input configuration */ + /* FIXME: I'm not very sure about OCR and ICONF, someone + * should have a look over it + */ + if(pin<16) { + tmp = OCR1(port); + tmp &= ~( 3<<(pin*2)); + tmp |= (ocr << (pin*2)); + OCR1(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA1(port) &= ~( 3<<(pin*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB1(port) &= ~( 3<<(pin*2)); + } else { + tmp = OCR2(port); + tmp &= ~( 3<<((pin-16)*2)); + tmp |= (ocr << ((pin-16)*2)); + OCR2(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA2(port) &= ~( 3<<((pin-16)*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB2(port) &= ~( 3<<((pin-16)*2)); + } +} + +#endif /* CONFIG_IMX */ diff --git a/cpu/arm920t/imx/interrupts.c b/cpu/arm920t/imx/interrupts.c new file mode 100755 index 0000000..03ce06d --- /dev/null +++ b/cpu/arm920t/imx/interrupts.c @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <arm920t.h> +#include <asm/arch/imx-regs.h> + +int interrupt_init (void) +{ + int i; + /* setup GP Timer 1 */ + TCTL1 = TCTL_SWR; + for ( i=0; i<100; i++) TCTL1 = 0; /* We have no udelay by now */ + TPRER1 = get_PERCLK1() / 1000000; /* 1 MHz */ + TCTL1 |= TCTL_FRR | (1<<1); /* Freerun Mode, PERCLK1 input */ + + reset_timer_masked(); + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked (); +} + +void set_timer (ulong t) +{ + /* nop */ +} + +void reset_timer_masked (void) +{ + TCTL1 &= ~TCTL_TEN; + TCTL1 |= TCTL_TEN; /* Enable timer */ +} + +ulong get_timer_masked (void) +{ + return TCN1; +} + +void udelay_masked (unsigned long usec) +{ + ulong endtime = get_timer_masked() + usec; + signed long diff; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +void udelay (unsigned long usec) +{ + udelay_masked(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + + return tbclk; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu (ulong ignored) +{ + /* Disable watchdog and set Time-Out field to 0 */ + WCR = 0x00000000; + + /* Write Service Sequence */ + WSR = 0x00005555; + WSR = 0x0000AAAA; + + /* Enable watchdog */ + WCR = 0x00000001; + + while (1); + /*NOTREACHED*/ +} + +#endif /* defined (CONFIG_IMX) */ diff --git a/cpu/arm920t/imx/serial.c b/cpu/arm920t/imx/serial.c new file mode 100755 index 0000000..9dbaa56 --- /dev/null +++ b/cpu/arm920t/imx/serial.c @@ -0,0 +1,201 @@ +/* + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +#ifndef CONFIG_IMX_SERIAL_NONE + +#if defined CONFIG_IMX_SERIAL1 +#define UART_BASE IMX_UART1_BASE +#elif defined CONFIG_IMX_SERIAL2 +#define UART_BASE IMX_UART2_BASE +#else +#error "define CONFIG_IMX_SERIAL1, CONFIG_IMX_SERIAL2 or CONFIG_IMX_SERIAL_NONE" +#endif + +struct imx_serial { + volatile uint32_t urxd[16]; + volatile uint32_t utxd[16]; + volatile uint32_t ucr1; + volatile uint32_t ucr2; + volatile uint32_t ucr3; + volatile uint32_t ucr4; + volatile uint32_t ufcr; + volatile uint32_t usr1; + volatile uint32_t usr2; + volatile uint32_t uesc; + volatile uint32_t utim; + volatile uint32_t ubir; + volatile uint32_t ubmr; + volatile uint32_t ubrc; + volatile uint32_t bipr[4]; + volatile uint32_t bmpr[4]; + volatile uint32_t uts; +}; + +void serial_setbrg (void) +{ + serial_init(); +} + +extern void imx_gpio_mode(int gpio_mode); + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; +#ifdef CONFIG_IMX_SERIAL1 + imx_gpio_mode(PC11_PF_UART1_TXD); + imx_gpio_mode(PC12_PF_UART1_RXD); +#else + imx_gpio_mode(PB30_PF_UART2_TXD); + imx_gpio_mode(PB31_PF_UART2_RXD); +#endif + + /* Disable UART */ + base->ucr1 &= ~UCR1_UARTEN; + + /* Set to default POR state */ + + base->ucr1 = 0x00000004; + base->ucr2 = 0x00000000; + base->ucr3 = 0x00000000; + base->ucr4 = 0x00008040; + base->uesc = 0x0000002B; + base->utim = 0x00000000; + base->ubir = 0x00000000; + base->ubmr = 0x00000000; + base->uts = 0x00000000; + /* Set clocks */ + base->ucr4 |= UCR4_REF16; + + /* Configure FIFOs */ + base->ufcr = 0xa81; + + /* Set the numerator value minus one of the BRM ratio */ + base->ubir = (CONFIG_BAUDRATE / 100) - 1; + + /* Set the denominator value minus one of the BRM ratio */ + base->ubmr = 10000 - 1; + + /* Set to 8N1 */ + base->ucr2 &= ~UCR2_PREN; + base->ucr2 |= UCR2_WS; + base->ucr2 &= ~UCR2_STPB; + + /* Ignore RTS */ + base->ucr2 |= UCR2_IRTS; + + /* Enable UART */ + base->ucr1 |= UCR1_UARTEN | UCR1_UARTCLKEN; + + /* Enable FIFOs */ + base->ucr2 |= UCR2_SRST | UCR2_RXEN | UCR2_TXEN; + + /* Clear status flags */ + base->usr2 |= USR2_ADET | + USR2_DTRF | + USR2_IDLE | + USR2_IRINT | + USR2_WAKE | + USR2_RTSF | + USR2_BRCD | + USR2_ORE | + USR2_RDR; + + /* Clear status flags */ + base->usr1 |= USR1_PARITYERR | + USR1_RTSD | + USR1_ESCF | + USR1_FRAMERR | + USR1_AIRINT | + USR1_AWAKE; + return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is successful, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + unsigned char ch; + + while(base->uts & UTS_RXEMPTY); + + ch = (char)base->urxd[0]; + + return ch; +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ +} +#endif + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + + /* Wait for Tx FIFO not full */ + while (base->uts & UTS_TXFULL); + + base->utxd[0] = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + + /* If receive fifo is empty, return false */ + if (base->uts & UTS_RXEMPTY) + return 0; + return 1; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} +#endif /* CONFIG_IMX_SERIAL_NONE */ +#endif /* defined CONFIG_IMX */ diff --git a/cpu/arm920t/imx/speed.c b/cpu/arm920t/imx/speed.c new file mode 100755 index 0000000..1e29698 --- /dev/null +++ b/cpu/arm920t/imx/speed.c @@ -0,0 +1,102 @@ +/* + * + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * SH FIXME: 16780000 in our case + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +ulong get_systemPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 spctl0 = SPCTL0; + u32 mfi = (spctl0 >> 10) & 0xf; + u32 mfn = spctl0 & 0x3f; + u32 mfd = (spctl0 >> 16) & 0x3f; + u32 pd = (spctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYSPLL_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_mcuPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 mpctl0 = MPCTL0; + u32 mfi = (mpctl0 >> 10) & 0xf; + u32 mfn = mpctl0 & 0x3f; + u32 mfd = (mpctl0 >> 16) & 0x3f; + u32 pd = (mpctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYS_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_FCLK(void) +{ + return (( CSCR>>15)&1) ? get_mcuPLLCLK()>>1 : get_mcuPLLCLK(); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + u32 bclkdiv = (( CSCR >> 10 ) & 0xf) + 1; + printf("bclkdiv: %d\n", bclkdiv); + return get_systemPLLCLK() / bclkdiv; +} + +/* return BCLK frequency */ +ulong get_BCLK(void) +{ + return get_HCLK(); +} + +ulong get_PERCLK1(void) +{ + return get_systemPLLCLK() / (((PCDR) & 0xf)+1); +} + +ulong get_PERCLK2(void) +{ + return get_systemPLLCLK() / (((PCDR>>4) & 0xf)+1); +} + +ulong get_PERCLK3(void) +{ + return get_systemPLLCLK() / (((PCDR>>16) & 0x7f)+1); +} + +#endif /* defined (CONFIG_IMX) */ diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c new file mode 100755 index 0000000..a43a3ed --- /dev/null +++ b/cpu/arm920t/interrupts.c @@ -0,0 +1,174 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <arm920t.h> +#include <asm/proc-armv/ptrace.h> + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts (void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + : "=r" (temp) + : + : "memory"); +} + + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts (void) +{ + unsigned long old,temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts (void) +{ + return; +} +int disable_interrupts (void) +{ + return 0; +} +#endif + + +void bad_mode (void) +{ + panic ("Resetting CPU ...\n"); + reset_cpu (0); +} + +void show_regs (struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes (regs); + + printf ("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer (regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf ("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf (" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled (regs) ? "on" : "off", + fast_interrupts_enabled (regs) ? "on" : "off", + processor_modes[processor_mode (regs)], + thumb_mode (regs) ? " (T)" : ""); +} + +void do_undefined_instruction (struct pt_regs *pt_regs) +{ + printf ("undefined instruction\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_software_interrupt (struct pt_regs *pt_regs) +{ + printf ("software interrupt\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_prefetch_abort (struct pt_regs *pt_regs) +{ + printf ("prefetch abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_data_abort (struct pt_regs *pt_regs) +{ + printf ("data abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_not_used (struct pt_regs *pt_regs) +{ + printf ("not used\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_fiq (struct pt_regs *pt_regs) +{ + printf ("fast interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_irq (struct pt_regs *pt_regs) +{ +#if defined (CONFIG_USE_IRQ) && defined (CONFIG_ARCH_INTEGRATOR) + /* ASSUMED to be a timer interrupt */ + /* Just clear it - count handled in */ + /* integratorap.c */ + *(volatile ulong *)(CFG_TIMERBASE + 0x0C) = 0; +#else + printf ("interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +#endif +} diff --git a/cpu/arm920t/ks8695/Makefile b/cpu/arm920t/ks8695/Makefile new file mode 100755 index 0000000..ac49060 --- /dev/null +++ b/cpu/arm920t/ks8695/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = interrupts.o serial.o +SOBJS = lowlevel_init.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/ks8695/interrupts.c b/cpu/arm920t/ks8695/interrupts.c new file mode 100755 index 0000000..883d689 --- /dev/null +++ b/cpu/arm920t/ks8695/interrupts.c @@ -0,0 +1,112 @@ +/* + * (C) Copyright 2004-2005, Greg Ungerer <greg.ungerer@opengear.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/platform.h> + +/* + * Handy KS8695 register access functions. + */ +#define ks8695_read(a) *((volatile ulong *) (KS8695_IO_BASE + (a))) +#define ks8695_write(a,v) *((volatile ulong *) (KS8695_IO_BASE + (a))) = (v) + +int timer_inited; +ulong timer_ticks; + +int interrupt_init (void) +{ + /* nothing happens here - we don't setup any IRQs */ + return (0); +} + +/* + * Initial timer set constants. Nothing complicated, just set for a 1ms + * tick. + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_1) +#define TIMER_COUNT (TIMER_INTERVAL / 2) +#define TIMER_PULSE TIMER_COUNT + +void reset_timer_masked(void) +{ + /* Set the hadware timer for 1ms */ + ks8695_write(KS8695_TIMER1, TIMER_COUNT); + ks8695_write(KS8695_TIMER1_PCOUNT, TIMER_PULSE); + ks8695_write(KS8695_TIMER_CTRL, 0x2); + timer_ticks = 0; + timer_inited++; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer_masked(void) +{ + /* Check for timer wrap */ + if (ks8695_read(KS8695_INT_STATUS) & KS8695_INTMASK_TIMERINT1) { + /* Clear interrupt condition */ + ks8695_write(KS8695_INT_STATUS, KS8695_INTMASK_TIMERINT1); + timer_ticks++; + } + return timer_ticks; +} + +ulong get_timer(ulong base) +{ + return (get_timer_masked() - base); +} + +void set_timer(ulong t) +{ + timer_ticks = t; +} + +void udelay(ulong usec) +{ + ulong start = get_timer_masked(); + ulong end; + + if (!timer_inited) + reset_timer(); + + /* Only 1ms resolution :-( */ + end = usec / 1000; + while (get_timer(start) < end) + ; +} + +void reset_cpu (ulong ignored) +{ + ulong tc; + + /* Set timer0 to watchdog, and let it timeout */ + tc = ks8695_read(KS8695_TIMER_CTRL) & 0x2; + ks8695_write(KS8695_TIMER_CTRL, tc); + ks8695_write(KS8695_TIMER0, ((10 << 8) | 0xff)); + ks8695_write(KS8695_TIMER_CTRL, (tc | 0x1)); + + /* Should only wait here till watchdog resets */ + for (;;) + ; +} diff --git a/cpu/arm920t/ks8695/lowlevel_init.S b/cpu/arm920t/ks8695/lowlevel_init.S new file mode 100755 index 0000000..e9f1227 --- /dev/null +++ b/cpu/arm920t/ks8695/lowlevel_init.S @@ -0,0 +1,205 @@ +/* + * lowlevel_init.S - basic hardware initialization for the KS8695 CPU + * + * Copyright (c) 2004-2005, Greg Ungerer <greg.ungerer@opengear.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/platform.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +/* + ************************************************************************* + * + * Handy dandy macros + * + ************************************************************************* + */ + +/* Delay a bit */ +.macro DELAY_FOR cycles, reg0 + ldr \reg0, =\cycles + subs \reg0, \reg0, #1 + subne pc, pc, #0xc +.endm + +/* + ************************************************************************* + * + * Some local storage. + * + ************************************************************************* + */ + +/* Should we boot with an interactive console or not */ +.globl serial_console + +/* + ************************************************************************* + * + * Raw hardware initialization code. The important thing is to get + * SDRAM setup and running. We do some other basic things here too, + * like getting the PLL set for high speed, and init the LEDs. + * + ************************************************************************* + */ + +.globl lowlevel_init +lowlevel_init: + +#if DEBUG + /* + * enable UART for early debug trace + */ + ldr r1, =(KS8695_IO_BASE+KS8695_UART_DIVISOR) + mov r2, #0xd9 + str r2, [r1] /* 115200 baud */ + ldr r1, =(KS8695_IO_BASE+KS8695_UART_LINE_CTRL) + mov r2, #0x03 + str r2, [r1] /* 8 data bits, no parity, 1 stop */ + ldr r1, =(KS8695_IO_BASE+KS8695_UART_TX_HOLDING) + mov r2, #0x41 + str r2, [r1] /* write 'A' */ +#endif +#if DEBUG + ldr r1, =(KS8695_IO_BASE+KS8695_UART_TX_HOLDING) + mov r2, #0x42 + str r2, [r1] +#endif + + /* + * remap the memory and flash regions. we want to end up with + * ram from address 0, and flash at 32MB. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_CTRL0) + ldr r2, =0xbfc00040 + str r2, [r1] /* large flash map */ + ldr pc, =(highflash+0x02000000-0x00f00000) /* jump to high flash address */ +highflash: + ldr r2, =0x8fe00040 + str r2, [r1] /* remap flash range */ + + /* + * remap the second select region to the 4MB immediately after + * the first region. This way if you have a larger flash (say 8Mb) + * then you can have it all mapped nicely. Has no effect if you + * only have a 4Mb or smaller flash. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_CTRL1) + ldr r2, =0x9fe40040 + str r2, [r1] /* remap flash2 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_GENERAL) + ldr r2, =0x30000005 + str r2, [r1] /* enable both flash selects */ + +#ifdef CONFIG_CM41xx + /* + * map the second flash chip, using the external IO lines. + */ + ldr r1, =(KS8695_IO_BASE+KS8695_IO_CTRL0) + ldr r2, =0xafe80b6d + str r2, [r1] /* remap io0 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_IO_CTRL1) + ldr r2, =0xbfec0b6d + str r2, [r1] /* remap io1 region, contiguous */ + ldr r1, =(KS8695_IO_BASE+KS8695_MEM_GENERAL) + ldr r2, =0x30050005 + str r2, [r1] /* enable second flash */ +#endif + + /* + * before relocating, we have to setup RAM timing + */ + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_CTRL0) +#if (PHYS_SDRAM_1_SIZE == 0x02000000) + ldr r2, =0x7fc0000e /* 32MB */ +#else + ldr r2, =0x3fc0000e /* 16MB */ +#endif + str r2, [r1] /* configure sdram bank0 setup */ + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_CTRL1) + mov r2, #0 + str r2, [r1] /* configure sdram bank1 setup */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_GENERAL) + ldr r2, =0x0000000a + str r2, [r1] /* set RAS/CAS timing */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_BUFFER) + ldr r2, =0x00030000 + str r2, [r1] /* send NOP command */ + DELAY_FOR 0x100, r0 + ldr r2, =0x00010000 + str r2, [r1] /* send PRECHARGE-ALL */ + DELAY_FOR 0x100, r0 + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_REFRESH) + ldr r2, =0x00000020 + str r2, [r1] /* set for fast refresh */ + DELAY_FOR 0x100, r0 + ldr r2, =0x00000190 + str r2, [r1] /* set normal refresh timing */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SDRAM_BUFFER) + ldr r2, =0x00020033 + str r2, [r1] /* send mode command */ + DELAY_FOR 0x100, r0 + ldr r2, =0x01f00000 + str r2, [r1] /* enable sdram fifos */ + + /* + * set pll to top speed + */ + ldr r1, =(KS8695_IO_BASE+KS8695_SYSTEN_BUS_CLOCK) + mov r2, #0 + str r2, [r1] /* set pll clock to 166MHz */ + + ldr r1, =(KS8695_IO_BASE+KS8695_SWITCH_CTRL0) + ldr r2, [r1] /* Get switch ctrl0 register */ + and r2, r2, #0x0fc00000 /* Mask out LED control bits */ + orr r2, r2, #0x01800000 /* Set Link/activity/speed actions */ + str r2, [r1] + +#ifdef CONFIG_CM4008 + ldr r1, =(KS8695_IO_BASE+KS8695_GPIO_MODE) + ldr r2, =0x0000fe30 + str r2, [r1] /* enable LED's as outputs */ + ldr r1, =(KS8695_IO_BASE+KS8695_GPIO_DATA) + ldr r2, =0x0000fe20 + str r2, [r1] /* turn on power LED */ +#endif +#if defined(CONFIG_CM4008) || defined(CONFIG_CM41xx) + ldr r2, [r1] /* get current GPIO input data */ + tst r2, #0x8 /* check if "erase" depressed */ + beq nobutton + mov r2, #0 /* be quiet on boot, no console */ + ldr r1, =serial_console + str r2, [r1] +nobutton: +#endif + + add lr, lr, #0x02000000 /* flash is now mapped high */ + add ip, ip, #0x02000000 /* this is a hack */ + mov pc, lr /* all done, return */ + +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/cpu/arm920t/ks8695/serial.c b/cpu/arm920t/ks8695/serial.c new file mode 100755 index 0000000..0dd91e7 --- /dev/null +++ b/cpu/arm920t/ks8695/serial.c @@ -0,0 +1,116 @@ +/* + * serial.c -- KS8695 serial driver + * + * (C) Copyright 2004, Greg Ungerer <greg.ungerer@opengear.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/platform.h> + +#ifndef CONFIG_SERIAL1 +#error "Bad: you didn't configure serial ..." +#endif + +/* + * Define the UART hardware register access structure. + */ +struct ks8695uart { + unsigned int RX; /* 0x00 - Receive data (r) */ + unsigned int TX; /* 0x04 - Transmit data (w) */ + unsigned int FCR; /* 0x08 - Fifo Control (r/w) */ + unsigned int LCR; /* 0x0c - Line Control (r/w) */ + unsigned int MCR; /* 0x10 - Modem Control (r/w) */ + unsigned int LSR; /* 0x14 - Line Status (r/w) */ + unsigned int MSR; /* 0x18 - Modem Status (r/w) */ + unsigned int BD; /* 0x1c - Baud Rate (r/w) */ + unsigned int SR; /* 0x20 - Status (r/w) */ +}; + +#define KS8695_UART_ADDR ((void *) (KS8695_IO_BASE + KS8695_UART_RX_BUFFER)) +#define KS8695_UART_CLK 25000000 + + +/* + * Under some circumstances we want to be "quiet" and not issue any + * serial output - though we want u-boot to otherwise work and behave + * the same. By default be noisy. + */ +int serial_console = 1; + + +void serial_setbrg(void) +{ + DECLARE_GLOBAL_DATA_PTR; + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + + /* Set to global baud rate and 8 data bits, no parity, 1 stop bit*/ + uartp->BD = KS8695_UART_CLK / gd->baudrate; + uartp->LCR = KS8695_UART_LINEC_WLEN8; +} + +int serial_init(void) +{ + serial_console = 1; + serial_setbrg(); + return 0; +} + +void serial_raw_putc(const char c) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + int i; + + for (i = 0; (i < 0x100000); i++) { + if (uartp->LSR & KS8695_UART_LINES_TXFE) + break; + } + + uartp->TX = c; +} + +void serial_putc(const char c) +{ + if (serial_console) { + serial_raw_putc(c); + if (c == '\n') + serial_raw_putc('\r'); + } +} + +int serial_tstc(void) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + if (serial_console) + return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0); + return 0; +} + +void serial_puts(const char *s) +{ + char c; + while ((c = *s++) != 0) + serial_putc(c); +} + +int serial_getc(void) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + + while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0) + ; + return (uartp->RX); +} diff --git a/cpu/arm920t/s3c24x0/Makefile b/cpu/arm920t/s3c24x0/Makefile new file mode 100755 index 0000000..af9e4ef --- /dev/null +++ b/cpu/arm920t/s3c24x0/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = i2c.o interrupts.o serial.o speed.o \ + usb_ohci.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/s3c24x0/i2c.c b/cpu/arm920t/s3c24x0/i2c.c new file mode 100755 index 0000000..ef56cd1 --- /dev/null +++ b/cpu/arm920t/s3c24x0/i2c.c @@ -0,0 +1,447 @@ +/* + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same I2C controller inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include <common.h> + +#ifdef CONFIG_DRIVER_S3C24X0_I2C + +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif +#include <i2c.h> + +#ifdef CONFIG_HARD_I2C + +#define I2C_WRITE 0 +#define I2C_READ 1 + +#define I2C_OK 0 +#define I2C_NOK 1 +#define I2C_NACK 2 +#define I2C_NOK_LA 3 /* Lost arbitration */ +#define I2C_NOK_TOUT 4 /* time out */ + +#define I2CSTAT_BSY 0x20 /* Busy bit */ +#define I2CSTAT_NACK 0x01 /* Nack bit */ +#define I2CCON_IRPND 0x10 /* Interrupt pending bit */ +#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ +#define I2C_MODE_MR 0x80 /* Master Receive Mode */ +#define I2C_START_STOP 0x20 /* START / STOP */ +#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ + +#define I2C_TIMEOUT 1 /* 1 second */ + + +static int GetI2CSDA(void) +{ + S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); + +#ifdef CONFIG_S3C2410 + return (gpio->GPEDAT & 0x8000) >> 15; +#endif +#ifdef CONFIG_S3C2400 + return (gpio->PGDAT & 0x0020) >> 5; +#endif +} + +#if 0 +static void SetI2CSDA(int x) +{ + rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15; +} +#endif + +static void SetI2CSCL(int x) +{ + S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); + +#ifdef CONFIG_S3C2410 + gpio->GPEDAT = (gpio->GPEDAT & ~0x4000) | (x&1) << 14; +#endif +#ifdef CONFIG_S3C2400 + gpio->PGDAT = (gpio->PGDAT & ~0x0040) | (x&1) << 6; +#endif +} + + +static int WaitForXfer (void) +{ + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + int i, status; + + i = I2C_TIMEOUT * 10000; + status = i2c->IICCON; + while ((i > 0) && !(status & I2CCON_IRPND)) { + udelay (100); + status = i2c->IICCON; + i--; + } + + return (status & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; +} + +static int IsACK (void) +{ + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + + return (!(i2c->IICSTAT & I2CSTAT_NACK)); +} + +static void ReadWriteByte (void) +{ + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + + i2c->IICCON &= ~I2CCON_IRPND; +} + +void i2c_init (int speed, int slaveadd) +{ + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + S3C24X0_GPIO *const gpio = S3C24X0_GetBase_GPIO (); + ulong freq, pres = 16, div; + int i, status; + + /* wait for some time to give previous transfer a chance to finish */ + + i = I2C_TIMEOUT * 1000; + status = i2c->IICSTAT; + while ((i > 0) && (status & I2CSTAT_BSY)) { + udelay (1000); + status = i2c->IICSTAT; + i--; + } + + if ((status & I2CSTAT_BSY) || GetI2CSDA () == 0) { +#ifdef CONFIG_S3C2410 + ulong old_gpecon = gpio->GPECON; +#endif +#ifdef CONFIG_S3C2400 + ulong old_gpecon = gpio->PGCON; +#endif + /* bus still busy probably by (most) previously interrupted transfer */ + +#ifdef CONFIG_S3C2410 + /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */ + gpio->GPECON = (gpio->GPECON & ~0xF0000000) | 0x10000000; +#endif +#ifdef CONFIG_S3C2400 + /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */ + gpio->PGCON = (gpio->PGCON & ~0x00003c00) | 0x00000c00; +#endif + + /* toggle I2CSCL until bus idle */ + SetI2CSCL (0); + udelay (1000); + i = 10; + while ((i > 0) && (GetI2CSDA () != 1)) { + SetI2CSCL (1); + udelay (1000); + SetI2CSCL (0); + udelay (1000); + i--; + } + SetI2CSCL (1); + udelay (1000); + + /* restore pin functions */ +#ifdef CONFIG_S3C2410 + gpio->GPECON = old_gpecon; +#endif +#ifdef CONFIG_S3C2400 + gpio->PGCON = old_gpecon; +#endif + } + + /* calculate prescaler and divisor values */ + freq = get_PCLK (); + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + while ((freq / pres / (div + 1)) > speed) + div++; + + /* set prescaler, divisor according to freq, also set + * ACKGEN, IRQ */ + i2c->IICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0); + + /* init to SLAVE REVEIVE and set slaveaddr */ + i2c->IICSTAT = 0; + i2c->IICADD = slaveadd; + /* program Master Transmit (and implicit STOP) */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; + +} + +/* + * cmd_type is 0 for write, 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + */ +static +int i2c_transfer (unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], unsigned short data_len) +{ + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + int i, status, result; + + if (data == 0 || data_len == 0) { + /*Don't support data transfer of no length or to address 0 */ + printf ("i2c_transfer: bad call\n"); + return I2C_NOK; + } + + /* Check I2C bus idle */ + i = I2C_TIMEOUT * 1000; + status = i2c->IICSTAT; + while ((i > 0) && (status & I2CSTAT_BSY)) { + udelay (1000); + status = i2c->IICSTAT; + i--; + } + + if (status & I2CSTAT_BSY) + return I2C_NOK_TOUT; + + i2c->IICCON |= 0x80; + result = I2C_OK; + + switch (cmd_type) { + case I2C_WRITE: + if (addr && addr_len) { + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; + i = 0; + while ((i < addr_len) && (result == I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = addr[i]; + ReadWriteByte (); + i++; + } + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = data[i]; + ReadWriteByte (); + i++; + } + } else { + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; + i = 0; + while ((i < data_len) && (result = I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = data[i]; + ReadWriteByte (); + i++; + } + } + + if (result == I2C_OK) + result = WaitForXfer (); + + /* send STOP */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + ReadWriteByte (); + break; + + case I2C_READ: + if (addr && addr_len) { + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT |= I2C_START_STOP; + result = WaitForXfer (); + if (IsACK ()) { + i = 0; + while ((i < addr_len) && (result == I2C_OK)) { + i2c->IICDS = addr[i]; + ReadWriteByte (); + result = WaitForXfer (); + i++; + } + + i2c->IICDS = chip; + /* resend START */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA | + I2C_START_STOP; + ReadWriteByte (); + result = WaitForXfer (); + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) + i2c->IICCON &= ~0x80; + ReadWriteByte (); + result = WaitForXfer (); + data[i] = i2c->IICDS; + i++; + } + } else { + result = I2C_NACK; + } + + } else { + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT |= I2C_START_STOP; + result = WaitForXfer (); + + if (IsACK ()) { + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) + i2c->IICCON &= ~0x80; + ReadWriteByte (); + result = WaitForXfer (); + data[i] = i2c->IICDS; + i++; + } + } else { + result = I2C_NACK; + } + } + + /* send STOP */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + ReadWriteByte (); + break; + + default: + printf ("i2c_transfer: bad call\n"); + result = I2C_NOK; + break; + } + + return (result); +} + +int i2c_probe (uchar chip) +{ + uchar buf[1]; + + buf[0] = 0; + + /* + * What is needed is to send the chip address and verify that the + * address was <ACK>ed (i.e. there was a chip at that address which + * drove the data line low). + */ + return (i2c_transfer (I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK); +} + +int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + uchar xaddr[4]; + int ret; + + if (alen > 4) { + printf ("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + if ((ret = + i2c_transfer (I2C_READ, chip << 1, &xaddr[4 - alen], alen, + buffer, len)) != 0) { + printf ("I2c read: failed %d\n", ret); + return 1; + } + return 0; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + uchar xaddr[4]; + + if (alen > 4) { + printf ("I2C write: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + return (i2c_transfer + (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, + len) != 0); +} +#endif /* CONFIG_HARD_I2C */ + +#endif /* CONFIG_DRIVER_S3C24X0_I2C */ diff --git a/cpu/arm920t/s3c24x0/interrupts.c b/cpu/arm920t/s3c24x0/interrupts.c new file mode 100755 index 0000000..3ec9b54 --- /dev/null +++ b/cpu/arm920t/s3c24x0/interrupts.c @@ -0,0 +1,217 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) + +#include <arm920t.h> +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +int timer_load_val = 0; + +/* macro to read the 16 bit timer */ +static inline ulong READ_TIMER(void) +{ + S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS(); + + return (timers->TCNTO4 & 0xffff); +} + +static ulong timestamp; +static ulong lastdec; + +int interrupt_init (void) +{ + S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS(); + + /* use PWM Timer 4 because it has no output */ + /* prescaler for Timer 4 is 16 */ + timers->TCFG0 = 0x0f00; + if (timer_load_val == 0) + { + /* + * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 + * (default) and prescaler = 16. Should be 10390 + * @33.25MHz and 15625 @ 50 MHz + */ + timer_load_val = get_PCLK()/(2 * 16 * 100); + } + /* load value for 10 ms timeout */ + lastdec = timers->TCNTB4 = timer_load_val; + /* auto load, manual update of Timer 4 */ + timers->TCON = (timers->TCON & ~0x0700000) | 0x600000; + /* auto load, start Timer 4 */ + timers->TCON = (timers->TCON & ~0x0700000) | 0x500000; + timestamp = 0; + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay (unsigned long usec) +{ + ulong tmo; + ulong start = get_timer(0); + + tmo = usec / 1000; + tmo *= (timer_load_val * 100); + tmo /= 1000; + + while ((ulong)(get_timer_masked () - start) < tmo) + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER(); + timestamp = 0; +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER(); + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + timer_load_val - now; + } + lastdec = now; + + return timestamp; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { + tmo = usec / 1000; + tmo *= (timer_load_val * 100); + tmo /= 1000; + } else { + tmo = usec * (timer_load_val * 100); + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + +#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB) + tbclk = timer_load_val * 100; +#elif defined(CONFIG_SMDK2410) || defined(CONFIG_VCMA9) + tbclk = CFG_HZ; +#else +# error "tbclk not configured" +#endif + + return tbclk; +} + +/* + * reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu (ulong ignored) +{ + volatile S3C24X0_WATCHDOG * watchdog; + +#ifdef CONFIG_TRAB + extern void disable_vfd (void); + + disable_vfd(); +#endif + + watchdog = S3C24X0_GetBase_WATCHDOG(); + + /* Disable watchdog */ + watchdog->WTCON = 0x0000; + + /* Initialize watchdog timer count register */ + watchdog->WTCNT = 0x0001; + + /* Enable watchdog timer; assert reset at timer timeout */ + watchdog->WTCON = 0x0021; + + while(1); /* loop forever and wait for reset to happen */ + + /*NOTREACHED*/ +} + +#endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */ diff --git a/cpu/arm920t/s3c24x0/serial.c b/cpu/arm920t/s3c24x0/serial.c new file mode 100755 index 0000000..8327443 --- /dev/null +++ b/cpu/arm920t/s3c24x0/serial.c @@ -0,0 +1,182 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) + +#if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +#ifdef CONFIG_SERIAL1 +#define UART_NR S3C24X0_UART0 + +#elif defined(CONFIG_SERIAL2) +# if defined(CONFIG_TRAB) +# error "TRAB supports only CONFIG_SERIAL1" +# endif +#define UART_NR S3C24X0_UART1 + +#elif defined(CONFIG_SERIAL3) +# if defined(CONFIG_TRAB) +# #error "TRAB supports only CONFIG_SERIAL1" +# endif +#define UART_NR S3C24X0_UART2 + +#else +#error "Bad: you didn't configure serial ..." +#endif + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + int i; + unsigned int reg = 0; + + /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ + reg = get_PCLK() / (16 * gd->baudrate) - 1; + + /* FIFO enable, Tx/Rx FIFO clear */ + uart->UFCON = 0x07; + uart->UMCON = 0x0; + /* Normal,No parity,1 stop,8 bit */ + uart->ULCON = 0x3; + /* + * tx=level,rx=edge,disable timeout int.,enable rx error int., + * normal,interrupt or polling + */ + uart->UCON = 0x245; + uart->UBRDIV = reg; + +#ifdef CONFIG_HWFLOW + uart->UMCON = 0x1; /* RTS up */ +#endif + for (i = 0; i < 100; i++); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + + /* wait for character to arrive */ + while (!(uart->UTRSTAT & 0x1)); + + return uart->URXH & 0xff; +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ + switch(on) { + case 0: + default: + break; /* return current */ + case 1: + hwflow = 1; /* turn on */ + break; + case -1: + hwflow = 0; /* turn off */ + break; + } + return hwflow; +} +#endif + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet = 0; +void disable_putc(void) +{ + be_quiet = 1; +} + +void enable_putc(void) +{ + be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); +#ifdef CONFIG_MODEM_SUPPORT + if (be_quiet) + return; +#endif + + /* wait for room in the tx FIFO */ + while (!(uart->UTRSTAT & 0x2)); + +#ifdef CONFIG_HWFLOW + /* Wait for CTS up */ + while(hwflow && !(uart->UMSTAT & 0x1)) + ; +#endif + + uart->UTXH = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ + S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); + + return uart->UTRSTAT & 0x1; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */ diff --git a/cpu/arm920t/s3c24x0/speed.c b/cpu/arm920t/s3c24x0/speed.c new file mode 100755 index 0000000..e0dca62 --- /dev/null +++ b/cpu/arm920t/s3c24x0/speed.c @@ -0,0 +1,101 @@ +/* + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same PLL and clock machinery inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include <common.h> +#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) + +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +#define MPLL 0 +#define UPLL 1 + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +static ulong get_PLLCLK(int pllreg) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + ulong r, m, p, s; + + if (pllreg == MPLL) + r = clk_power->MPLLCON; + else if (pllreg == UPLL) + r = clk_power->UPLLCON; + else + hang(); + + m = ((r & 0xFF000) >> 12) + 8; + p = ((r & 0x003F0) >> 4) + 2; + s = r & 0x3; + + return((CONFIG_SYS_CLK_FREQ * m) / (p << s)); +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + return(get_PLLCLK(MPLL)); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + + return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK()); +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + + return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK()); +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + return(get_PLLCLK(UPLL)); +} + +#endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */ diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c new file mode 100755 index 0000000..b4cc744 --- /dev/null +++ b/cpu/arm920t/s3c24x0/usb_ohci.c @@ -0,0 +1,1688 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the S3C2400. + * + * (C) Copyright 2003 + * Gary Jennejohn, DENX Software Engineering <gj@denx.de> + * + * Note: Much of this code has been derived from Linux 2.4 + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +/* + * IMPORTANT NOTES + * 1 - you MUST define LITTLEENDIAN in the configuration file for the + * board or this driver will NOT work! + * 2 - this driver is intended for use with USB Mass Storage Devices + * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! + */ + +#include <common.h> +/* #include <pci.h> no PCI on the S3C24X0 */ + +#ifdef CONFIG_USB_OHCI + +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +#include <malloc.h> +#include <usb.h> +#include "usb_ohci.h" + +#define OHCI_USE_NPS /* force NoPowerSwitching mode */ +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ + + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define readl(a) (*((vu_long *)(a))) +#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) + +#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#undef DEBUG +#ifdef DEBUG +#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while(0) +#endif /* DEBUG */ +#define err(format, arg...) printf("ERROR: " format "\n", ## arg) +#undef SHOW_INFO +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format "\n", ## arg) +#else +#define info(format, arg...) do {} while(0) +#endif + +#define m16_swap(x) swap_16(x) +#define m32_swap(x) swap_32(x) + +/* global ohci_t */ +static ohci_t gohci; +/* this must be aligned to a 256 byte boundary */ +struct ohci_hcca ghcca[1]; +/* a pointer to the aligned storage */ +struct ohci_hcca *phcca; +/* this allocates EDs for all possible endpoints */ +struct ohci_device ohci_dev; +/* urb_priv */ +urb_priv_t urb_priv; +/* RHSC flag */ +int got_rhsc; +/* device which was disconnected */ +struct usb_device *devgone; +/* flag guarding URB transation */ +int urb_finished = 0; + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define OHCI_QUIRK_AMD756 0xabcd +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + + +/* forward declaration */ +static int hc_interrupt (void); +static void +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (urb_priv_t * urb) +{ + int i; + int last; + struct td * td; + + last = urb->length - 1; + if (last >= 0) { + for (i = 0; i <= last; i++) { + td = urb->td[i]; + if (td) { + td->usb_dev = NULL; + urb->td[i] = NULL; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) +{ + urb_priv_t * purb = &urb_priv; + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); + } + if (transfer_len > 0 && buffer) { + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t *ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *)m32_swap(ed_p); + printf (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printf ("\n"); + } +} + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + ed_t *edp = (ed_t *)value; + + if (value) { + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); + } +} + +static char * hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +/* dump control and status registers */ +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + ohci_t *ohci; + ed_t * ed; + urb_priv_t *purb_priv; + int i, size = 0; + + ohci = &gohci; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + err("sohci_submit_job: EPIPE"); + return -1; + } + + /* if we have an unfinished URB from previous transaction let's + * fail and scream as quickly as possible so as not to corrupt + * further communication */ + if (!urb_finished) { + err("sohci_submit_job: URB NOT FINISHED"); + return -1; + } + /* we're about to begin a new transaction here so mark the URB unfinished */ + urb_finished = 0; + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (dev, pipe))) { + err("sohci_submit_job: ENOMEM"); + return -1; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + } + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d", size, N_URB_TD); + return -1; + } + purb_priv = &urb_priv; + purb_priv->pipe = pipe; + + /* fill the private part of the URB */ + purb_priv->length = size; + purb_priv->ed = ed; + purb_priv->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + purb_priv->td[i] = td_alloc (dev); + if (!purb_priv->td[i]) { + purb_priv->length = i; + urb_free_priv (purb_priv); + err("sohci_submit_job: ENOMEM"); + return -1; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (purb_priv); + err("sohci_submit_job: EINVAL"); + return -1; + } + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t *ohci = &gohci; + + return m16_swap (ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +static int ep_unlink (ohci_t *ohci, ed_t *ed) +{ + ed->hwINFO |= m32_swap (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +{ + td_t *td; + ed_t *ed_ret; + volatile ed_t *ed; + + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + err("ep_add_ed: pending delete"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (usb_dev); + ed->hwTailP = m32_swap (td); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + ohci_dev.ed_cnt++; + } + + ed->hwINFO = m32_swap (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) +{ + volatile td_t *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + + if (index > urb_priv->length) { + err("index > length"); + return; + } + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->data = (__u32)data; +#ifdef OHCI_FILL_TRACE + if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); + printf("\n"); + } +#endif + if (!len) + data = 0; + + td->hwINFO = m32_swap (info); + td->hwCBP = m32_swap (data); + if (data) + td->hwBE = m32_swap (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = m32_swap (td_pt); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +{ + ohci_t *ohci = &gohci; + int data_len = transfer_len; + void *data; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + } + urb->td_cnt = 0; + if (data_len) + data = buffer; + else + data = 0; + + switch (usb_pipetype (pipe)) { + case PIPE_BULK: + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + cnt++; + + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, setup, 8, dev, cnt++, urb); + if (data_len > 0) { + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, dev, cnt++, urb); + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + } + if (urb->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + urb_priv_t *lurb_priv = &urb_priv; + + tdINFO = m32_swap (td->hwINFO); + tdBE = m32_swap (td->hwBE); + tdCBP = m32_swap (td->hwCBP); + + + if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + lurb_priv->actual_length += tdBE - td->data + 1; + else + lurb_priv->actual_length += tdCBP - td->data; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t *ohci) +{ + __u32 td_list_hc; + td_t *td_rev = NULL; + td_t *td_list = NULL; + urb_priv_t *lurb_priv = NULL; + + td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = (td_t *)td_list_hc; + + if (TD_CC_GET (m32_swap (td_list->hwINFO))) { + lurb_priv = &urb_priv; + dbg(" USB-error/status: %x : %p", + TD_CC_GET (m32_swap (td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & m32_swap (0x1)) { + if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { + td_list->ed->hwHeadP = + (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) | + (td_list->ed->hwHeadP & m32_swap (0x2)); + lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= m32_swap (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; + } + + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* td done list */ +static int dl_done_list (ohci_t *ohci, td_t *td_list) +{ + td_t *td_list_next = NULL; + ed_t *ed; + int cc = 0; + int stat = 0; + /* urb_t *urb; */ + urb_priv_t *lurb_priv; + __u32 tdINFO, edHeadP, edTailP; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + lurb_priv = &urb_priv; + tdINFO = m32_swap (td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length(td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (cc != 0) { + dbg("ConditionCode %#x", cc); + stat = cc_to_error[cc]; + } + + /* see if this done list makes for all TD's of current URB, + * and mark the URB finished if so */ + if (++(lurb_priv->td_cnt) == lurb_priv->length) { + if ((ed->state & (ED_OPER | ED_UNLINK))) + urb_finished = 1; + else + dbg("dl_done_list: strange.., ED state %x, ed->state\n"); + } else + dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt, + lurb_priv->length); + + if (ed->state != ED_NEW) { + edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; + edTailP = m32_swap (ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + + td_list = td_list_next; + } + return stat; +} + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'O', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#ifdef DEBUG +#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#else +#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#endif +#define RD_RH_STAT roothub_status(&gohci) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) + +/* request to virtual root hub */ + +int rh_check_port_status(ohci_t *controller) +{ + __u32 temp, ndp, i; + int res; + + res = -1; + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + /* check for a device disconnect */ + if (((temp & (RH_PS_PESC | RH_PS_CSC)) == + (RH_PS_PESC | RH_PS_CSC)) && + ((temp & RH_PS_CCS) == 0)) { + res = i; + break; + } + } + return res; +} + +static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *cmd) +{ + void * data = buffer; + int leni = transfer_len; + int len = 0; + int stat = 0; + __u32 datab[4]; + __u8 *data_buf = (__u8 *)datab; + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + +#ifdef DEBUG +urb_priv.actual_length = 0; +pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + info("Root-Hub submit IRQ: NOT implemented"); + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = m16_swap (cmd->value); + wIndex = m16_swap (cmd->index); + wLength = m16_swap (cmd->length); + + info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", + dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = m16_swap (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = m32_swap ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); + } + break; + + case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if(wValue==0x0300) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); + } + if(wValue==0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); + } + default: + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a (&gohci); + + data_buf [0] = 9; /* min length; */ + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + /* corresponds to data_buf[4-7] */ + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (&gohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); + } + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + dbg ("unsupported root hub command"); + stat = USB_ST_STALLED; + } + +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#else + wait_ms(1); +#endif + + len = min_t(int, len, leni); + if (data != data_buf) + memcpy (data, data_buf, len); + dev->act_len = len; + dev->status = stat; + +#ifdef DEBUG + if (transfer_len) + urb_priv.actual_length = transfer_len; + pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); +#else + wait_ms(1); +#endif + + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/* common code for handling submit messages - used for all but root hub */ +/* accesses. */ +int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + int stat = 0; + int maxsize = usb_maxpacket(dev, pipe); + int timeout; + + /* device pulled? Shortcut the action. */ + if (devgone == dev) { + dev->status = USB_ST_CRC_ERR; + return 0; + } + +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_common_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + + if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { + err("sohci_submit_job failed"); + return -1; + } + + wait_ms(10); + /* ohci_dump_status(&gohci); */ + + /* allow more time for a BULK device to react - some are slow */ +#define BULK_TO 5000 /* timeout in milliseconds */ + if (usb_pipetype (pipe) == PIPE_BULK) + timeout = BULK_TO; + else + timeout = 100; + + /* wait for it to complete */ + for (;;) { + /* check whether the controller is done */ + stat = hc_interrupt(); + + if (stat < 0) { + stat = USB_ST_CRC_ERR; + break; + } + + /* NOTE: since we are not interrupt driven in U-Boot and always + * handle only one URB at a time, we cannot assume the + * transaction finished on the first successful return from + * hc_interrupt().. unless the flag for current URB is set, + * meaning that all TD's to/from device got actually + * transferred and processed. If the current URB is not + * finished we need to re-iterate this loop so as + * hc_interrupt() gets called again as there needs to be some + * more TD's to process still */ + if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { + /* 0xff is returned for an SF-interrupt */ + break; + } + + if (--timeout) { + wait_ms(1); + if (!urb_finished) + dbg("\%"); + + } else { + err("CTL:TIMEOUT "); + dbg("submit_common_msg: TO status %x\n", stat); + stat = USB_ST_CRC_ERR; + urb_finished = 1; + break; + } + } + +#if 0 + /* we got an Root Hub Status Change interrupt */ + if (got_rhsc) { +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#endif + got_rhsc = 0; + /* abuse timeout */ + timeout = rh_check_port_status(&gohci); + if (timeout >= 0) { +#if 0 /* this does nothing useful, but leave it here in case that changes */ + /* the called routine adds 1 to the passed value */ + usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); +#endif + /* + * XXX + * This is potentially dangerous because it assumes + * that only one device is ever plugged in! + */ + devgone = dev; + } + } +#endif + + dev->status = stat; + dev->act_len = transfer_len; + +#ifdef DEBUG + pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + + /* free TDs in urb_priv */ + urb_free_priv (&urb_priv); + return 0; +} + +/* submit routines called from usb.c */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + info("submit_bulk_msg"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + int maxsize = usb_maxpacket(dev, pipe); + + info("submit_control_msg"); +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_control_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { + gohci.rh.dev = dev; + /* root hub - redirect */ + return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, + setup); + } + + return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg"); + return -1; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (ohci_t *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + info("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", + ohci->slot_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); + + /* HC Reset requires max 10 us delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + __u32 mask; + unsigned int fminterval; + + ohci->disabled = 1; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* disable all interrupts */ + mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | + OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | + OHCI_INTR_OC | OHCI_INTR_MIE); + writel (mask, &ohci->regs->intrdisable); + /* clear all interrupts */ + mask &= ~OHCI_INTR_MIE; + writel (mask, &ohci->regs->intrstatus); + /* Choose the interrupts we care about now - but w/o MIE */ + mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrenable); + +#ifdef OHCI_USE_NPS + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + +#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) + /* POTPGT delay is bits 24-31, in 2 ms units. */ + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->rh.devnum = 0; + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static int +hc_interrupt (void) +{ + ohci_t *ohci = &gohci; + struct ohci_regs *regs = ohci->regs; + int ints; + int stat = -1; + + if ((ohci->hcca->done_head != 0) && + !(m32_swap (ohci->hcca->done_head) & 0x01)) { + + ints = OHCI_INTR_WDH; + + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { + ohci->disabled++; + err ("%s device removed!", ohci->slot_name); + return -1; + + } else if ((ints &= readl (®s->intrenable)) == 0) { + dbg("hc_interrupt: returning..\n"); + return 0xff; + } + + /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + + if (ints & OHCI_INTR_RHSC) { + got_rhsc = 1; + stat = 0xff; + } + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->slot_name); + /* e.g. due to PCI Master/Target Abort */ + +#ifdef DEBUG + ohci_dump (ohci, 1); +#else + wait_ms(1); +#endif + /* FIXME: be optimistic, hope that bug won't repeat often. */ + /* Make some non-interrupt context restart the controller. */ + /* Count and limit the retries though; either hardware or */ + /* software errors can go forever... */ + hc_reset (ohci); + return -1; + } + + if (ints & OHCI_INTR_WDH) { + wait_ms(1); + + writel (OHCI_INTR_WDH, ®s->intrdisable); + stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun\n"); + writel (OHCI_INTR_SO, ®s->intrenable); + stat = -1; + } + + /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ + if (ints & OHCI_INTR_SF) { + unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1; + wait_ms(1); + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list[frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); + stat = 0xff; + } + + writel (ints, ®s->intrstatus); + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t *ohci) +{ + dbg ("USB HC release ohci usb-%s", ohci->slot_name); + + if (!ohci->disabled) + hc_reset (ohci); +} + +/*-------------------------------------------------------------------------*/ + +/* + * low level initalisation routine, called from usb.c + */ +static char ohci_inited = 0; + +int usb_lowlevel_init(void) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); + + /* + * Set the 48 MHz UPLL clocking. Values are taken from + * "PLL value selection guide", 6-23, s3c2400_UM.pdf. + */ + clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2); + gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */ + + /* + * Enable USB host clock. + */ + clk_power->CLKCON |= (1 << 4); + + memset (&gohci, 0, sizeof (ohci_t)); + memset (&urb_priv, 0, sizeof (urb_priv_t)); + + /* align the storage */ + if ((__u32)&ghcca[0] & 0xff) { + err("HCCA not aligned!!"); + return -1; + } + phcca = &ghcca[0]; + info("aligned ghcca %p", phcca); + memset(&ohci_dev, 0, sizeof(struct ohci_device)); + if ((__u32)&ohci_dev.ed[0] & 0x7) { + err("EDs not aligned!!"); + return -1; + } + memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); + if ((__u32)gtd & 0x7) { + err("TDs not aligned!!"); + return -1; + } + ptd = gtd; + gohci.hcca = phcca; + memset (phcca, 0, sizeof (struct ohci_hcca)); + + gohci.disabled = 1; + gohci.sleeping = 0; + gohci.irq = -1; + gohci.regs = (struct ohci_regs *)S3C24X0_USB_HOST_BASE; + + gohci.flags = 0; + gohci.slot_name = "s3c2400"; + + if (hc_reset (&gohci) < 0) { + hc_release_ohci (&gohci); + /* Initialization failed */ + clk_power->CLKCON &= ~(1 << 4); + return -1; + } + + /* FIXME this is a second HC reset; why?? */ + writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); + wait_ms (10); + + if (hc_start (&gohci) < 0) { + err ("can't start usb-%s", gohci.slot_name); + hc_release_ohci (&gohci); + /* Initialization failed */ + clk_power->CLKCON &= ~(1 << 4); + return -1; + } + +#ifdef DEBUG + ohci_dump (&gohci, 1); +#else + wait_ms(1); +#endif + ohci_inited = 1; + urb_finished = 1; + + return 0; +} + +int usb_lowlevel_stop(void) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + + /* this gets called really early - before the controller has */ + /* even been initialized! */ + if (!ohci_inited) + return 0; + /* TODO release any interrupts, etc. */ + /* call hc_release_ohci() here ? */ + hc_reset (&gohci); + /* may not want to do this */ + clk_power->CLKCON &= ~(1 << 4); + return 0; +} + +#endif /* CONFIG_USB_OHCI */ diff --git a/cpu/arm920t/s3c24x0/usb_ohci.h b/cpu/arm920t/s3c24x0/usb_ohci.h new file mode 100755 index 0000000..5e9a0fd --- /dev/null +++ b/cpu/arm920t/s3c24x0/usb_ohci.h @@ -0,0 +1,417 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> + * + * usb-ohci.h + */ + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ + /* No Error */ 0, + /* CRC Error */ USB_ST_CRC_ERR, + /* Bit Stuff */ USB_ST_BIT_ERR, + /* Data Togg */ USB_ST_CRC_ERR, + /* Stall */ USB_ST_STALLED, + /* DevNotResp */ -1, + /* PIDCheck */ USB_ST_BIT_ERR, + /* UnExpPID */ USB_ST_BIT_ERR, + /* DataOver */ USB_ST_BUF_ERR, + /* DataUnder */ USB_ST_BUF_ERR, + /* reservd */ -1, + /* reservd */ -1, + /* BufferOver */ USB_ST_BUF_ERR, + /* BuffUnder */ USB_ST_BUF_ERR, + /* Not Access */ -1, + /* Not Access */ -1 +}; + +/* ED States */ +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed *ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed *ed_rm_list; + + struct usb_device *usb_dev; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct usb_device *usb_dev; + int transfer_len; + __u32 data; + + __u32 unused2[2]; +} __attribute((aligned(32))); +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *dev; /* was urb */ + void *int_addr; + int send; + int interval; +}; + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +#define N_URB_TD 48 +typedef struct +{ + ed_t *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + int state; + unsigned long pipe; + int actual_length; + td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t *ed_bulktail; /* last endpoint of bulk list */ + ed_t *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_device *dev[32]; + struct virt_root_hub rh; + + const char *slot_name; +} ohci_t; + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; +}; + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); + +/*-------------------------------------------------------------------------*/ + +/* we need more TDs than EDs */ +#define NUM_TD 64 + +/* +1 so we can align the storage */ +td_t gtd[NUM_TD+1]; +/* pointers to aligned storage */ +td_t *ptd; + +/* TDs ... */ +static inline struct td * +td_alloc (struct usb_device *usb_dev) +{ + int i; + struct td *td; + + td = NULL; + for (i = 0; i < NUM_TD; i++) + { + if (ptd[i].usb_dev == NULL) + { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + + return td; +} + +static inline void +ed_free (struct ed *ed) +{ + ed->usb_dev = NULL; +} diff --git a/cpu/arm920t/start.S b/cpu/arm920t/start.S new file mode 100755 index 0000000..b082fae --- /dev/null +++ b/cpu/arm920t/start.S @@ -0,0 +1,528 @@ +/* + * armboot - Startup Code for ARM920 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +#include <config.h> +#include <version.h> + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * These are defined in the board-specific linker script. + */ +.globl _bss_start +_bss_start: + .word __bss_start + +.globl _bss_end +_bss_end: + .word _end + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + +/* turn off the watchdog */ +#if defined(CONFIG_S3C2400) +# define pWTCON 0x15300000 +# define INTMSK 0x14400008 /* Interupt-Controller base addresses */ +# define CLKDIVN 0x14800014 /* clock divisor register */ +#elif defined(CONFIG_S3C2410) +# define pWTCON 0x53000000 +# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ +# define INTSUBMSK 0x4A00001C +# define CLKDIVN 0x4C000014 /* clock divisor register */ +#endif + +#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) + ldr r0, =pWTCON + mov r1, #0x0 + str r1, [r0] + + /* + * mask all IRQs by setting all bits in the INTMR - default + */ + mov r1, #0xffffffff + ldr r0, =INTMSK + str r1, [r0] +# if defined(CONFIG_S3C2410) + ldr r1, =0x3ff + ldr r0, =INTSUBMSK + str r1, [r0] +# endif + + /* FCLK:HCLK:PCLK = 1:2:4 */ + /* default FCLK is 120 MHz ! */ + ldr r0, =CLKDIVN + mov r1, #3 + str r1, [r0] +#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */ + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate: /* relocate U-Boot to RAM */ + adr r0, _start /* r0 <- current position of code */ + ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ + cmp r0, r1 /* don't reloc during debug */ + beq stack_setup + + ldr r2, _armboot_start + ldr r3, _bss_start + sub r2, r3, r2 /* r2 <- size of armboot */ + add r2, r0, r2 /* r2 <- source end address */ + +copy_loop: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end addreee [r2] */ + ble copy_loop +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + + /* Set up the stack */ +stack_setup: + ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ + sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ + sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ +#ifdef CONFIG_USE_IRQ + sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) +#endif + sub sp, r0, #12 /* leave 3 words for abort-stack */ + +clear_bss: + ldr r0, _bss_start /* find start of bss segment */ + ldr r1, _bss_end /* stop here */ + mov r2, #0x00000000 /* clear */ + +clbss_l:str r2, [r0] /* clear loop... */ + add r0, r0, #4 + cmp r0, r1 + ble clbss_l + +#if 0 + /* try doing this stuff after the relocation */ + ldr r0, =pWTCON + mov r1, #0x0 + str r1, [r0] + + /* + * mask all IRQs by setting all bits in the INTMR - default + */ + mov r1, #0xffffffff + ldr r0, =INTMR + str r1, [r0] + + /* FCLK:HCLK:PCLK = 1:2:4 */ + /* default FCLK is 120 MHz ! */ + ldr r0, =CLKDIVN + mov r1, #3 + str r1, [r0] + /* END stuff after relocation */ +#endif + + ldr pc, _start_armboot + +_start_armboot: .word start_armboot + + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +cpu_init_crit: + + /* + * Invalidate L1 I/D + */ + mov r0, #0 @ set up for MCR + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + +#if defined (CONFIG_WMT) + bic r0, r0, #0x00000300 @ clear bits 9:8 (---- --RS) + bic r0, r0, #0x0000000F @ clear bits 3:0 (---- WCAM) + orr r0, r0, #0x00002000 @ set bit 13 (--V--) +#else + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) +#endif + orr r0, r0, #0x00000002 @ set bit 2 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + bl lowlevel_init + mov lr, ip + mov pc, lr + + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + ldr r2, _armboot_start + sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) + sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack + ldmia r2, {r2 - r3} @ get pc, cpsr + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, _armboot_start @ setup our mode stack + sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) + sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + + + + + +//#if 0 +.global memset_32Byte +memset_32Byte: + stmfd sp!,{r3-r12,lr} + + add r7,r0,r2 + + ands r4,r0,#0x1f + beq set_loop_ +for_align: subs r4,r4,#1 //r4-1 + blt set_loop_ + strb r1,[r0],#1 + b for_align + +set_loop_: +#if 0 + and r4,r1,r1, lsl #8 + and r5,r4,r4, lsl #16 + mov r4,r5 +#endif + mov r4,r1 + add r4,r4,r1,lsl #8 + add r4,r4,r1,lsl #16 + add r4,r4,r1,lsl #24 + + mov r5,r4 + mov r8,r4 + mov r9,r4 + mov r10,r4 + mov r11,r4 + mov r12,r4 + mov r3,r4 + + and r6,r7,#0xffffffe0 + +main_loop: cmp r0,r6 + beq last_loop + stmia r0!,{r3,r4,r5,r8,r9,r10,r11,r12} + //strd r4,r5,[r0],#8 + b main_loop + +last_loop: cmp r0,r7 + beq memset_quit + strb r1,[r0],#1 + b last_loop +memset_quit: + ldmfd sp!,{r3-r12,pc} + + + + + +.global memcpy_32Byte +memcpy_32Byte: + stmfd sp!,{r3-r12,lr} + + add r7,r1,r2 //r7 src_end addr +//#if 0 + ands r4,r0,#0x1f + bne byte_cpy + ands r5,r1,#0x1f + bne byte_cpy + + add r6,r7,#0xffffffe0 //r6 src_aligned_end addr +dword_cpy: cmp r1,r6 + beq byte_cpy + //ldrd r4,r5,[r1],#8 + //strd r4,r5,[r0],#8 + ldmia r1!,{r3,r4,r5,r8,r9,r10,r11,r12} + stmia r0!,{r3,r4,r5,r8,r9,r10,r11,r12} + b dword_cpy +//#endif + +byte_cpy: cmp r1,r7 + beq cpy_quit + ldrb r4,[r1],#1 + strb r4,[r0],#1 + b byte_cpy +cpy_quit: + ldmfd sp!,{r3-r12,pc} + + +//#endif
\ No newline at end of file diff --git a/cpu/arm920t/wmt/Makefile b/cpu/arm920t/wmt/Makefile new file mode 100755 index 0000000..a3e420e --- /dev/null +++ b/cpu/arm920t/wmt/Makefile @@ -0,0 +1,72 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# Some descriptions of such software. Copyright (c) 2008 WonderMedia Technologies, Inc. +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software Foundation, +# either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +# +# WonderMedia Technologies, Inc. +# 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = interrupts.o \ + serial.o \ + zde.o \ + upcix.o \ + pcinet.o \ + tconvert.o \ + mem.o \ + tcrc.o \ + vpci.o \ + dma.o \ + api-loader.o \ + cypher.o \ + cypherif.o \ + mmc.o +#ether.o \ +#mac.o \ +#macif.o \ +#adapter.o \ +#alloct.o \ +#mii.o \ +#macif.o \ +#gmacif.o \ +#gmii.o \ +#gcard.o \ +#gmib.o \ +#gisr.o \ +#galloct.o \ +#gmac.o \ +#gadapter.o \ +#proto.o \ +#proco.o \ + +all: .depend $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/wmt/adapter.c b/cpu/arm920t/wmt/adapter.c new file mode 100755 index 0000000..7c1a322 --- /dev/null +++ b/cpu/arm920t/wmt/adapter.c @@ -0,0 +1,503 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +/* modified by kevin */ +/*#ifndef _GLOBAL_H_ +#include "global.h" +#endif +#ifndef _EXTVARS_H_ +#include "extvars.h" +#endif*/ + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__EMACISR_H__) +/* #include "emacisr.h" */ +#endif +#if !defined(__ALLOCT_H__) +#include "alloct.h" +#endif +#if !defined(__VPCI_H__) +#include "vpci.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif +#include "macif.h" +#if !defined(__DBG_H__) +#include "dbg.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +static void s_vInit(PSAdapterInfo pAdapter, UINT uTotalNum, UINT uIdx); + +/*--------------------- Export Variables --------------------------*/ +PSAdapterInfo sg_aAdapter; +SAdapterOpts g_sOptions = {0, 0, 0, 0, 0, 0}; + +/*--------------------- Export Functions --------------------------*/ +BOOL +ADPbBind( + PSAdapterInfo pAdapter + ) +{ + /* build RDR/TDR */ + if (!ALCbAllocateRdrMemory(pAdapter)) { + printf("allocate Buffer or RD fail!\n"); + return FALSE; + } + if (!ALCbAllocateTdrMemory(pAdapter)) { + printf("allocate Buffer or TD fail!\n"); + return FALSE; + } + + ALCvChainRdrMemory(pAdapter); + ALCvChainTdrMemory(pAdapter); + /* Mac init & mii init */ + if (!ADPbInitializeEx(pAdapter)) { + printf("init ex fail\n"); + return FALSE; + } + /* Hook Interrupt Service Routine on IRQ */ + /* set_irq_handlers(pAdapter->byIrqLevel, pAdapter->pvAdapterIsr); */ + + /* Enable Interrupt Mask */ + /* unmask_interrupt(pAdapter->byIrqLevel); */ + + /* MacDump(MACDBG_INFO, ("[ADPbBind] - Hook ISR on IRQ%d\n", pAdapter->byIrqLevel)); */ + + /* Start ISR */ + MACvIntEnable(pAdapter->dwIoBase, pAdapter->byRevId, IMR_MASK_VALUE); + + /* Wait MAUTO to poll twice, then MIISR_LNKFL will be correct status */ + /* kevin???? */ + PCAvDelayByIO(CB_DELAY_MII_STABLE * 20000); + /* Update link status */ + pAdapter->bLinkPass = MACbIsCableLinkOk(pAdapter->dwIoBase); + if (pAdapter->bLinkPass) { + MacDump(MACDBG_INFO, ("[ADPbBind]- Link Pass\n")); + + /* update duplex status */ + /* NOTE.... here we don't call MIIbIsInFullDuplexMode(), because */ + /* we won't turn on/off MAUTO */ + MACvIsInFullDuplexMode(&pAdapter->bFullDuplex, pAdapter->dwIoBase); + /* Update speed status */ + pAdapter->bSpeed100M = MACbIsIn100MMode(pAdapter->dwIoBase, pAdapter->byRevId); + } else + MacDump(MACDBG_INFO, ("[ADPbBind]- Fail\n")); + + pAdapter->pbyTmpBuff = (PBYTE)mALLOc(CB_MAX_BUF_SIZE); + MacDump(MACDBG_INFO, ("[ADPbBind]- Exit!\n")); + + return TRUE; +} + +static BOOL ADPbDynaAllocBuf( + PSAdapterInfo pAdapter + ) +{ + /* Allocate RD/TD pointer array & DescBuf SAllocMap array. */ + /* modified by kevin:mALLOc supplied by u-boot */ + pAdapter->apRD = (PSRxDesc *)mALLOc(sizeof(PSRxDesc) * pAdapter->cbRD); + MacDump(MACDBG_INFO, ("[ADPbDynaAllocBuf] - pAdapter->apRD : %p, size : %d\n", pAdapter->apRD, + sizeof(PSRxDesc)*pAdapter->cbRD)); + pAdapter->aamRxDescBuf = (PSAllocMap)mALLOc(sizeof(SAllocMap) * pAdapter->cbRD); + MacDump(MACDBG_INFO, ("[ADPbDynaAllocBuf] - pAdapter->aamRxDescBuf : %p, size : %d\n", + pAdapter->aamRxDescBuf, sizeof(SAllocMap) * pAdapter->cbRD)); + + pAdapter->apTD = (PSTxDesc *)mALLOc(sizeof(PSTxDesc) * pAdapter->cbTD); + MacDump(MACDBG_INFO, ("[ADPbDynaAllocBuf] - pAdapter->apTD : %p, size : %d\n", pAdapter->apTD, + sizeof(PSTxDesc)*pAdapter->cbTD)); + pAdapter->aamTxDescBuf = (PSAllocMap)mALLOc(sizeof(SAllocMap) * pAdapter->cbTD); + MacDump(MACDBG_INFO, ("[ADPbDynaAllocBuf] - pAdapter->aamTxDescBuf : %p, size : %d\n", + pAdapter->aamTxDescBuf, sizeof(SAllocMap) * pAdapter->cbTD)); + + if ((pAdapter->apRD == NULL) || (pAdapter->apTD == NULL) || + (pAdapter->aamTxDescBuf == NULL) || (pAdapter->aamRxDescBuf == NULL)) + return FALSE; + + return TRUE; +} + +BOOL +ADPbInitializeEx( + PSAdapterInfo pAdapter + ) +{ + BYTE byOrgData, byPMRegOffset; + + /* Fill default value */ + /* marked by kevin:repeat again */ + /* ALCvSetDefaultRD(pAdapter); */ + /* ALCvSetDefaultTD(pAdapter); */ + + /* Init PCI */ + VPCIvInitialize(pAdapter->dwIoBase, pAdapter->byRevId); + + /* Write-clear PME status bit */ + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_CAP, &byPMRegOffset); + VPCIvReadB(pAdapter->dwIoBase, (BYTE)(byPMRegOffset + PM_PMCSR1), &byOrgData); + VPCIvWriteB(pAdapter->dwIoBase, (BYTE)(byPMRegOffset + PM_PMCSR1), + (BYTE)(PMCSR1_PME_STATUS | byOrgData)); + + if (!g_sOptions.bNoInit) { + /* Init MAC */ + MACvInitialize(pAdapter->dwIoBase, pAdapter->byRevId); + + /* PATCH.... */ + /* PCI speed is too slow on some mainboard will cause */ + /* tx fifo underflow, so set tx threshold to SF */ + /* set tx threshold, SF */ + /* Masked by Ray for WMT */ + /* MACvSetTxThreshold(pAdapter->dwIoBase, 7); */ + + /* Set address filter to accept any packet */ + /* MACvSetPacketFilter(pAdapter->dwIoBase, PKT_TYPE_PROMISCUOUS); */ + + /* Detect PHY is from which company */ + MIIvReadPhyCmrId(pAdapter->dwIoBase, pAdapter->byRevId, &pAdapter->dwPhyCmrId); + /* Init MII */ + MIIvInitialize(pAdapter->dwIoBase, pAdapter->byRevId, pAdapter->dwPhyCmrId); + + CARDvSetLoopbackMode(pAdapter->dwIoBase, pAdapter->byRevId, CARD_LB_NONE); + /* set mii NWAY or AUTO */ + CARDvSetMediaLinkMode(pAdapter->dwIoBase, pAdapter->byRevId, pAdapter->uConnectionType); + + if (pAdapter->uConnectionType == MEDIA_AUTO) { + /* Restart AUTO-NEGO to make sure AUTO-NEGO is correct */ + /* Modified by Ray, Not sure if this instruction is wrong. */ + /* MIIvSetResetOn(pAdapter->dwIoBase, pAdapter->byRevId); */ + MIIvSetReAuto(pAdapter->dwIoBase, pAdapter->byRevId); + } + + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_FLOWCR0, (BYTE)pAdapter->cbRD); + + } + + /* Set init rx/tx descriptor address into chip */ + MACvSetCurrRxDescAddr(pAdapter->dwIoBase, pAdapter->amRxDescRing.dwPAddr); + MACvSetCurrTxDescAddr(pAdapter->dwIoBase, pAdapter->amTxDescRing.dwPAddr); + + /* Set current rx/tx descriptor index to 0 */ + pAdapter->idxRxCurDesc = 0; + pAdapter->idxTxCurDesc = 0; + /* added by kevin for checking serviced TD RD status */ + pAdapter->idxRxdirtyDesc = 0; + pAdapter->idxTxdirtyDesc = 0; + pAdapter->idxRxPktStartDesc = 0; + + return TRUE; +} + +BOOL +ADPbShutdown( + PSAdapterInfo pAdapter + ) +{ + /* Stop chip */ + if (!MACbSafeStop(pAdapter->dwIoBase, pAdapter->byRevId)) + return FALSE; + + /* Stop ISR */ + MACvIntDisable(pAdapter->dwIoBase, pAdapter->byRevId); + + /* Take off Interrupt Service Routine */ + /* unset_irq_handlers(pAdapter->byIrqLevel); */ + + /* Disable Interrupt */ + /* mask_interrupt(pAdapter->byIrqLevel); */ + + MacDump(MACDBG_INFO, ("[ADPbShutdown] - Take off ISR on IRQ%d\n", pAdapter->byIrqLevel)); + + /* Destroy RDR/TDR */ + /* ALCvFreeRdrMemory(pAdapter); */ + /* ALCvFreeTdrMemory(pAdapter); */ + + if (pAdapter->pbyTmpBuff != NULL) + pAdapter->pbyTmpBuff = NULL; + + return TRUE; +} + +UINT +ADPuInitAll( + void + ) +{ + int ii; + UINT uTotalDev = 0; + + /* modified by kevin:mALLOc supplied by u-boot */ + if (!g_bInit) { + sg_aAdapter = (PSAdapterInfo)mALLOc(sizeof(SAdapterInfo) * CB_MAX_NET_DEVICE); + + if (sg_aAdapter != NULL) { + /* modifiey by kevin:memset supplied by u-boot */ + memset(sg_aAdapter, 0, sizeof(SAdapterInfo) * CB_MAX_NET_DEVICE); + } else { + return 0; + } + } + + for (ii = 0; ii < CB_MAX_NET_DEVICE; ii++) { + s_vInit(&sg_aAdapter[ii], CB_MAX_NET_DEVICE, ii); + + if ((&sg_aAdapter[ii])->wDevId == W_DEVICE_ID_3106A || + (&sg_aAdapter[ii])->wDevId == W_DEVICE_ID_3053A) + uTotalDev++; + } + + return uTotalDev; +} + +VOID +CARDvSetLoopbackMode( + DWORD dwIoBase, + BYTE byRevId, + WORD wLoopbackMode + ) +{ + switch (wLoopbackMode) { + case CARD_LB_NONE: + case CARD_LB_MAC: + case CARD_LB_MII: + break; + default: + /* DBG_ASSERT(FALSE); */ + break; + } + + /* set MAC loopback */ + MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode)); + /* set MII loopback */ + MIIvSetLoopbackMode(dwIoBase, byRevId, HIBYTE(wLoopbackMode)); +} + +VOID +CARDvSetMediaLinkMode( + DWORD dwIoBase, + BYTE byRevId, + UINT uConnectionType + ) +{ + DWORD dwData; + + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_PHYID2, (PWORD)&dwData); + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_PHYID1, (PWORD)&dwData + 1); + + /* If connection type is AUTO */ + if (uConnectionType == MEDIA_AUTO) { + /* Set duplex mode of MAC according to duplex mode of MII */ + if (MIIbIsInFullDuplexMode(dwIoBase, byRevId)) + MACvSetDuplexMode(dwIoBase, byRevId, TRUE); + else + MACvSetDuplexMode(dwIoBase, byRevId, FALSE); + + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); + /* not force */ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_MODCFG, 1); + + /* enable AUTO-NEGO mode */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + } else { + /* If not, then */ + /* 1). Turn off AUTO-NEGO */ + /* 2). Set USER-FORCED speed (10/100) & duplex (half/full) mode of MII and MAC */ + + /* For 3065/3106, Nway-force */ + WORD wANAR; + + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_ANAR, &wANAR); + + wANAR &= (~(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)); + + switch (uConnectionType) { + case MEDIA_100M_FULL: + wANAR |= ANAR_TXFD; + MACvSetDuplexMode(dwIoBase, byRevId, TRUE); + break; + + case MEDIA_100M_HALF: + wANAR |= ANAR_TX; + MACvSetDuplexMode(dwIoBase, byRevId, FALSE); + break; + + case MEDIA_10M_FULL: + wANAR |= ANAR_10FD; + MACvSetDuplexMode(dwIoBase, byRevId, TRUE); + break; + + case MEDIA_10M_HALF: + wANAR |= ANAR_10; + MACvSetDuplexMode(dwIoBase, byRevId, FALSE); + break; + + default: + break; + } + + MIIbWriteEmbedded(dwIoBase, byRevId, MII_REG_ANAR, wANAR); + /* force */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_MODCFG, 1); + + /* Enable AUTO-NEGO mode */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + } +} + +static void s_vInit( + PSAdapterInfo pAdapter, + UINT uTotalNum, + UINT uIdx + ) +{ + int ii; + unsigned char check; + + pAdapter->cbTotalAdapterNum = uTotalNum; + pAdapter->uAdapterIndex = uIdx; + + /* Save Memory Mapped IO base address */ + switch (uIdx) { + case 0: + pAdapter->dwIoBase = BA_MAC0; + break; + + case 1: + pAdapter->dwIoBase = BA_MAC1; + break; + + default: + break; + } + MacDump(MACDBG_INFO, ("Memory mapped IO base address:%08X\n", pAdapter->dwIoBase)); + + /* check vee oe pee */ + VNSvInPortB(pAdapter->dwIoBase+0x77, &check); + if (check & 0x40){ + /* Issue AUTOLD in EECSR to reload eeprom to ensure right data from eeprom */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_EECSR, EECSR_AUTOLD); + /* set VEELD */ + VNSvOutPortB(pAdapter->dwIoBase+PCI_Configuration_Space_Offset+VMSTS, 0x1); + /* wait until VEELD is set */ + ii = 0; + while (1) { + VNSvInPortB(pAdapter->dwIoBase+PCI_Configuration_Space_Offset+VMSTS, &check); + if (check&0x2 || ii == MaxTimeOut) + break; + ii++; + } + /* clear VEELD */ + VNSvOutPortB(pAdapter->dwIoBase+PCI_Configuration_Space_Offset+VMSTS, 0x0); + } else { + /* Issue AUTOLD in EECSR to reload eeprom to ensure right data from eeprom */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_EECSR, EECSR_AUTOLD); + /* Wait until EEPROM loading complete */ + while (TRUE) { + BYTE byData; + VNSvInPortB(pAdapter->dwIoBase + MAC_REG_EECSR, &byData); + if (BITbIsBitOff(byData, EECSR_AUTOLD)) + break; + } + } + + /* Get Device ID from PCI configuration space */ + VPCIvReadW(pAdapter->dwIoBase, PCI_REG_DEVICE_ID, &pAdapter->wDevId); + MacDump(MACDBG_INFO, ("Device ID:%04X\n", pAdapter->wDevId)); + + if (pAdapter->wDevId != W_DEVICE_ID_3106A && pAdapter->wDevId != W_DEVICE_ID_3053A) + return; + + /* Get Revision ID from PCI configuration */ + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_REV_ID, &pAdapter->byRevId); + MacDump(MACDBG_INFO, ("Revision ID:%02X\n", pAdapter->byRevId)); + + /* Clear sticky bits */ + if (g_sOptions.ulInitCmds & INIT_CMD_CLEAR_STICKHW) + MACvClearStckDS(pAdapter->dwIoBase); + + if (g_sOptions.byRevId != 0) + pAdapter->byRevId = g_sOptions.byRevId; + + /* Set RD,TD number for this adapter now */ + /* For 3065, 3106J, 3206 */ + pAdapter->cbRD = (g_sOptions.iRDescNum) ? g_sOptions.iRDescNum : CB_INIT_RD_NUM; + pAdapter->cbTD = (g_sOptions.iTDescNum) ? g_sOptions.iTDescNum : CB_INIT_TD_NUM; + + /* Save IRQ number */ + switch (uIdx) { + case 0: + pAdapter->byIrqLevel = IRQ_ETH0; + /* pAdapter->pvAdapterIsr = ISRvIsrForMAC0; */ + break; + + case 1: + pAdapter->byIrqLevel = IRQ_ETH1; + /* pAdapter->pvAdapterIsr = ISRvIsrForMAC1; */ + break; + + default: + break; + } + + g_sOptions.uiBuffsize = (g_sOptions.uiBuffsize) ? g_sOptions.uiBuffsize : CB_MAX_BUF_SIZE; + + /* Get the offset of PM Capability and save it from pci configuration space */ + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_CAP, &pAdapter->byPMRegOffset); + + /* Get PHY address */ + pAdapter->byPhyId = MACbyGetPhyId(pAdapter->dwIoBase); + MacDump(MACDBG_INFO, ("PHY Address:%02X\n", pAdapter->byPhyId)); + + /* Get Ethernet address */ + for (ii = 0; ii < U_ETHER_ADDR_LEN; ii++) + VNSvInPortB(pAdapter->dwIoBase + MAC_REG_PAR, pAdapter->abyEtherAddr + ii); + + /* Allocate RD/TD poiter array & DescBuf array data structure */ + if (!g_bInit) { + if (!ADPbDynaAllocBuf(pAdapter)) { + printf("ADPbDynaAllocBuf() can't allocate buffer.\n"); + return; + } + } + + pAdapter->dwCacheLineSize = sizeof(DWORD) * 4; + + /* Set default value of connection type to MEDIA_AUTO */ + pAdapter->uConnectionType = MEDIA_AUTO; + + /* Init default descriptor number per packet in monitor mode */ + pAdapter->uTxDescNumPerPacket = 1; + + /* Background timer send as default */ + pAdapter->bTxContFunTest = TRUE; +} diff --git a/cpu/arm920t/wmt/adapter.h b/cpu/arm920t/wmt/adapter.h new file mode 100755 index 0000000..8d4a8d8 --- /dev/null +++ b/cpu/arm920t/wmt/adapter.h @@ -0,0 +1,201 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __ADAPTER_H__ +#define __ADAPTER_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__MIB_H__) +#include "mib.h" +#endif + +#include <malloc.h> + +#if !defined(__DESC_H__) +#include "desc.h" +#endif +#if !defined(__MEM_H__) +#include "mem.h" +#endif +#include <common.h> +#include "tbit.h" +/*--------------------- Export Definitions -------------------------*/ +// +// constants +// +#define W_DEVICE_ID_3106A 0x3106 // device ID for 3106A +#define W_DEVICE_ID_3053A 0x3053 + +// +// Adapter Information +// +typedef struct tagSAdapterInfo { + + UINT cbTotalAdapterNum; + UINT uAdapterIndex; // device index + + // got from PCI regs + WORD wDevId; // The Device ID of this adapter + BYTE byRevId; // The Revision Number of this adapter + DWORD dwIoBase; + BYTE byPMRegOffset; // the content of Cap_Ptr + + // got from MAC regs (loaded from EEPROM) + BYTE byPhyId; + BYTE abyEtherAddr[U_ETHER_ADDR_LEN]; + + // got from MII regs (updated by Link-Change) + DWORD dwPhyCmrId; // Company/Module/Revision ID of the PHY + BOOL bLinkPass; // current link status + BOOL bSpeed100M; // current speed status + BOOL bFullDuplex; // current duplex status + UINT uConnectionType; // for media connect type parameter + + // for RDR + UINT cbRD; // number of total RD + PSRxDesc *apRD; // RD pointer array + SAllocMap amRxDescRing; + SAllocMap *aamRxDescBuf; + int idxRxCurDesc; + int idxRxdirtyDesc; + int idxRxPktStartDesc; // if multi-RD, this is the starting RD + + // for TDR + UINT cbTD; // number of total TD + PSTxDesc *apTD; // TD pointer array + SAllocMap amTxDescRing; + SAllocMap *aamTxDescBuf; + int idxTxCurDesc; + int idxTxdirtyDesc; + int idxTxPktStartDesc; // if multi-TD, this is the starting TD + UINT cbTxAbortRetry; + + DWORD dwCacheLineSize; + + // for IRQ + BYTE byIrqLevel; // IRQ number + PVOID pvAdapterIsr; // adapter's ISR + + INT iRxPktHandled; // rx packets has been handled + INT iTxPktPosted; // tx packets posted and wait to be sent + + // for statistic + SStatCounter scStatistic; + + // for default setting + BOOL bTxOn; + BOOL bTxContinuous; // for origional performance test (Tx Continuous - performance test) + BOOL bTxContFunTest; // for functional test (Tx Continuous - functional test) + BOOL bTxSinglePacket; + BOOL bRandomPktLength; + BOOL bRandomPktData; + LONG lTxPacketNum; + LONG lTxPacketNumShadow; + + // DEBUG.... + BOOL bWhenRxCrcErrNoBuf; + BOOL bWhenRxDataErrNoBuf; + BOOL bIncPktLength; + UINT cbPktSize; + + PBYTE pbyTmpBuff; + + // for 3065, multiple descriptors in one packet + UINT uTxDescNumPerPacket; + UINT uTxPktSize; + + // for 3065, Early Receive handling + BOOL bERNow; + + BOOL bPktFw; + PVOID pvFwAdapter; + +} SAdapterInfo, *PSAdapterInfo; + + +typedef struct _adapter_option { + int iTdRingNum; + int iRDescNum; + int iTDescNum; + UINT uiBuffsize; + BYTE byRevId; + BOOL bNoInit; + ULONG ulInitCmds; +} SAdapterOpts, *PSAdapterOpts; + +#define INIT_CMD_NONE 0 +#define INIT_CMD_CLEAR_STICKHW 0x00000001UL + +#define W_MAX_TIMEOUT 0x0FFFU // + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ +extern PSAdapterInfo sg_aAdapter; +extern SAdapterOpts g_sOptions; + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL +ADPbBind( + PSAdapterInfo pAdapter + ); + +BOOL +ADPbInitializeEx( + PSAdapterInfo pAdapter + ); + +BOOL +ADPbShutdown( + PSAdapterInfo pAdapter + ); + +UINT +ADPuInitAll( + void + ); + +VOID +CARDvSetLoopbackMode( + DWORD dwIoBase, + BYTE byRevId, + WORD wLoopbackMode + ); + +VOID +CARDvSetMediaLinkMode( + DWORD dwIoBase, + BYTE byRevId, + UINT uConnectionType + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __ADAPTER_H__ + diff --git a/cpu/arm920t/wmt/alloct.c b/cpu/arm920t/wmt/alloct.c new file mode 100755 index 0000000..da75657 --- /dev/null +++ b/cpu/arm920t/wmt/alloct.c @@ -0,0 +1,289 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#if !defined(__MEM_H__) +#include "mem.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__ALLOCT_H__) +#include "alloct.h" +#endif +#include "macif.h" +#if !defined(__DBG_H__) +#include "dbg.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +BOOL +ALCbAllocateRdrMemory( + PSAdapterInfo pAdapter + ) +{ + int jj; + + /* Allocate the Receive Descriptor ring */ + /* (Physically contiguous and non cached) */ + pAdapter->amRxDescRing.dwRawSize = sizeof(SRxDesc) * pAdapter->cbRD + pAdapter->dwCacheLineSize; + pAdapter->amRxDescRing.dwSize = sizeof(SRxDesc) * pAdapter->cbRD; + /* allocate raw RD : add cacheline */ + MEMvAllocateShared(&pAdapter->amRxDescRing); + MacDump(MACDBG_INFO, ("[ALCbAllocateRdrMemory] - pAdapter->amRxDescRing.dwRawVAddr : %p, size : %d\n", + (PVOID)pAdapter->amRxDescRing.dwRawVAddr, pAdapter->amRxDescRing.dwRawSize)); + + if (pAdapter->amRxDescRing.dwRawVAddr == 0) + return FALSE; + + /* descriptor MUST aligned by 4 dword */ + MEMvAlign(&pAdapter->amRxDescRing, (UINT)pAdapter->dwCacheLineSize); + + for (jj = 0; jj < pAdapter->cbRD; jj++) { + pAdapter->aamRxDescBuf[jj].dwRawSize = g_sOptions.uiBuffsize + pAdapter->dwCacheLineSize; + pAdapter->aamRxDescBuf[jj].dwSize = g_sOptions.uiBuffsize; + /* allocate Rx Buffer raw:add cacheline */ + MEMvAllocateShared(&pAdapter->aamRxDescBuf[jj]); + if (pAdapter->aamRxDescBuf[jj].dwRawVAddr == 0) { + printf("allocate RX Buffer failed\n "); + return FALSE; + } + MEMvAlign(&pAdapter->aamRxDescBuf[jj], (UINT)pAdapter->dwCacheLineSize); + } + + return TRUE; +} + + +BOOL +ALCbAllocateTdrMemory( + PSAdapterInfo pAdapter + ) +{ + /* Allocate the transmit descriptor ring */ + /* (Physically contiguous and non cached) */ + pAdapter->amTxDescRing.dwRawSize = sizeof(STxDesc) * pAdapter->cbTD + pAdapter->dwCacheLineSize; + pAdapter->amTxDescRing.dwSize = sizeof(STxDesc) * pAdapter->cbTD; + MEMvAllocateShared(&pAdapter->amTxDescRing); + MacDump(MACDBG_INFO, ("[ALCbAllocateTdrMemory] - pAdapter->amTxDescRing.dwRawVAddr : %p, size : %d\n", + (PVOID)pAdapter->amTxDescRing.dwRawVAddr, pAdapter->amTxDescRing.dwRawSize)); + + if (pAdapter->amTxDescRing.dwRawVAddr == 0) + return FALSE; + + /* Descriptor MUST aligned by 4 dword */ + MEMvAlign(&pAdapter->amTxDescRing, (UINT)pAdapter->dwCacheLineSize); + + if (!ALCbAllocateTdrBuffer(pAdapter, pAdapter->aamTxDescBuf, pAdapter->cbTD)) { + printf("allocte TX buffer failed\n"); + return FALSE; + } + return TRUE; +} + +BOOL +ALCbAllocateTdrBuffer( + PSAdapterInfo pAdapter, + SAllocMap asMaps[], + UINT cbTD + ) +{ + int ii; + + + for (ii = 0; ii < cbTD; ii++) { + asMaps[ii].dwRawSize = g_sOptions.uiBuffsize + pAdapter->dwCacheLineSize; + asMaps[ii].dwSize = g_sOptions.uiBuffsize; + + MEMvAllocateShared(&asMaps[ii]); + + if (asMaps[ii].dwRawVAddr == 0) + return FALSE; + + /* If allocated Tx buffers are double-word alignment, make it byte-alignment */ + if (asMaps[ii].dwRawVAddr % sizeof(DWORD) == 0) { + asMaps[ii].dwVAddr = asMaps[ii].dwRawVAddr + (ii % 4); + asMaps[ii].dwPAddr = LODWORD(asMaps[ii].qwRawPAddr) + (ii % 4); + } else { + asMaps[ii].dwVAddr = asMaps[ii].dwRawVAddr; + asMaps[ii].dwPAddr = LODWORD(asMaps[ii].qwRawPAddr); + } + } + + return TRUE; +} + +VOID +ALCvChainRdrMemory( + PSAdapterInfo pAdapter + ) +{ + int ii; + PSRxDesc pRD; + + /* Initialize the receive descriptor poniter array and */ + /* each individual receive descriptor */ + pRD = (PSRxDesc)pAdapter->amRxDescRing.dwVAddr; + + for (ii = 0; ii < pAdapter->cbRD; ii++) { + pAdapter->apRD[ii] = pRD; + + /* Init descriptor value */ + pRD->m_rd0RD0.f15FrameLen = 0; + pRD->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; + pRD->m_rd1RD1.f15RxBufLen = CB_MAX_BUF_SIZE; + + /* Set default RD buffer size to 512 bytes if 3065 (for multi-Rx descs per packet) */ + pRD->m_rd1RD1.f15RxBufLen = CB_BUF_SIZE_65; + + pRD->m_dwRxBufferAddr = pAdapter->aamRxDescBuf[ii].dwPAddr; + if (ii == (pAdapter->cbRD - 1)) + pRD->m_dwRxNextDescAddr = pAdapter->amRxDescRing.dwPAddr; + else + pRD->m_dwRxNextDescAddr = pAdapter->amRxDescRing.dwPAddr + sizeof(SRxDesc) * (ii + 1); + + pRD = (PSRxDesc)(pAdapter->amRxDescRing.dwVAddr + sizeof(SRxDesc) * (ii + 1)); + } +} + +VOID +ALCvChainTdrMemory( + PSAdapterInfo pAdapter + ) +{ + int ii; + PSTxDesc pTD; + + /* Initialize the tx desc ring */ + /* Initialize the Transmit Descriptor pointer array */ + pTD = (PSTxDesc)pAdapter->amTxDescRing.dwVAddr; + + for (ii = 0; ii < pAdapter->cbTD; ii++) { + pAdapter->apTD[ii] = pTD; + /* Init descriptor value */ + pTD->m_td0TD0.f1Owner = B_OWNED_BY_HOST; + /* modified by kevin:length =0 */ + pTD->m_td1TD1.f15TxBufLen = 0; + pTD->m_td1TD1.f1Chain = 1; + pTD->m_td1TD1.byTCR = TCR_IC | TCR_EDP | TCR_STP; + + pTD->m_dwTxBufferAddr = pAdapter->aamTxDescBuf[ii].dwPAddr; + if (ii == (pAdapter->cbTD - 1)) + pTD->m_dwTxNextDescAddr = pAdapter->amTxDescRing.dwPAddr; + else + pTD->m_dwTxNextDescAddr = pAdapter->amTxDescRing.dwPAddr + sizeof(STxDesc) * (ii + 1); + + pTD = (PSTxDesc)(pAdapter->amTxDescRing.dwVAddr + sizeof(STxDesc) * (ii + 1)); + } + + /* Init adapter's sturcture also, init value = MAX_PACKET_LEN */ + pAdapter->uTxPktSize = MAX_PACKET_LEN; + +} + +VOID +ALCvFreeRdrMemory( + PSAdapterInfo pAdapter + ) +{ + int ii; + + /* Free the receive descriptor ring. */ + if (pAdapter->amRxDescRing.dwRawVAddr != 0) + pAdapter->amRxDescRing.dwRawVAddr = 0; + + /* Free the Receive buffers */ + for (ii = 0; ii < pAdapter->cbRD; ii++) { + if (pAdapter->aamRxDescBuf[ii].dwRawVAddr != 0) + pAdapter->aamRxDescBuf[ii].dwRawVAddr = 0; + } +} + +VOID +ALCvFreeTdrMemory( + PSAdapterInfo pAdapter + ) +{ + int ii; + + /* Free the transmit descriptor ring */ + if (pAdapter->amTxDescRing.dwRawVAddr != 0) + pAdapter->amTxDescRing.dwRawVAddr = 0; + + /* Free the Transmit Buffers */ + for (ii = 0; ii < pAdapter->cbTD; ii++) { + if (pAdapter->aamTxDescBuf[ii].dwRawVAddr != 0) + pAdapter->aamTxDescBuf[ii].dwRawVAddr = 0; + } +} + +VOID +ALCvSetDefaultRD( + PSAdapterInfo pAdapter + ) +{ + /* set init RD value */ + ALCvChainRdrMemory(pAdapter); +} + +VOID +ALCvSetDefaultTD( + PSAdapterInfo pAdapter + ) +{ + int ii; + int jj; + PBYTE pbyBuf; + + DWORD adwPattern[4] = { + 0xFFFFFFFFL, 0x00000000L, + 0xAAAAAAAAL, 0x55555555L + }; + + /* Set init TD value */ + ALCvChainTdrMemory(pAdapter); + + /* Set tx descriptors owner to host(0) */ + /* Set IC = 1, EDP = 1, STP = 1 */ + for (ii = pAdapter->cbTD - 1; ii >= 0; ii--) { + pbyBuf = (PBYTE)pAdapter->aamTxDescBuf[ii].dwVAddr; + + /* Packet length maybe multiples of 16 */ + jj = 0; + while (jj < pAdapter->apTD[ii]->m_td1TD1.f15TxBufLen) { + if (jj < pAdapter->apTD[ii]->m_td1TD1.f15TxBufLen - 8) { + *(PDWORD)(pbyBuf + jj) = adwPattern[ii % 4]; + *(PDWORD)(pbyBuf + jj + 4) = adwPattern[ii % 4]; + jj += 8; + } else { + *(PBYTE)(pbyBuf + jj) = (BYTE)adwPattern[ii % 4]; + jj++; + } + } + } +} diff --git a/cpu/arm920t/wmt/alloct.h b/cpu/arm920t/wmt/alloct.h new file mode 100755 index 0000000..ecf9ee5 --- /dev/null +++ b/cpu/arm920t/wmt/alloct.h @@ -0,0 +1,94 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __ALLOCT_H__ +#define __ALLOCT_H__ + +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#include "mem.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL +ALCbAllocateRdrMemory( + PSAdapterInfo pAdapter + ); + +BOOL +ALCbAllocateTdrMemory( + PSAdapterInfo pAdapter + ); + +BOOL +ALCbAllocateTdrBuffer( + PSAdapterInfo pAdapter, + SAllocMap asMaps[], + UINT cbTD + ); + +VOID +ALCvChainRdrMemory( + PSAdapterInfo pAdapter + ); + +VOID +ALCvChainTdrMemory( + PSAdapterInfo pAdapter + ); + +VOID +ALCvFreeRdrMemory( + PSAdapterInfo pAdapter + ); + +VOID +ALCvFreeTdrMemory( + PSAdapterInfo pAdapter + ); + +VOID +ALCvSetDefaultRD( + PSAdapterInfo pAdapter + ); + +VOID +ALCvSetDefaultTD( + PSAdapterInfo pAdapter + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __ALLOCT_H__ diff --git a/cpu/arm920t/wmt/api-loader.c b/cpu/arm920t/wmt/api-loader.c new file mode 100755 index 0000000..8cda718 --- /dev/null +++ b/cpu/arm920t/wmt/api-loader.c @@ -0,0 +1,66 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2010 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +/* + * api-loader.c - this is entry support for the WMT evaluation board to go to loader + */ + +//#include <common.h> +#include <api_loader.h> + +#define LOADER_ADDR 0xffff0000 +#define HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR 0xFFFFFFC0 +#define DO_DVO_PLL_SET (HIBERNATION_ENTER_EXIT_CODE_BASE_ADDR + 0x38) +//#define wmt_debug +#ifdef wmt_debug +#define WMprintf(fmt, args...) printk("[%s]: " fmt, __FUNCTION__ , ## args) +#else +#define WMprintf(fmt, args...) +#endif + +int dvo_pll_set (unsigned int multi, unsigned char divisor, unsigned short resx, unsigned short resy) +{ + volatile unsigned int base = 0; + unsigned int exec_at = (unsigned int)-1; + int (*theKernel_dvo)(int from, unsigned int multi, unsigned char divisor, unsigned short resx, unsigned short resy); + int retval = 0; + + WMprintf("entry 0x%8.8X 0x%8.8X %d %d\n",multi, divisor, resx, resy); + /*enble SF clock*/ + /*REG32_VAL(PMCEU_ADDR) |= 0x00800000;*/ + + /*jump to loader api to do something*/ +/* base = (unsigned int)ioremap_nocache(LOADER_ADDR, 0x10000);*/ + base = (unsigned int)LOADER_ADDR; + exec_at = base + (DO_DVO_PLL_SET - LOADER_ADDR); + theKernel_dvo = (int (*)(int from, unsigned int multi, unsigned char divisor, unsigned short resx, unsigned short resy))exec_at; + + retval = theKernel_dvo(1, multi, divisor, resx, resy); + +/* iounmap((void *)base);*/ + + /*disable SF clock*/ +/* REG32_VAL(PMCEU_ADDR) &= ~0x00800000;*/ + + WMprintf("exit!!(%d)\n",retval); + + return retval; +} + diff --git a/cpu/arm920t/wmt/card.h b/cpu/arm920t/wmt/card.h new file mode 100755 index 0000000..cd49991 --- /dev/null +++ b/cpu/arm920t/wmt/card.h @@ -0,0 +1,73 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __CARD_H__ +#define __CARD_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__MII_H__) +#include "mii.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +// media type +#define MEDIA_AUTO 0x00 // +#define MEDIA_100M_HALF 0x01 // +#define MEDIA_100M_FULL 0x02 // +#define MEDIA_10M_HALF 0x03 // +#define MEDIA_10M_FULL 0x04 // +#define MEDIA_1M 0x05 // Home PHY + + + +/* + * Loopback mode + */ +/* LOBYTE is MAC LB mode, HIBYTE is MII LB mode */ +#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, MII_LB_NONE) +/* PHY must ISO, avoid MAC loopback packet go out */ +#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, MII_LB_ISO) // PHY must ISO, avoid MAC loopback packet go out +#define CARD_LB_MII MAKEWORD(MAC_LB_PHY, MII_LB_INTERNAL) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __CARD_H__ */ + + + diff --git a/cpu/arm920t/wmt/cypher.c b/cpu/arm920t/wmt/cypher.c new file mode 100755 index 0000000..41de88d --- /dev/null +++ b/cpu/arm920t/wmt/cypher.c @@ -0,0 +1,415 @@ +/*++
+Copyright (c) 2010 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+should have received a copy of the GNU General Public License along with this
+program. If not, see http://www.gnu.org/licenses/>.
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+/*--
+Revision History:
+-------------------------------------------------------------------------------
+
+--*/
+
+#include <malloc.h>
+
+#include "cypher.h"
+
+#ifdef DPRINTK
+ #undef DPRINTK
+#endif
+
+//#define DEBUG_CYPHER
+#ifdef DEBUG_CYPHER
+
+ #define DPRINTK printf
+
+ #define DPRINT_FUNC_IN() DPRINTK("--- Enter %s() ---\n", __FUNCTION__)
+ #define DPRINT_FUNC_OUT() DPRINTK("=== Exit %s() ===\n", __FUNCTION__)
+#else
+ #define DPRINTK(a,...)
+ #define DPRINT_FUNC_IN()
+ #define DPRINT_FUNC_OUT()
+#endif
+
+
+
+/*****************************************************************/
+u32 OUTPUT_buf[BUFFER_MAX];
+u32 in_table_buf[40960], out_table_buf[10];
+u32 KEY_buf[8], IV_buf[4], INC_buf;
+u8 cipher_int_flag = 0;
+
+/*****************************************************************/
+#define AHB_NOP(str) // DPRINTK("wait %d nop...\n", str)
+#ifndef AHB_NOP
+void AHB_NOP(int count)
+{
+ while(count) {
+ asm("nop");
+ count--;
+ }
+}
+#endif
+
+/****************************************************************/
+void cypher_isr(void)
+{
+ REG_SET32(CYPHER_DMA_INT_STATUS_REG, 0x00000001); //clear interrupt bit
+ cipher_int_flag = 1;
+ DPRINTK("cipher interrupt mode done! \n");
+}
+
+/*****************************************************************/
+void cypher_enable(
+ IN cypher_algo_t algo_mode)
+{
+ DPRINT_FUNC_IN();
+
+#ifdef CYPHER_INT_ENABLE
+ // enable cipher DMA Interrupt
+ REG_SET32(CYPHER_DMA_INT_ENABLE_REG, CYPHER_DMA_INT_ENABLE);
+#endif
+
+ // enable cipher Clock
+ switch(algo_mode) {
+ case CYPHER_ALGO_SHA256:
+ REG_SET32(CYPHER_CLK_ENABLE_REG, CYPHER_SHA256_CLK_ENABLE);
+ break;
+ default:
+ break;
+ }
+
+ // doing software reset to makesure ervrything is going well
+ REG_SET32(CYPHER_SW_RESET_REG, 0x01);
+ REG_SET32(CYPHER_SW_RESET_REG, 0x00);
+
+ DPRINT_FUNC_OUT();
+}
+
+/*****************************************************************/
+void cypher_disable(void)
+{
+ DPRINT_FUNC_IN();
+
+#ifdef CYPHER_INT_ENABLE
+ // disable cipher DMA Interrupt
+ REG_SET32(CYPHER_DMA_INT_ENABLE_REG, CYPHER_DMA_INT_DISABLE);
+#endif
+
+ // disable cipher Clock
+ REG_SET32(CYPHER_CLK_ENABLE_REG, CYPHER_CLK_DISABLE);
+
+ DPRINT_FUNC_OUT();
+}
+
+/*****************************************************************/
+void cypher_mode_set(
+ IN cypher_base_cfg_t *cypher_base_cfg)
+{
+ u32 sha256_variable = 0x00;
+
+ DPRINT_FUNC_IN();
+
+ if(cypher_base_cfg->algo_mode == CYPHER_ALGO_SHA256) {
+ REG_SET32(CYPHER_MODE_REG, CYPHER_SHA256_MODE); //Set cipher mode to SHA256
+
+ /* set data length to bit25-16, write 1 to bit1 to swap buffer, write 1 to bit0 to enable SHA256 */
+ sha256_variable = cypher_base_cfg->sha256_data_length;
+ REG_SET32(CYPHER_SHA256_DATA_LEN_REG, sha256_variable);
+
+ REG_SET32(CYPHER_SHA256_START_REG, (0x01 | 0x02 << 2));
+ }
+
+
+ DPRINT_FUNC_OUT();
+}
+
+
+
+/*****************************************************************/
+void cypher_prd_table(
+ IN int prd_tbl_addr,
+ IN int phy_base_addr,
+ IN int byte_count)
+{
+ int edt_byte_cnt, edt_bit;
+ int j, prd_bytecount;
+
+ DPRINT_FUNC_IN();
+
+ for (j = 0, edt_bit = 0; byte_count > 0; j++) {
+ if (byte_count > PRD_BYTE_COUNT_MAX) {
+ prd_bytecount = PRD_BYTE_COUNT_MAX;
+ byte_count -= PRD_BYTE_COUNT_MAX ;
+ }
+ else {
+ prd_bytecount = byte_count;
+ edt_bit = 1;
+ byte_count = 0;
+ }
+
+ edt_byte_cnt = (edt_bit << 31) + prd_bytecount;
+
+ REG_SET32((prd_tbl_addr + (j * PRD_TABLE_BOUNDARY)), (phy_base_addr + (j * PRD_BYTE_COUNT_MAX))); // Set memory read base address
+ REG_SET32((prd_tbl_addr + (j * PRD_TABLE_BOUNDARY) + 4), edt_byte_cnt); // Set EDT, Byte count
+ }
+
+#if 0
+DPRINTK("addr = %x \n", REG_GET32(prd_tbl_addr));
+DPRINTK("addr+4 = %x \n", REG_GET32(prd_tbl_addr+4));
+#endif
+
+ DPRINT_FUNC_OUT();
+}
+
+/*****************************************************************/
+void cypher_dma_start(void)
+{
+#ifndef CYPHER_INT_ENABLE
+ int r_value;
+#endif
+
+ DPRINT_FUNC_IN();
+
+ cipher_int_flag = 0;
+ REG_SET32(CYPHER_DMA_START_REG, 0x01); /*Set the DMA start*/
+
+ while(1) {
+#ifndef CYPHER_INT_ENABLE
+ r_value = REG_GET32(CYPHER_DMA_INT_STATUS_REG);
+
+ if( (r_value & 0x01) == 1 ) {
+ REG_SET32(CYPHER_DMA_INT_STATUS_REG, 0x00000001); //clear interrupt bit
+ cipher_int_flag = 1;
+ DPRINTK("cipher polling mode done! \n");
+ }
+#endif
+
+ if (cipher_int_flag)
+ break;
+ }
+
+ DPRINT_FUNC_OUT();
+}
+
+/****************************************************************/
+unsigned long cypher_transform(IN unsigned long temp)
+{
+ int i;
+ u32 buf;
+ buf = 0;
+
+ for (i = 0; i < 4; i++) {
+ buf += ((temp << 8 * (3 - i)) & 0xff000000) >> (8 * i);
+ }
+
+ return (buf);
+}
+
+
+/*****************************************************************/
+void Get_Output_Buf( OUT u32 dest_addr, u32 dest_size, u32 dec_enc )
+{
+ int patterns;
+ int total_u32;
+
+ DPRINT_FUNC_IN();
+
+ if (dest_size % DMA_BOUNDARY)
+ patterns = (dest_size / DMA_BOUNDARY) + 1;
+ else
+ patterns = (dest_size / DMA_BOUNDARY);
+
+ memset((void*)dest_addr, CYPHER_ZERO, dest_size * sizeof(u8));
+
+ total_u32 = patterns * (DMA_BOUNDARY / sizeof(u32));
+ memcpy((void*)dest_addr, OUTPUT_buf, total_u32 * sizeof(u32));
+
+#if 0
+#ifdef DEBUG
+{
+ int idx;
+
+ if (dec_enc == CYPHER_ENCRYPT) {
+ DPRINTK("ciphertext: ");
+ }
+ else {
+ DPRINTK("plaintext: ");
+ }
+
+ for (idx = 0; idx < total_u32; idx++) {
+ DPRINTK("%08x ", (uint)cypher_transform(OUTPUT_buf[idx]));
+ }
+ DPRINTK(" [%d]\n", total_u32);
+}
+#endif
+#endif
+
+ DPRINT_FUNC_OUT();
+}
+
+/*****************************************************************/
+void Count_Patterns(
+ IN int patterns,
+ OUT int *in_bytecount,
+ OUT int *out_bytecount,
+ OUT int *total_patterns )
+{
+ DPRINT_FUNC_IN();
+
+#if 1
+ *in_bytecount = patterns * DMA_BOUNDARY;
+ *out_bytecount = patterns * DMA_BOUNDARY;
+ *total_patterns = patterns * (DMA_BOUNDARY / sizeof(u32));
+#else
+ if(algo_mode == CYPHER_ALGO_DES || algo_mode == CYPHER_ALGO_TDES)
+ patterns = cypher_base->patterns * 2;
+
+ if(algo_mode == CYPHER_ALGO_AES || algo_mode == CYPHER_ALGO_RC4)
+ {
+ in_bytecount = patterns*128/8; //read data byte count
+ out_bytecount = patterns*128/8; //write data byte count
+ }
+ else if(algo_mode == CYPHER_ALGO_DES || algo_mode == CYPHER_ALGO_TDES)
+ {
+ in_bytecount = patterns*64/8; //read data byte count
+ out_bytecount = patterns*64/8; //write data byte count
+ }
+
+ //Compute total words of data
+ if(algo_mode == CYPHER_ALGO_AES || algo_mode == CYPHER_ALGO_RC4)
+ total_patterns = 4 * patterns;
+ else if(algo_mode == CYPHER_ALGO_DES || algo_mode == CYPHER_ALGO_TDES)
+ total_patterns = 2 * patterns;
+#endif
+
+ DPRINTK("in_bytecount: %d \n", *in_bytecount);
+ DPRINTK("out_bytecount: %d \n", *out_bytecount);
+ DPRINTK("total_patterns: %d \n", *total_patterns);
+
+ DPRINT_FUNC_OUT();
+}
+
+/*****************************************************************/
+int Cypher_Action( IN OUT cypher_base_cfg_t *cypher_base )
+{
+ int i;
+ int in_bytecount;
+ int out_bytecount;
+ int total_patterns;
+ int patterns;
+
+ DPRINT_FUNC_IN();
+
+ //memset(in_table_buf, CYPHER_ZERO, 1000 * sizeof(u32));
+ //memset(out_table_buf, CYPHER_ZERO, 1000 * sizeof(u32));
+
+ if (cypher_base->text_length % DMA_BOUNDARY)
+ patterns = (cypher_base->text_length / DMA_BOUNDARY) + 1;
+ else
+ patterns = (cypher_base->text_length / DMA_BOUNDARY);
+
+ if (cypher_base->algo_mode > CYPHER_ALGO_BASE_END)
+ return 1;
+
+
+ //Compute total words of data
+ Count_Patterns(patterns, &in_bytecount, &out_bytecount, &total_patterns);
+
+
+ /* actuality output bytes of SHA256 encrypt always = 32 Bytes */
+ if (cypher_base->algo_mode == CYPHER_ALGO_SHA256) {
+ out_bytecount = 32;
+ }
+
+ DPRINTK("*******************************************\n");
+
+
+ cypher_enable(cypher_base->algo_mode);
+ cypher_mode_set(cypher_base);
+
+
+ /****************************
+ Write PRD CIPHER_IN Control register
+ ****************************/
+ cypher_prd_table((int)in_table_buf, cypher_base->input_addr, in_bytecount);
+ //cypher_prd_table((int)in_table_buf, (int)INPUT_buf, in_bytecount);
+ REG_SET32(CYPHER_DMA_SOUR_ADDR_REG, (int)in_table_buf); // Set PRD read point
+
+ /****************************
+ Write PRD CIPHER_OUT Control register
+ ****************************/
+ cypher_prd_table((int)out_table_buf, (int)OUTPUT_buf, out_bytecount);
+ REG_SET32(CYPHER_DMA_DEST_ADDR_REG, (int)out_table_buf); // Set PRD write point
+
+ DPRINTK("in_table_buf=0x%08x \n", (uint)in_table_buf);
+ //DPRINTK("INPUT_buf=0x%08x \n", (uint)INPUT_buf);
+ DPRINTK("out_table_buf=0x%08x \n", (uint)out_table_buf);
+ DPRINTK("OUTPUT_buf=0x%08x \n", (uint)OUTPUT_buf);
+
+ /*if (total_patterns <= 32) {
+ DPRINTK("INPUT_buf: \n");
+ for(i = 0; i < total_patterns; i++)
+ DPRINTK("%08x ", (uint)INPUT_buf[i]);
+ DPRINTK(" [%d]\n", total_patterns);
+ }*/
+
+
+ //START CIPHER DMA
+ cypher_dma_start();
+
+
+ /*Now, text_length should be output bytes of SHA256 encrypt always = 32 Bytes */
+ if (cypher_base->algo_mode == CYPHER_ALGO_SHA256) {
+ cypher_base->text_length = 32;
+ }
+
+ if (total_patterns <= 32) {
+ DPRINTK("OUTPUT_buf: \n");
+ for(i = 0; i < total_patterns; i++)
+ DPRINTK("%08x ", (uint)OUTPUT_buf[i]);
+ DPRINTK(" [%d]\n", total_patterns);
+ }
+
+ DPRINT_FUNC_OUT();
+
+ cypher_disable();
+ return 0;
+}
+
+
+/*****************************************************************/
+void Clear_All_Buf(void)
+{
+ //memset(INPUT_buf, CYPHER_ZERO, BUFFER_MAX * sizeof(u32));
+ //memset(OUTPUT_buf, CYPHER_ZERO, BUFFER_MAX * sizeof(u32));
+ memset(KEY_buf, CYPHER_ZERO, 6 * sizeof(u32));
+ memset(IV_buf, CYPHER_ZERO, 4 * sizeof(u32));
+ INC_buf = CYPHER_ZERO;
+}
+
+/*****************************************************************/
+void Show_Register(int start, int end)
+{
+ int idx;
+ u32 value;
+
+ DPRINTK("Register [ 0x%x ~ 0x%x ]\n", start, end);
+ for (idx = start; idx <= end; idx += 4) {
+ value = REG_GET32(CYPHER_REG_BASE + idx);
+ DPRINTK("[0x%02x] %08x \n", idx, (uint)value);
+ }
+
+}
+
diff --git a/cpu/arm920t/wmt/cypher.h b/cpu/arm920t/wmt/cypher.h new file mode 100755 index 0000000..e7ce6a5 --- /dev/null +++ b/cpu/arm920t/wmt/cypher.h @@ -0,0 +1,159 @@ +/*++
+Copyright (c) 2010 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+should have received a copy of the GNU General Public License along with this
+program. If not, see http://www.gnu.org/licenses/>.
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+/*--
+Revision History:
+-------------------------------------------------------------------------------
+
+--*/
+
+#ifndef __CYPHER_H__
+#define __CYPHER_H__
+
+//#include "../../../board/wmt/include/global.h"
+#include "../../../common/wmt_display/hw/wmt_mmap.h"
+
+#define IN
+#define OUT
+#define IO
+
+/* Basic Define*/
+#define REG32 *(volatile unsigned int *)
+#define REG16 *(volatile unsigned short *)
+#define REG8 *(volatile unsigned char *)
+#define REG_GET32(addr) ( REG32(addr) ) /* Read 32 bits Register */
+#define REG_GET16(addr) ( REG16(addr) ) /* Read 16 bits Register */
+#define REG_GET8(addr) ( REG8(addr) ) /* Read 8 bits Register */
+#define REG_SET32(addr, val) ( REG32(addr) = (val) ) /* Write 32 bits Register */
+#define REG_SET16(addr, val) ( REG16(addr) = (val) ) /* Write 16 bits Register */
+#define REG_SET8(addr, val) ( REG8(addr) = (val) ) /* Write 8 bits Register */
+
+/*
+ * Refer CYPHER Module ver. 0.01
+ *
+ */
+
+#define CYPHER_REG_BASE SECURITY_ENGINE_CFG_BASE_ADDR// 1KB
+
+//the CYPHER status
+#define CYPHER_OK 0
+#define CYPHER_FAIL 1
+
+
+/*
+ * Registers
+ */
+// MISC
+#define CYPHER_SRAM_WR_DATA_REG CYPHER_REG_BASE + 0x0A8
+#define CYPHER_SRAM_WR_ADDR_REG CYPHER_REG_BASE + 0x0AC
+#define CYPHER_SRAM_WR_ENABLE_REG CYPHER_REG_BASE + 0x0B0
+#define CYPHER_MODE_REG CYPHER_REG_BASE + 0x0C0
+#define CYPHER_SW_RESET_REG CYPHER_REG_BASE + 0x0C4
+#define CYPHER_CLK_ENABLE_REG CYPHER_REG_BASE + 0x0C8
+#define CYPHER_DMA_INT_ENABLE_REG CYPHER_REG_BASE + 0x0CC
+
+// DMA
+#define CYPHER_DMA_START_REG CYPHER_REG_BASE + 0x0D0
+#define CYPHER_DMA_INT_STATUS_REG CYPHER_REG_BASE + 0x0D4
+#define CYPHER_DMA_SOUR_ADDR_REG CYPHER_REG_BASE + 0x0E0
+#define CYPHER_DMA_SOUR_RD_ADDR_REG CYPHER_REG_BASE + 0x0E4
+#define CYPHER_DMA_SOUR_RD_DWC_REG CYPHER_REG_BASE + 0x0E8
+#define CYPHER_DMA_DEST_ADDR_REG CYPHER_REG_BASE + 0x0F0
+#define CYPHER_DMA_DEST_RD_ADDR_REG CYPHER_REG_BASE + 0x0F4
+#define CYPHER_DMA_DEST_RD_DWC_REG CYPHER_REG_BASE + 0x0F8
+
+
+// SHA256
+#define CYPHER_SHA256_START_REG CYPHER_REG_BASE + 0x50
+#define CYPHER_SHA256_DATA_LEN_REG CYPHER_REG_BASE + 0x54
+
+
+//---------------------------------------------------------------------------------------
+// CYPHER define
+//---------------------------------------------------------------------------------------
+#define BUFFER_MAX 76802
+
+#define PRD_BYTE_COUNT_MAX 65520 // have to meet 16 Bytes alignment
+#define PRD_TABLE_BOUNDARY 8
+#define PRD_BYTE_COUNT_BOUNDARY 16
+
+#define DMA_BOUNDARY 16 // 16 bytes
+
+#define DATA_MAX 307200
+
+
+#define SHA256_TEXT_BOUNDARY 4
+#define SHA256_OUTPUT_SIZE 32
+
+// Encrypt/Decrypt mode
+#define CYPHER_ENCRYPT 1
+#define CYPHER_DECRYPT 0
+#define CYPHER_ZERO 0x0L
+
+// Cipher mode
+#define CYPHER_SHA256_MODE 4
+#define CYPHER_EXTERNAL_MODE 7
+
+#define CYPHER_SHA256_CLK_ENABLE 0x2003
+
+#define CYPHER_CLK_DISABLE 0
+
+// Cipher DMA Interrupt
+#define CYPHER_DMA_INT_ENABLE 1
+#define CYPHER_DMA_INT_DISABLE 0
+
+//---------------------------------------------------------------------------------------
+// CYPHER Data structure
+//---------------------------------------------------------------------------------------
+typedef enum cypher_algo_e
+{
+ CYPHER_ALGO_SHA256 = 7 // Secure Hash Algorithm 256
+} cypher_algo_t;
+
+#define CYPHER_ALGO_BASE_START CYPHER_ALGO_SHA256
+#define CYPHER_ALGO_BASE_END CYPHER_ALGO_SHA256
+
+// http://www-128.ibm.com/developerworks/tw/library/s-crypt02.html
+
+#define SIZEOF(x) sizeof(x)
+#define NO_OF( x ) ( SIZEOF( (x) ) / SIZEOF( (x)[0] ) )
+
+typedef struct cypher_base_cfg_s
+{
+ cypher_algo_t algo_mode;
+ int op_mode;
+ u32 dec_enc;
+ u32 input_addr;
+ u32 output_addr;
+ u32 text_length;
+ u32 key_addr;
+ u32 IV_addr; // Initial Vector address for CBC, CTR and OFB mode of AES
+ u32 INC; // for CTR mode of AES
+ u32 sha1_data_length; // for SHA1 only
+ u32 sha256_data_length; // for SHA256 only
+ int aes_hwkey;
+} cypher_base_cfg_t;
+
+//---------------------------------------------------------------------------------------
+// Defined in the cypherif.c
+//---------------------------------------------------------------------------------------
+void cypher_initialization(void);
+
+
+#endif // _CYPHER_H_
+
+
diff --git a/cpu/arm920t/wmt/cypherif.c b/cpu/arm920t/wmt/cypherif.c new file mode 100755 index 0000000..7077c83 --- /dev/null +++ b/cpu/arm920t/wmt/cypherif.c @@ -0,0 +1,180 @@ +/*++
+Copyright (c) 2010 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+should have received a copy of the GNU General Public License along with this
+program. If not, see http://www.gnu.org/licenses/>.
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+/*--
+Revision History:
+-------------------------------------------------------------------------------
+
+--*/
+
+#include "common.h"
+#include <malloc.h>
+
+#include <stdarg.h>
+#include "../../../board/wmt/include/wmt_clk.h"
+#include "cypher.h"
+
+
+
+//#define DEBUG_CYPHER
+#ifdef DEBUG_CYPHER
+
+ #define DPRINTK printf
+
+ #define DPRINT_FUNC_IN() DPRINTK("--- Enter %s() ---\n", __FUNCTION__)
+ #define DPRINT_FUNC_OUT() DPRINTK("=== Exit %s() ===\n", __FUNCTION__)
+#else
+ #define DPRINT_FUNC_IN()
+ #define DPRINT_FUNC_OUT()
+#endif
+
+/****************************************************************/
+extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd, int unit, int freq);
+
+
+
+/* NOTICE: the input data length of SHA256 must be multiple of 4Bytes */
+u8 Input_Plainttext[] = "abc";
+
+u8 Output_Plainttext[3] = {0};
+
+
+
+
+u8 Plaintext[DATA_MAX + 1]; // for output of decrypt
+
+u8 Ciphertext[DATA_MAX + 1]; // for output of encrypt
+
+int text_len;
+
+
+
+/****************************************************************/
+int Cypher_Action( IN OUT cypher_base_cfg_t *cypher_base );
+void Clear_All_Buf(void);
+void Set_Input_Buf( IN unsigned int src_addr, unsigned int src_size, unsigned int dec_enc );
+void Get_Output_Buf( OUT unsigned int dest_addr, unsigned int dest_size, unsigned int dec_enc );
+void Show_Register(int start, int end);
+void cypher_isr(void);
+
+
+
+
+
+/****************************************************************/
+int cipher_enc_dec( IN OUT cypher_base_cfg_t *cipher_obj )
+{
+ DPRINT_FUNC_IN();
+
+ Clear_All_Buf();
+ Cypher_Action(cipher_obj);
+ Get_Output_Buf(cipher_obj->output_addr, cipher_obj->text_length, cipher_obj->dec_enc);
+
+ DPRINT_FUNC_OUT();
+
+ return 0;
+}
+
+
+
+/****************************************************************/
+void cipher_obj_clear( IN cypher_base_cfg_t *cipher_obj )
+{
+ DPRINT_FUNC_IN();
+
+ cipher_obj->algo_mode = CYPHER_ALGO_SHA256;
+ cipher_obj->op_mode = 0;
+ cipher_obj->dec_enc = CYPHER_DECRYPT;
+ cipher_obj->text_length = 0x0;
+ cipher_obj->key_addr = CYPHER_ZERO;
+ cipher_obj->IV_addr = CYPHER_ZERO;
+
+ cipher_obj->input_addr = CYPHER_ZERO; // address
+ cipher_obj->output_addr = CYPHER_ZERO; // address
+ cipher_obj->INC = 0x0;
+ cipher_obj->sha1_data_length = 0x0;
+ cipher_obj->sha256_data_length = 0x0;
+
+ DPRINT_FUNC_OUT();
+}
+
+
+
+
+/****************************************************************/
+int sha256_action( cypher_base_cfg_t *test_object, u32 input_buf, u32 output_buf)
+{
+ int ret = 0;
+
+ test_object->algo_mode = CYPHER_ALGO_SHA256;
+ test_object->op_mode = 0;
+
+ // encrypt
+ test_object->input_addr = (u32)input_buf; // address
+ test_object->output_addr = (u32)Ciphertext; // address
+
+ test_object->dec_enc = CYPHER_ENCRYPT;
+ cipher_enc_dec(test_object);
+
+ memcpy((void*)output_buf, (void*)Ciphertext, 32);
+
+ return ret;
+}
+
+
+
+/****************************************************************/
+void cypher_initialization(void)
+{
+ auto_pll_divisor(DEV_SAE,CLK_ENABLE,0,0);
+#ifdef CYPHER_INT_ENABLE
+ /* Interrupt setting */
+ set_irq_handlers(IRQ_SAE, cypher_isr);
+ set_int_route(IRQ_SAE, 0);
+ unmask_interrupt(IRQ_SAE);
+#endif
+
+}
+
+void cipher_release(void)
+{
+
+ auto_pll_divisor(DEV_SAE,CLK_DISABLE,0,0);
+
+} /* End of cipher_release() */
+
+
+int cypher_encode(unsigned int buf_in, unsigned int in_len, unsigned int buf_out)
+{
+ cypher_base_cfg_t test_object;
+ int ret = 1;
+
+ cipher_obj_clear(&test_object);
+
+ test_object.sha256_data_length = in_len;
+ test_object.text_length = in_len;
+
+ ret = sha256_action(&test_object, (unsigned int)buf_in, (unsigned int)buf_out);
+
+ return ret;
+}
+
+
+
+
+
+
diff --git a/cpu/arm920t/wmt/dbg.h b/cpu/arm920t/wmt/dbg.h new file mode 100755 index 0000000..d9152b1 --- /dev/null +++ b/cpu/arm920t/wmt/dbg.h @@ -0,0 +1,47 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __DBG_H__ +#define __DBG_H__ + + +/*--------------------- Export Definitions -------------------------*/ +#if MACDBG +#define MACDBG_INFO ((ULONG)0x00000001) +#define MACDBG_ISR ((ULONG)0x00000002) +#define MACDBG_MAC ((ULONG)0x00000004) +#define MACDBG_SROM ((ULONG)0x00000008) + +extern ULONG MacDebugLevel; +#define MacDump(LEVEL,STRING) \ + do { \ + if (MacDebugLevel & (LEVEL)) { \ + printf STRING; \ + } \ + } while (0) +#else +#define MacDump(LEVEL,STRING) do {;} while (0) +#endif + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif // __DBG_H__ + diff --git a/cpu/arm920t/wmt/desc.h b/cpu/arm920t/wmt/desc.h new file mode 100755 index 0000000..cad492f --- /dev/null +++ b/cpu/arm920t/wmt/desc.h @@ -0,0 +1,191 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __DESC_H__ +#define __DESC_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +#define B_OWNED_BY_CHIP 1 // +#define B_OWNED_BY_HOST 0 // + +// +// Bits in the RSR0 register +// +#define RSR0_BUFF 0x80 // +#define RSR0_SERR 0x40 // +#define RSR0_RUNT 0x20 // +#define RSR0_LONG 0x10 // +#define RSR0_FOV 0x08 // +#define RSR0_FAE 0x04 // +#define RSR0_CRC 0x02 // +#define RSR0_RERR 0x01 // + +// +// Bits in the RSR1 register +// +#define RSR1_RXOK 0x80 // rx OK +#define RSR1_VIDHIT 0x40 // VID Hit +#define RSR1_MAR 0x20 // MAC accept multicast address packet +#define RSR1_BAR 0x10 // MAC accept broadcast address packet +#define RSR1_PHY 0x08 // MAC accept physical address packet +#define RSR1_CHN 0x04 // chain buffer, always = 1 +#define RSR1_STP 0x02 // start of packet +#define RSR1_EDP 0x01 // end of packet + +#define PQSTS_IPOK 0x20 //IP Checkusm validatiaon ok +#define PQSTS_TUOK 0x10 //TCP/UDP Checkusm validatiaon ok +#define PQSTS_IPKT 0x08 //Received an IP packet +#define PQSTS_TCPKT 0x04 //Received a TCP packet +#define PQSTS_UDPKT 0x02 //Received a UDP packet +#define PQSTS_TAG 0x01 //Received a tagged packet + +// +// Bits in the TSR0 register +// +#define TSR0_CDH 0x80 // AQE test fail (CD heartbeat) +#define TSR0_COLS 0x10 // experience collision in this transmit event +#define TSR0_NCR3 0x08 // collision retry counter[3] +#define TSR0_NCR2 0x04 // collision retry counter[2] +#define TSR0_NCR1 0x02 // collision retry counter[1] +#define TSR0_NCR0 0x01 // collision retry counter[0] + +// +// Bits in the TSR1 register +// +#define TSR1_TERR 0x80 // +#define TSR1_JAB 0x40 // jabber condition occured +#define TSR1_SERR 0x20 // +#define TSR1_TBUFF 0x10 // +#define TSR1_UDF 0x08 // +#define TSR1_CRS 0x04 // +#define TSR1_OWC 0x02 // late collision +#define TSR1_ABT 0x01 // + +// +// Bits in the TCR register +// +#define TCR_IC 0x80 // assert interrupt immediately + // while descriptor has been send complete +#define TCR_EDP 0x40 // end of packet +#define TCR_STP 0x20 // start of packet +#define TCR_TCPCK 0x10 // request TCP checksum calculation. +#define TCR_UDPCK 0x08 // request UDP checksum calculation. +#define TCR_IPCK 0x04 // request TCP checksum calculation. +#define TCR_CRC 0x01 // disable CRC generation + + +// max transmit or receive buffer size +//#define CB_MAX_BUF_SIZE 1536U // max buffer size +#define CB_MAX_BUF_SIZE 2048U // max buffer size +#define CB_BUF_SIZE_65 2048U // default Rx buffer size for 3065 + // NOTE: must be multiple of 4 +#define CB_MAX_RD_NUM 64 // MAX # of RD +#define CB_MAX_TD_NUM 32 // MAX # of TD + +#define CB_INIT_RD_NUM 10 // init # of RD, for setup default +#define CB_INIT_TD_NUM 10 // init # of TD, for setup default + +// for 3106S +#define CB_TD_RING_NUM 7 // # of TD rings. + +#define CB_MAX_DESC_PER_PKT 4 // max descriptors per packet (Tx) + +// max number of physical segments +// in a single NDIS packet. Above this threshold, the packet +// is copied into a single physically contiguous buffer +#define CB_MAX_SEGMENT (1 * CB_MIN_TX_DESC) + +#define CB_MAP_REGISTER_NUM (1 * CB_MAX_SEGMENT) + +// if collisions excess 15 times , tx will abort, and +// if tx fifo underflow, tx will fail +// we should try to resend it +#define CB_MAX_TX_ABORT_RETRY 3 + + +/*--------------------- Export Types ------------------------------*/ + +typedef struct tagRDES0 { + BYTE byRSR0; + BYTE byRSR1; + WORD f15FrameLen : 15; + WORD f1Owner : 1; +} SRDES0; + +typedef struct tagRDES1 { + WORD f15RxBufLen : 15; + WORD f1Reserve : 1; + BYTE byPQSTS; // VT3106 + BYTE byIPKT; // VT3106 +} SRDES1; + +// +// receive descriptor +// +typedef struct tagSRxDesc { + SRDES0 m_rd0RD0; + SRDES1 m_rd1RD1; + DWORD m_dwRxBufferAddr; // pointer to logical buffer + DWORD m_dwRxNextDescAddr; // pointer to next logical descriptor +} SRxDesc, *PSRxDesc; +typedef const SRxDesc* PCSRxDesc; + +typedef struct tagTDES0 { + BYTE byTSR0; + BYTE byTSR1; + WORD f12VID:12; + WORD f4Prioity:3; + WORD f1Owner : 1; +} STDES0; + +typedef struct tagTDES1 { + WORD f15TxBufLen : 15; + WORD f1Chain : 1; + BYTE byTCR; + BYTE byReserve; +} STDES1; + +// +// transmit descriptor +// +typedef struct tagSTxDesc { + STDES0 m_td0TD0; + STDES1 m_td1TD1; + DWORD m_dwTxBufferAddr; // pointer to logical buffer + DWORD m_dwTxNextDescAddr; // pointer to next logical descriptor +} STxDesc, *PSTxDesc; +typedef const STxDesc* PCSTxDesc; + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#endif // __DESC_H__ + diff --git a/cpu/arm920t/wmt/diag.h b/cpu/arm920t/wmt/diag.h new file mode 100755 index 0000000..b29afef --- /dev/null +++ b/cpu/arm920t/wmt/diag.h @@ -0,0 +1,98 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __DIAG_H__ +#define __DIAG_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +#define CMD_RBTST_TXRAM 0x01 +#define CMD_RBTST_RXRAM 0x02 +#define CMD_RBTST_SCANMODE 0x04 +#define CMD_RBTST_SEQMODE 0x08 +#define CMD_RBTST_PATMASK 0x70 + +typedef enum tagDIAG_TEST_ITEM { + DIAG_TEST_MAC_REG_RW = 1, + DIAG_TEST_EEP_CONT_RW = 2, + DIAG_TEST_MII_REG_RW = 3, + DIAG_TEST_MII_FLOWREG_RW = 4, + DIAG_TEST_IRQ_CONN = 5, + DIAG_TEST_INT_EXT_LBK = 6, + DIAG_TEST_RD_TD_HANDLE = 7, + DIAG_TEST_ADDR_MATCH_LOG = 8, + DIAG_TEST_CABLE_LINK = 9, + DIAG_TEST_ITEM_MAX +} DIAG_TEST_ITEM; +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL GDIAGbLoopbackOnceByPoll(PSAdapterInfo pAdapter); + +BOOL GDIAGbTestMacRegReadWrite(PSAdapterInfo pAdapter); +BOOL GDIAGbTestSromReadWrite(PSAdapterInfo pAdapter); +BOOL GDIAGbTestMiiRegReadWrite(PSAdapterInfo pAdapter); + +BOOL GDIAGbTestMiiRegRWPAUSE(PSAdapterInfo pAdapter); + +BOOL GDIAGbTestIrqConnect(PSAdapterInfo pAdapter); +BOOL GDIAGbTestRdTdHandling(PSAdapterInfo pAdapter); +BOOL GDIAGbTestAddrMatchLogic(PSAdapterInfo pAdapter); +BOOL GDIAGbTestCableLink(PSAdapterInfo pAdapter); + +BOOL GDIAGbTestLoopbackMac(PSAdapterInfo pAdapter); +BOOL GDIAGbTestLoopbackExt(PSAdapterInfo pAdapter); +BOOL GDIAGbTestLoopbackExtGiga(PSAdapterInfo pAdapter); + +BOOL GDIAGbTestPromiscuousMode(PSAdapterInfo pAdapter); +BOOL GDIAGbTestBroadcastMode(PSAdapterInfo pAdapter); +BOOL GDIAGbTestMulticastMode(PSAdapterInfo pAdapter); +BOOL GDIAGbTestDirectedMode(PSAdapterInfo pAdapter); +BOOL GDIAGbTestRuntPktMode(PSAdapterInfo pAdapter); +BOOL GDIAGbTestLongPktMode(PSAdapterInfo pAdapter); + +BOOL GDIAGbRAMBISTTest(PSAdapterInfo pAdapter); + +BOOL GDIAGbFIFOTest(PSAdapterInfo pAdapter); +VOID GDIAGvShowHWMibCounter( + PSAdapterInfo pAdapter, + PSHWMibCounter psHWMibCounter + ); + +ULONG GDIAGuNetworkTest(DWORD dwTimes, UINT uPktSize); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __DIAG_H__ */ diff --git a/cpu/arm920t/wmt/dma.c b/cpu/arm920t/wmt/dma.c new file mode 100755 index 0000000..60c2e7f --- /dev/null +++ b/cpu/arm920t/wmt/dma.c @@ -0,0 +1,926 @@ +/*++
+Copyright (c) 2010 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+should have received a copy of the GNU General Public License along with this
+program. If not, see http://www.gnu.org/licenses/>.
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+
+#include <config.h> +#include <common.h> +#include <asm/errno.h>
+#include <asm/arch/hardware.h> +#include <part.h> +#include <asm-arm/arch-wmt/common_def.h>
+
+#include <dma.h>
+#include <malloc.h>
+
+static struct dma_state dma_status;
+static struct DMA_INFO dma_chan[DMA_CHANNELS];
+
+static struct DMA_DESCRIPT_ADDR descript_chan[DMA_CHANNELS];
+
+/*
+* [Table Description]
+* Default dma channel setting for each peripheral device
+* [Arguments]
+* DeviceReq -> device dma request source
+* DefaultCCR -> default channel configuration register setting
+* Source_0/Destination_0 -> address settings for buffer 0
+* Source_1/Destination_1 -> address settings for buffer 1
+*/
+struct dma_device_cfg dma_device_cfg_table[] = {
+/* DeviceReq , DefaultCCR , Source_0, Destination_0 */
+ { SPI0_DMA_TX_REQ , 0x00000100 , 0, 0 } , /*spi0*/
+ { SPI0_DMA_RX_REQ , 0x00000100 , 0, 0 } , /*spi1*/
+ { SPI1_DMA_TX_REQ , 0x00000100 , 0, 0 } ,
+ { SPI1_DMA_RX_REQ , 0x00000100 , 0, 0 } ,
+ { SPI2_DMA_TX_REQ , 0x00000100 , 0, 0 } ,
+ { SPI2_DMA_RX_REQ , 0x00000100 , 0, 0 } ,
+ /* start from 0, above 5, below 6 */
+ { UART_0_TX_DMA_REQ , 0x00000100, 0, 0 } , /* uart2*/
+ { UART_0_RX_DMA_REQ , 0x00000100, 0, 0 } , /* uart2*/
+ { UART_1_TX_DMA_REQ , 0x00000100, 0, 0 } ,
+ { UART_1_RX_DMA_REQ , 0x00000100, 0, 0 } ,
+ { UART_2_TX_DMA_REQ , 0x00000100, 0, 0 } , /* uart1*/
+ /*start from 0, above 10, below 11 */
+ { UART_2_RX_DMA_REQ , 0x00000100, 0, 0 } , /* uart1*/
+ { UART_3_TX_DMA_REQ , 0x00000100, 0, 0 } ,
+ { UART_3_RX_DMA_REQ , 0x00000100, 0, 0 } ,
+ { I2S_TX_DMA_REQ , 0x00000100, 0, 0 } ,
+ { I2S_RX_DMA_REQ , 0x00000100, 0, 0 } ,
+ /*start from 0, above 15, below 16 */
+ { UART_4_TX_DMA_REQ , 0x00000100, 0, 0} ,
+ { UART_4_RX_DMA_REQ , 0x00000100, 0, 0} ,
+ { AC97_PCM_TX_DMA_REQ , 0x00000100, 0, 0} ,
+ { AC97_PCM_RX_DMA_REQ , 0x00000100, 0, 0} ,
+ { AC97_MIC_DMA_REQ , 0x00000100, 0, 0} ,
+ /*start from 0, above 20, below 21 */
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { UART_5_TX_DMA_REQ , 0x00000100, 0, 0} ,
+ { UART_5_RX_DMA_REQ , 0x00000100, 0, 0} ,
+ /*start from 0, above 30, below 31 */
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+ { MEMORY_DMA_REQ , 0x2a800000, 0x0a200000 , 0x0a220000} ,
+ { DEVICE_RESERVED , 0x00000100, 0, 0} ,
+};
+
+/*
+* [Routine Description]
+* inital DMA
+* 1. init dma_status and DMA_INFO structure for each dma channels
+* 2. init dma channel registers for each channels
+* 3. dma controller enable
+* it is necessary to allocate space to store
+* memory registers and descript register.
+* So we allocate these space while initing at the first time
+*/
+void init_dma(void)
+{
+ int ch;
+ struct DMA_REG *dma_regs ;
+ struct DMA_MEM_REG *dma_mem_regs;
+
+ static unsigned int first_init = 0;
+ static unsigned int dma_mem_regs_base;
+ dma_regs = (struct DMA_REG *)BA_DMA;
+ unsigned long addr;
+
+ printf("DMA INIT\n");
+
+ /*
+ // software initial
+ */
+ dma_status.request_chans = 0 ;
+ dma_status.regs = (struct DMA_REG *) BA_DMA;
+
+ for (ch = 0 ; ch < DMA_CHANNELS ; ++ch) {
+ if (first_init) {
+ free((unsigned long *)dma_chan[ch].DES_ADDR.DES_0);
+ free((unsigned long *)dma_chan[ch].DES_ADDR.DES_1_2);
+ free_descriptstack(ch);
+ }
+ //des_0 = calloc(SIZE_8KB,sizeof(int));
+ //des_1 = calloc(SIZE_8KB,sizeof(int));
+
+
+ dma_chan[ch].DES_ADDR.DES_0 = descript_chan[ch].despstack_0.addr_base;
+ dma_chan[ch].DES_ADDR.DES_1_2 = descript_chan[ch].despstack_1_2.addr_base;
+ dma_chan[ch].channel_no = ch ;
+ dma_chan[ch].regs = (struct DMA_REG *) BA_DMA;
+ dma_chan[ch].device_no = DEVICE_RESERVED ;
+ dma_chan[ch].in_use = 0 ;
+ dma_chan[ch].descript_cnt = 0;
+ }
+ /*
+ * hardware initial
+ */
+
+ dma_status.regs->DMA_GCR |= DMA_SW_RST ;
+ //REG32_VAL(0xD8001000 + 0x40) |= DMA_SW_RST;
+ //REG32_VAL(0xD8001800 + 0x40) |= DMA_GLOBAL_EN;
+ //*(volatile unsigned int *)BA_DMA |= DMA_SW_RST;
+
+
+
+ dma_status.regs->DMA_GCR |= DMA_GLOBAL_EN;
+ dma_status.regs->DMA_ISR = ALL_INT_CLEAR;
+ dma_status.regs->DMA_IER |= ALL_INT_EN;
+ dma_status.regs->DMA_TMR &= ~SCHEDULE_RR_DISABLE; /*use RR schedule*/
+
+
+ if (first_init)
+ free((unsigned int *)dma_mem_regs_base);
+
+
+ dma_mem_regs = (struct DMA_MEM_REG *)malloc((sizeof(struct DMA_MEM_REG)+256));
+ dma_mem_regs_base = (unsigned int)dma_mem_regs;
+
+ addr = (unsigned long)dma_mem_regs;
+ addr &= (unsigned long)0xFFFFFF00;
+ addr += 256;
+ dma_mem_regs = (struct DMA_MEM_REG *) addr;
+ //(unsigned long)dma_mem_regs &= (unsigned long)0xFFFFFF00;
+ //(unsigned long)dma_mem_regs += 256;
+ dma_status.regs->DMA_MRPR = (unsigned long)dma_mem_regs;
+
+
+ for (ch = 0 ; ch < DMA_CHANNELS ; ++ch) {
+ dma_chan[ch].mem_regs = (struct DMA_MEM_REG *)dma_mem_regs;
+ dma_mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0x0;
+ dma_mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = 0x0;
+ dma_status.regs->DMA_CCR_CH[ch] = 0x0;
+ }
+
+
+ if(!first_init)
+ first_init++;
+
+ printf("DMA INIT finish\n");
+
+}
+
+void disable_dma(void)
+{
+ dma_status.regs->DMA_GCR &= (~DMA_GLOBAL_EN);
+}
+
+void enable_dma(void)
+{
+ unsigned int ch = 0;
+ dma_status.regs->DMA_GCR |= DMA_GLOBAL_EN;
+ for (ch = 0; ch < DMA_CHANNELS; ++ch)
+ dma_status.regs->DMA_CCR_CH[ch] |= SYSTEM_DMA_RUN;
+}
+
+
+/*
+* [Routine Description]
+* request a free dma channel
+* 1. search free dma channel,
+* 2. update arguments to specific DMA_INFO structure
+* 3. re-setting dma channel registers according to new configuration
+* [Arguments]
+* channel -> interrupt number
+* device_id -> device id string
+* device -> dma_device structure
+* callback -> device isr function
+* [Return]
+* 0 -> success
+* -1 -> fail
+*/
+int request_dma(unsigned int *channel, const char *device_id, enum dma_device device)
+{
+ int ch;
+ struct DMA_INFO *dma;
+ *channel = -1;
+
+ /*
+ * Ask for Free Channels
+ */
+
+ for (ch = 0 ; ch < DMA_CHANNELS ; ++ch) {
+ dma = &dma_chan[ch];
+ if (dma->in_use == 0)
+ break ;
+ }
+
+ if (ch >= DMA_CHANNELS) {
+ printf("DMA : %s no free DMA channel available\n\r", device_id);
+ return -1; /* EBUSY*/
+ }
+
+ /*
+ * Request IRQ, all DMA Share one IRQ, so we do request only request_chans is zero
+ */
+ //if (!(dma_status.request_chans & (1 << ch))) {
+ //set_irq_handlers(dma_irq_mapping[ch], dma_irq_handler) ;
+ //unmask_interrupt(dma_irq_mapping[ch]) ;
+ //}
+
+ dma_status.request_chans = (1 << ch) ;
+
+ *channel = ch;
+ dma->device_id = device_id;
+ dma->device_no = device ;
+ //dma->callback = callback;
+ dma->in_use = 1;
+ dma->descript_cnt = 0;
+
+ /*
+ * clear status register
+ */
+ dma->regs->DMA_ISR |= 1<<ch;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0x0; /*reset descript*/
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = 0x0; /*reset descript*/
+ /*set shadow descript addr*/
+ descript_chan[ch].DES_0 = dma->DES_ADDR.DES_0;
+ descript_chan[ch].DES_1_2 = dma->DES_ADDR.DES_1_2;
+ /*
+ * setup default device
+ */
+ dma->device_cfg = dma_device_cfg_table[device] ;
+
+ /*
+ *Critical 3: It should be filled with DefaultCCR
+ */
+ /*Dean:To do*/
+ dma->regs->DMA_CCR_CH[ch] = (dma_device_cfg_table[device].DefaultCCR & DMA_USER_SET_MASK) ;
+ if (device != MEMORY_DMA_REQ)
+ dma->regs->DMA_CCR_CH[ch] |= device << DMA_REQ_ID_SHIFT;
+
+
+ #ifdef CONFIG_EMU
+ printf("DMA : requested dma device %d\n\r", device);
+ #endif /*CONFIG_EMU*/
+ return 0;
+}
+
+/*
+* [Routine Description]
+* clear specific dma channel register
+* [Arguments]
+* ch -> channel number
+*/
+void clear_dma(unsigned int ch)
+{
+ struct DMA_INFO *dma;
+ dma = &dma_chan[ch] ;
+
+ /*
+ * clear status register
+ */
+ dma->regs->DMA_CCR_CH[ch] = 0x0;
+ dma->regs->DMA_ISR |= 0x1<<ch;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0x0; /*clear M_0 descript address*/
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = 0x0; /*clear M_1/2 descript address*/
+ dma->descript_cnt = 0x0;
+ free((unsigned long *)dma->DES_ADDR.DES_0);
+ free((unsigned long *)dma->DES_ADDR.DES_1_2);
+}
+
+/*
+* [Routine Description]
+* release specific dma channel
+* 1. check whether free correct dma channel
+* 2. clear_dma()
+* 3. clear specific DMA_INFO structure and SCC register setting for dma request source
+* [Arguments]
+* ch -> channel number
+*/
+void free_dma(unsigned int ch)
+{
+ struct DMA_INFO *dma;
+ enum dma_device dev_no ;
+
+ if (ch >= MAX_DMA_CHANNELS) {
+ printf("DMA : bad DMA identifier\n\r");
+ return ;
+ }
+
+ dma = &dma_chan[ch];
+ if (dma->in_use == 0) {
+ #ifdef CONFIG_EMU
+ printf("DMA : trying to free free dma channe %dl\n\r", ch);
+ #endif
+ return;
+ }
+
+ if (dma->device_no == DEVICE_RESERVED) {
+ printf("DMA : trying to free free dma %d\n\r", ch);
+ return ;
+ }
+
+ clear_dma(ch);
+
+ dma_status.request_chans &= ~(1 << ch);
+ //if (dma_status.request_chans == 0)
+ // unset_irq_handlers(dma_irq_mapping[ch]);
+
+
+ dev_no = dma->device_no ;
+ /*if(dev_no != MEMORY_DMA_REQ)
+ dma->scc_regs->DMA_REQ_CSR[ dev_no ] = ( SCC_CSR_DISABLE | SCC_CSR_SYSTEM_DMA | 0 ) ;*/
+ dma->device_no = DEVICE_RESERVED ;
+ dma->device_id = NULL ;
+ dma->in_use = 0;
+}
+
+/*
+* [Routine Description]
+* setup dma configure table with relative dma channel and re-setting dma channel registers
+* 1. check whether setup correct dma channel
+* 2. clear dma relative status register
+* 3. update dma_device_cfg table
+* 4. re-setting dma channel registers
+* [Arguments]
+* ch -> channel number
+* device_cfg -> dma_device_cfg structure
+* [Return]
+* 0 -> success
+* 1 -> fail
+*/
+int setup_dma(unsigned int ch, struct dma_device_cfg device_cfg)
+{
+ struct DMA_INFO *dma;
+ enum dma_device dev_no ;
+
+ dma = &dma_chan[ch];
+
+ if (ch >= MAX_DMA_CHANNELS || (dma_chan[ch].in_use == 0)) {
+ printf("DMA : bad DMA identifier\n\r");
+ return -1 ; /* EINVAL*/
+ }
+
+ if (dma->device_no != device_cfg.DeviceReqType) {
+ printf("DMA : bad Device_NO\n\r");
+ return -1 ;
+ }
+
+ //printf("CCR setting ch%d = %x\n", ch, device_cfg.DefaultCCR);
+
+ dev_no = dma->device_no ;
+ dma_device_cfg_table[dev_no] = device_cfg ;
+ dma->device_cfg = dma_device_cfg_table[dev_no] ;
+
+ /*
+ * clear status register
+ */
+ dma->regs->DMA_ISR |= 1<<ch;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0x0; /*reset descript*/
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = 0x0; /*reset descript*/
+
+ dma->regs->DMA_CCR_CH[ch] = dma_device_cfg_table[dev_no].DefaultCCR ;
+ if (device_cfg.DeviceReqType != MEMORY_DMA_REQ)
+ dma->regs->DMA_CCR_CH[ch] |= device_cfg.DeviceReqType << DMA_REQ_ID_SHIFT;
+
+ /*Device -> Memory(Read)*/
+ //if (dma->regs->DMA_CCR_CH[ch] & DEVICE_TO_MEM) {
+ /* 0x00010000*/
+ // dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = dma->device_cfg.MIF1addr;
+ // dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0 ;
+ //} else {/* Memory(Write)i-->Device*/
+ // dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = 0 ;
+ // dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = dma->device_cfg.MIF1addr ;
+ //}
+ //if (dev_no == MEMORY_DMA_REQ) {
+ /*
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = dma->device_cfg.MIF0addr;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = dma->device_cfg.MIF1addr;
+ */
+ descript_chan[ch].DES_0 = dma->DES_ADDR.DES_0; /*we set descript size to 2 KB*/
+ descript_chan[ch].DES_1_2 = dma->DES_ADDR.DES_1_2; /*we set descript size to 2 KB*/
+ //}
+ return 0;
+}
+
+
+
+/*===================================================*/
+/* [Routine Description]*/
+/* check relative dma channel whether enable or disable*/
+/* [Arguments]*/
+/* ch -> channel number*/
+/* [Return]*/
+/* 1 -> busy(enable)*/
+/* 0 -> not busy(disable)*/
+/* other -> fail*/
+/*===================================================*/
+int dma_busy(unsigned int ch)
+{
+ struct DMA_INFO *dma;
+ /*
+ unsigned int newtimer = 0;
+ */
+ dma = &dma_chan[ch];
+ if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
+ printf("DMA : bad DMA identifier\n\r");
+ return -1 ; /* EINVAL*/
+ }
+
+ if (dma->regs->DMA_CCR_CH[ch] & DMA_ACTIVE)
+ return 1 ;
+ else
+ /*
+ newtimer = ReadTimer();
+ printf("time = %d\n",(newtimer-global_timer));
+ */
+ return 0;
+
+}
+
+/*===================================================*/
+/* [Routine Description]*/
+/* check terminal count bit of relative dma channel*/
+/* [Arguments]*/
+/* ch -> channel number*/
+/* [Return]*/
+/* 0 -> complete*/
+/* 1 -> not complete*/
+/* other -> fail*/
+/*===================================================*/
+int dma_complete(unsigned int ch)
+{
+ struct DMA_INFO *dma;
+
+ dma = &dma_chan[ch];
+ if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
+ printf("DMA : bad DMA identifier\n\r");
+ return -1 ; /* EINVAL*/
+ }
+ /*
+ if ((dma->regs->DMA_CCR_CH[ch]&DMA_EVT_ID_MASK) == DMA_EVT_SUCCESS)
+ return 0 ;
+ */
+ if (dma->regs->DMA_CCR_CH[ch] & DMA_P0_COMPLETE)
+ return 0 ;
+ else
+ return 1;
+
+}
+
+/*===================================================*/
+/* [Routine Description]*/
+/* start specific dma channel transfer*/
+/* 1. check whether data size or buffer usage correctly*/
+/* 2. configure relative dma channel registers*/
+/* 3. dma channel enable*/
+/* [Arguments]*/
+/* ch -> channel number*/
+/* dma_ptr1 -> source/destionation address for memory-to-peripheral/peripheral-to-memory transfer*/
+/* or source address for memory-to-memory transfer*/
+/* dma_ptr2 -> destination address for memory-to-memory transfer*/
+/* size -> transfer data size*/
+/* [Return]*/
+/* 0 -> start transfer*/
+/* -1 -> fail*/
+/*===================================================*/
+int start_dma(unsigned long ch, unsigned long dma_ptr1, unsigned long dma_ptr2, unsigned long size)
+{
+ int count ;
+ int residue_count;
+ int des_cnt;
+ unsigned int current_des0;
+ struct DMA_INFO *dma ;
+ enum dma_device dev_no ;
+
+ /*
+ global_timer = 0
+ SetTimer();
+ */
+ dma = &dma_chan[ch] ;
+
+ if (size == 0)
+ return -1 ;
+
+ dev_no = dma->device_no ;
+ count = size;
+ residue_count = size;
+ current_des0 = descript_chan[ch].DES_0;
+ //if (dev_no == MEMORY_DMA_REQ) {
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = descript_chan[ch].DES_0;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = descript_chan[ch].DES_1_2;
+ des_cnt = prepare_dma_descript(current_des0, dma_ptr1, residue_count);
+ dma->descript_cnt += des_cnt;
+ current_des0 += des_cnt*DMA_DES0_SIZE;
+ descript_chan[ch].DES_0 = current_des0;
+ dma->descript_cnt = prepare_dma_descript(descript_chan[ch].DES_1_2, dma_ptr2, count);
+ descript_chan[ch].DES_1_2 += dma->descript_cnt*DMA_DES0_SIZE;
+
+ //} else {
+ // dma->descript_cnt = prepare_dma_descript(descript_chan[ch].DES_0, dma_ptr1, count);
+ // dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = descript_chan[ch].DES_0;
+ //}
+ //dma->descript_cnt--;
+ /*
+ global_timer = ReadTimer();
+ */
+ dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_RUN);
+ dma->regs->DMA_CCR_CH[ch] |= SYSTEM_DMA_RUN;
+ printf("IF0CPR ch%d = %x\n", ch, dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH);
+ printf("IF1CPR ch%d = %x\n", ch, dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH);
+
+ return 0;
+}
+
+/*===================================================*/
+/* [Routine Description]*/
+/* dma interrupt service routine*/
+/* 1. check which dma channel interrupt event occur*/
+/* 2. clear interrupt event*/
+/* 3. call to relative device isr routine*/
+/*===================================================*/
+void handle_dma_irq(unsigned long ch)
+{
+ unsigned int global_status ;
+ unsigned char chan_status ; /* fix to use 8-bit character, temp comment */
+ struct DMA_INFO *dma ;
+
+ if (ch >= DMA_CHANNELS){
+ printf("DMA : unknown DMA IRQ\n\r") ;
+ return ;
+ }
+ dma = &dma_chan[ch] ;
+
+ //while(1){
+
+ global_status = (dma_status.regs->DMA_ISR & 0xFFFF) ;
+ while(!(global_status & (0x0001 << ch))){
+ global_status = (dma_status.regs->DMA_ISR & 0xFFFF);
+ }
+
+ //while (1) {
+ // if (dma_busy(ch) != 1)
+ // break;
+ //}
+
+ //printf("DMA%d, %x : \n", ch, dma_status.regs->DMA_CCR_CH[ch]);
+
+ if (global_status & (0x0001 << ch)) {
+ chan_status = dma_status.regs->DMA_CCR_CH[ch] ;
+ if ((chan_status & DMA_EVT_ID_MASK) == DMA_EVT_SUCCESS){
+ dma_status.regs->DMA_ISR = 1<<ch; /* Harry@Feb.28.2005*/
+ //break ; /* do one servce, each time*/
+
+ }
+ }
+
+
+ /*
+ * If there is any DMA error flag turned on.
+ */
+ if ((chan_status & DMA_EVT_ID_MASK) != DMA_EVT_SUCCESS) {
+ /* 1. clear error/abort status*/
+ /* 2. re-program src/des/cnt reg 0 and 1*/
+ /* 3. write "1" to csr bit6 to reset the buffer pointer to 0*/
+ /* 4. re-enable dma channle*/
+
+ /*
+ * I hold in here and try to look what is the error.
+ */
+ while (1)
+ ;
+ return ;
+ }
+
+ /*
+ * Decrease the channel buffer usage indicator.
+ */
+ //}
+ return;
+}
+/*===================================================*/
+/* [Routine Description]*/
+/* create dma descript format 0*/
+/* 1. clear the last descript end bit and interrupt bit*/
+/* 2. count how many descripts need to be setting*/
+/* 3. set descript */
+/* [Arguments]*/
+/* start_descript---> the first descript address*/
+/* start_addr----> the first data address*/
+/* size----> the size needing to transfer*/
+/*===================================================*/
+int prepare_dma_descript(unsigned int start_descript, unsigned int start_addr, unsigned int size)
+{
+ unsigned int need_descriptcnt ;
+ unsigned int residue_size;
+ unsigned int i;
+ unsigned des_col0;
+ des_col0 = 0;
+ need_descriptcnt = size/SIZE_32KB;
+ residue_size = size%SIZE_32KB;
+ struct DMA_DES_FMT0 *descript_addr;
+ descript_addr = (struct DMA_DES_FMT0 *)start_descript;
+ --descript_addr;
+ descript_addr->REQCNT &= ~(DMA_DES_END|DMA_INTEN_DES);
+ ++descript_addr;
+ for (i = 0; i < need_descriptcnt; ++i) {
+ des_col0 = 0;
+ des_col0 = SIZE_32KB;
+ descript_addr->REQCNT = des_col0;
+ descript_addr->DATAADDR = start_addr + i*SIZE_32KB;
+ ++descript_addr;
+ }
+ if (residue_size != 0) {
+ need_descriptcnt++;
+ des_col0 = 0;
+ des_col0 = (DMA_DES_END|DMA_INTEN_DES|residue_size);
+ descript_addr->REQCNT = des_col0;
+ descript_addr->DATAADDR = start_addr + i*SIZE_32KB;
+ } else {
+ --descript_addr;
+ descript_addr->REQCNT |= DMA_DES_END|DMA_INTEN_DES;
+ }
+ return need_descriptcnt;
+}
+/*===================================================*/
+/* [Routine Description]*/
+/* create dma descript format 1*/
+/* [Arguments]*/
+/* start_descript---> the first descript address*/
+/* branch_descript---> branch descirpt*/
+/* start_addr----> the first data address*/
+/* size----> the size needing to transfer*/
+/* last--->*/
+/* 0:did not the last descript*/
+/* 1:the last descript*/
+/*===================================================*/
+int prepare_dma_long_descript(unsigned int start_descript, unsigned int branch_descript,
+ unsigned int start_addr, unsigned int size, unsigned int last_des)
+{
+ unsigned int need_descriptcnt ;
+ unsigned des_col0;
+ need_descriptcnt = 1;
+ if (size >= 0x10000) {
+ printf("reqCount too big\n");
+ return 1;
+ }
+ des_col0 = 0;
+ struct DMA_DES_FMT1 *descript_addr;
+ descript_addr = (struct DMA_DES_FMT1 *)start_descript;
+ des_col0 = 0;
+ des_col0 = DMA_FORMAT_DES1|TRAN_SIZE;
+ descript_addr->REQCNT = des_col0;
+ descript_addr->DATAADDR = start_addr ;
+ descript_addr->BRADDR = branch_descript ;
+
+ if (last_des != 0) {
+ need_descriptcnt++;
+ des_col0 = 0;
+ des_col0 |= (DMA_DES_END|DMA_INTEN_DES);
+ }
+ ++descript_addr;
+ return need_descriptcnt;
+}
+
+void wake_dma_channel(unsigned int ch)
+{
+ dma_status.regs->DMA_CCR_CH[ch] |= DMA_WAKE;
+}
+/*===================================================*/
+/* [Routine Description]*/
+/* add descipt from the end of the last transfer descript*/
+/* [Arguments]*/
+/* ch--->dma channel number*/
+/* source_addr--->the source data address */
+/* dest_addr--->the destination data address*/
+/* transfer_size--->the size you want transfer*/
+/*===================================================*/
+void add_descript(unsigned int ch, unsigned int source_addr,
+ unsigned int dest_addr, unsigned int transfer_size)
+{
+ unsigned des_cnt;
+ struct DMA_INFO *dma ;
+ dma = &dma_chan[ch];
+ prepare_dma_descript(descript_chan[ch].DES_0, source_addr, transfer_size);
+ des_cnt = prepare_dma_descript(descript_chan[ch].DES_1_2, dest_addr, transfer_size);
+ dma->descript_cnt += des_cnt ;
+ descript_chan[ch].DES_0 += des_cnt*DMA_DES0_SIZE ;
+ descript_chan[ch].DES_1_2 += des_cnt*DMA_DES0_SIZE;
+}
+
+void init_descriptstack(unsigned int ch)
+{
+ struct DMA_DES_FMT1 *descript_addr;
+ descript_chan[ch].despstack_0.addr_base = (unsigned int)calloc(SIZE_8KB + 8,sizeof(int));
+ descript_chan[ch].despstack_1_2.addr_base = (unsigned int)calloc(SIZE_8KB + 8,sizeof(int));
+ descript_addr = (struct DMA_DES_FMT1 *)(descript_chan[ch].despstack_0.addr_base);
+ descript_addr += (descript_chan[ch].despstack_0.length - 1);
+ descript_addr->BRADDR = descript_chan[ch].despstack_0.addr_base;
+ descript_addr->REQCNT |= DMA_FORMAT_DES1;
+ descript_addr = (struct DMA_DES_FMT1 *)(descript_chan[ch].despstack_1_2.addr_base);
+ descript_addr += (descript_chan[ch].despstack_1_2.length - 1);
+ descript_addr->BRADDR = descript_chan[ch].despstack_1_2.addr_base;
+ descript_addr->REQCNT |= DMA_FORMAT_DES1;
+
+ descript_chan[ch].despstack_0.length = 1024;
+ descript_chan[ch].despstack_1_2.length = 1024;
+ descript_chan[ch].despstack_0.cur_index = 0;
+ descript_chan[ch].despstack_1_2.cur_index = 0;
+ descript_chan[ch].despstack_0.head_index = 0;
+ descript_chan[ch].despstack_1_2.head_index = 0;
+ descript_chan[ch].despstack_0.freedesp_num = 1024;
+ descript_chan[ch].despstack_1_2.freedesp_num = 1024;
+ descript_chan[ch].despstack_0.mem_startaddr = 0;
+ descript_chan[ch].despstack_1_2.mem_startaddr = 0;
+ descript_chan[ch].despstack_0.mem_length = 0;
+ descript_chan[ch].despstack_1_2.mem_length = 0;
+}
+
+void reset_descriptstack(unsigned int ch)
+{
+ //descript_chan[ch].despstack_0.length = 1024;
+ //descript_chan[ch].despstack_1_2.length = 1024;
+ descript_chan[ch].despstack_0.cur_index = 0;
+ descript_chan[ch].despstack_1_2.cur_index = 0;
+ descript_chan[ch].despstack_0.head_index = 0;
+ descript_chan[ch].despstack_1_2.head_index = 0;
+ descript_chan[ch].despstack_0.freedesp_num = 1024;
+ descript_chan[ch].despstack_1_2.freedesp_num = 1024;
+ descript_chan[ch].despstack_0.mem_startaddr = 0;
+ descript_chan[ch].despstack_1_2.mem_startaddr = 0;
+ descript_chan[ch].despstack_0.mem_length = 0;
+ descript_chan[ch].despstack_1_2.mem_length = 0;
+}
+
+void free_descriptstack(unsigned int ch)
+{
+ free((unsigned long *)(descript_chan[ch].despstack_0.addr_base));
+ free((unsigned long *)(descript_chan[ch].despstack_1_2.addr_base));
+}
+
+int set_descript(struct desp_stack * pdesp_stack, unsigned int start_addr, unsigned int size)
+{
+ unsigned int need_descriptcnt;
+ unsigned int residue_size;
+ unsigned int i;
+ struct DMA_DES_FMT0 *descript_addr;
+
+ if(size == 0){
+ printf("ERROR: zero bytes is requested!\n");
+ return 0;
+ }
+
+ need_descriptcnt = size/SIZE_32KB;
+ residue_size = size%SIZE_32KB;
+
+ if(need_descriptcnt >= pdesp_stack->freedesp_num)
+ {
+ need_descriptcnt = pdesp_stack->freedesp_num;
+ }
+ if(size > need_descriptcnt * SIZE_32KB && need_descriptcnt != 0)
+ {
+ pdesp_stack->mem_startaddr = start_addr + need_descriptcnt * SIZE_32KB;
+ pdesp_stack->mem_length = size - need_descriptcnt * SIZE_32KB;
+ }
+ else
+ {
+ pdesp_stack->mem_startaddr = 0;
+ pdesp_stack->mem_length = 0;
+ }
+ //printf("residue = %x\n", pdesp_stack->mem_length);
+ descript_addr = (struct DMA_DES_FMT0 *)(pdesp_stack->addr_base);
+ if(pdesp_stack->cur_index == 0)
+ {
+ descript_addr += (pdesp_stack->length - 1);
+ }
+ else
+ {
+ descript_addr += (pdesp_stack->cur_index - 1);
+ }
+ descript_addr->REQCNT &= ~(DMA_DES_END|DMA_INTEN_DES);
+ if(pdesp_stack->cur_index == 0)
+ {
+ descript_addr -= (pdesp_stack->length - 1);
+ }
+ else
+ {
+ ++descript_addr;;
+ }
+
+ pdesp_stack->head_index = pdesp_stack->cur_index;
+
+ for (i = 0; i < need_descriptcnt; ++i) {
+ descript_addr->REQCNT |= SIZE_32KB;
+ if(pdesp_stack->cur_index == (pdesp_stack->length - 1))
+ {
+ descript_addr->REQCNT |= DMA_FORMAT_DES1;
+ descript_addr = (struct DMA_DES_FMT0 *)(pdesp_stack->addr_base);
+ pdesp_stack->cur_index = 0;
+ }
+ else
+ {
+ ++descript_addr;
+ pdesp_stack->cur_index ++;
+ }
+ descript_addr->DATAADDR = start_addr + i * SIZE_32KB;
+ pdesp_stack->freedesp_num--;
+ }
+
+ if (residue_size != 0 && pdesp_stack->freedesp_num > 0) {
+ descript_addr->REQCNT |= (DMA_DES_END|DMA_INTEN_DES|residue_size);
+ if(pdesp_stack->cur_index == (pdesp_stack->length - 1))
+ {
+ descript_addr->REQCNT |= DMA_FORMAT_DES1;
+ pdesp_stack->cur_index = 0;
+ }
+ else
+ {
+ pdesp_stack->cur_index ++;
+ }
+ descript_addr->DATAADDR = start_addr + i * SIZE_32KB;
+ pdesp_stack->freedesp_num--;
+ need_descriptcnt ++;
+ }
+ else
+ {
+ if(pdesp_stack->cur_index == 0){
+ descript_addr = (struct DMA_DES_FMT0 *)(pdesp_stack->addr_base);
+ descript_addr += (pdesp_stack->length - 1);
+ }
+ else{
+ descript_addr --;
+ }
+ descript_addr->REQCNT |= DMA_DES_END|DMA_INTEN_DES;
+ }
+ return need_descriptcnt;
+}
+
+int handle_transfer(unsigned long ch, unsigned long dma_ptr1, unsigned long dma_ptr2, unsigned long size)
+{
+ int count ;
+ int residue_count;
+ int des_cnt;
+ struct DMA_INFO *dma ;
+ enum dma_device dev_no ;
+ int firststart;
+
+ firststart = 1;
+ dma = &dma_chan[ch] ;
+
+ if (size == 0)
+ return -1 ;
+
+ dev_no = dma->device_no;
+ count = size;
+ residue_count = size;
+ do{
+ des_cnt = set_descript(&(descript_chan[ch].despstack_0), dma_ptr1, residue_count);
+ printf("residue ch%d = %x\n", ch, descript_chan[ch].despstack_0.mem_length);
+ dma->descript_cnt += des_cnt;
+ descript_chan[ch].DES_0 = descript_chan[ch].despstack_0.addr_base + descript_chan[ch].despstack_0.head_index * DMA_DES0_SIZE;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH = descript_chan[ch].DES_0;
+ dma->descript_cnt = set_descript(&descript_chan[ch].despstack_1_2, dma_ptr2, count);
+ //printf("Stack 1 Base ch%d = %x\n", ch, descript_chan[ch].despstack_1_2.addr_base);
+ descript_chan[ch].DES_1_2 = descript_chan[ch].despstack_1_2.addr_base + descript_chan[ch].despstack_1_2.head_index * DMA_DES0_SIZE;
+ dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH = descript_chan[ch].DES_1_2;
+ if(firststart){
+ dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_RUN);
+ dma->regs->DMA_CCR_CH[ch] |= SYSTEM_DMA_RUN;
+ firststart = 0;
+ }
+ else
+ {
+ dma->regs->DMA_CCR_CH[ch] |= DMA_WAKE;
+ }
+ //printf("IF0CPR ch%d = %x\n", ch, dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF0CPR_CH);
+ // printf("IF1CPR ch%d = %x\n", ch, dma->mem_regs->MEM_REG_GROUP[ch].DMA_IF1CPR_CH);
+
+ //printf("DMA%d : handle irq begin\n", ch);
+ handle_dma_irq(ch);
+ descript_chan[ch].despstack_0.head_index += dma->descript_cnt;
+ descript_chan[ch].despstack_0.freedesp_num += dma->descript_cnt;
+ descript_chan[ch].despstack_1_2.head_index += dma->descript_cnt;
+ descript_chan[ch].despstack_1_2.freedesp_num += dma->descript_cnt;
+ //printf("DMA%d : handle irq OK\n", ch);
+ while (1) {
+ if (dma_busy(ch) != 1)
+ break;
+ }
+ //printf("DMA%d : no busy\n", ch);
+ while (1) {
+ if (dma_complete(ch) == 0)
+ break;
+ }
+ }
+ while(descript_chan[ch].despstack_0.mem_length > 0);
+
+ return 0;
+}
diff --git a/cpu/arm920t/wmt/ether.c b/cpu/arm920t/wmt/ether.c new file mode 100755 index 0000000..aafad9e --- /dev/null +++ b/cpu/arm920t/wmt/ether.c @@ -0,0 +1,85 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <common.h> +#include <asm/io.h> +#include <net.h> +#include <miiphy.h> +#include "macif.h" +#include "mac.h" +#include "alloct.h" +#include <asm/u-boot.h> +#include <configs/wmt.h> + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/****************************************************************************** + * + * Public u-boot interface functions below + * + *****************************************************************************/ +int eth_init(bd_t *bd) +{ + return mac_startio(bd); + } + +int eth_send(volatile void *packet, int length) +{ + return mac_send(packet,length); +} + +int eth_rx(void) +{ + return mac_receive(); +} + +void eth_halt(void) +{ + mac_halt(); + return; +} + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +int wmt_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + mii_read(devname, addr, reg, value); + return 0; +} + +int wmt_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + mii_write(devname, addr, reg, value); + return 0; +} + +#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */ + +int wmt_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + /* miiphy_register("wmtphy", wmt_miiphy_read, wmt_miiphy_write); */ +#endif + return 0; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm920t/wmt/gadapter.c b/cpu/arm920t/wmt/gadapter.c new file mode 100755 index 0000000..1615b0b --- /dev/null +++ b/cpu/arm920t/wmt/gadapter.c @@ -0,0 +1,631 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__UPCI_H__) +#include "upci.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__GISR_H__) +#include "gisr.h" +#endif +#if !defined(__VPCI_H__) +#include "vpci.h" +#endif +#if !defined(__TCONVERT_H__) +#include "tconvert.h" +#endif +#if !defined(__ALLOCT_H__) +#include "alloct.h" +#endif + +#include "macif.h" + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +static void s_vInit( + PSAdapterInfo pAdapter, + UINT uTotalNum, + UINT uIdx, + PISR pisrNetIsr, + WORD wBusDevFunID + ); +/*--------------------- Export Variables --------------------------*/ +PSAdapterInfo sg_aGAdapter; +SAdapterOpts sOptions = {0, 0, 0, 0, 0, 0}; +PBYTE sg_abyRandomTable; + +/*--------------------- Export Functions --------------------------*/ +/* Init all adapter's AdapterInfo data structure */ +UINT GADPuInitAll(void) +{ + PISR apisrNetProc[MAX_NET_DEVICE] = { + (PISR)ISRvIsrForNetwork_Card0, + (PISR)ISRvIsrForNetwork_Card1, + (PISR)ISRvIsrForNetwork_Card2, + (PISR)ISRvIsrForNetwork_Card3 + }; + + SPciDevice pciDevice3119; + SPciDevice pciDevice3286; + + int ii; + U16 u16IdxPciDev; + U16 u16TotalPciDev; + + /* read pci info */ + /* + NPCIbReadDeviceInfo(NULL, W_VENDOR_ID, W_DEVICE_ID_3119A, &pciDevice3119); + NPCIbReadDeviceInfo(NULL, W_VENDOR_ID, 0x3286, &pciDevice3286); + */ + memset(&pciDevice3119, 0, sizeof(SPciDevice)); + memset(&pciDevice3286, 0, sizeof(SPciDevice)); + pciDevice3119.wDeviceNum = CB_MAX_NET_DEVICE; + pciDevice3286.wDeviceNum = 0; + + u16TotalPciDev = (U16)(pciDevice3119.wDeviceNum + pciDevice3286.wDeviceNum); + + if (u16TotalPciDev == 0) + return 0; + + sg_aGAdapter = (PSAdapterInfo)malloc(sizeof(SAdapterInfo)*u16TotalPciDev); + if (sg_aGAdapter == NULL) { + printf("Memory allocation error %s, %d\n", __FILE__, __LINE__); + freemem(); + return 0; + } + memset(sg_aGAdapter, 0, sizeof(SAdapterInfo)*u16TotalPciDev); + + /* set adapter info */ + u16IdxPciDev = 0; + for (ii = 0; ii < pciDevice3119.wDeviceNum; ii++, u16IdxPciDev++) { + s_vInit( + &sg_aGAdapter[u16IdxPciDev], + u16TotalPciDev, + u16IdxPciDev, + apisrNetProc[u16IdxPciDev], + pciDevice3119.awBusDevFunID[ii] + ); + } + + for (ii = 0; ii < pciDevice3286.wDeviceNum; ii++, u16IdxPciDev++) { + s_vInit( + &sg_aGAdapter[u16IdxPciDev], + u16TotalPciDev, + u16IdxPciDev, + apisrNetProc[u16IdxPciDev], + pciDevice3286.awBusDevFunID[ii] + ); + } + + return u16TotalPciDev; +} + +/* + * Description: + * + * Parameters: + * In: + * bySlotNum - specify which slot number to init, + * 0xFF means the first one adapter to init. + * Out: + * pAdapter - pointer of adapter which initialized, + * return NULL if init failed. + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL GADPbInitOne(U8 bySlotNum, PSAdapterInfo *ppAdapter) +{ + PISR apisrNetProc[MAX_NET_DEVICE] = { + (PISR)ISRvIsrForNetwork_Card0, + (PISR)ISRvIsrForNetwork_Card1 + }; + + SPciDevice pciDevice3119; + /* SPciDevice pciDevice3286; */ + + int ii; + U16 u16IdxPciDev; + U16 u16TotalPciDev; + + *ppAdapter = NULL; + + /* read pci info */ + NPCIbReadDeviceInfo(NULL, W_VENDOR_ID, W_DEVICE_ID_3119A, &pciDevice3119); + /* NPCIbReadDeviceInfo(NULL, W_VENDOR_ID, 0x3286, &pciDevice3286); */ + + u16TotalPciDev = (U16)(pciDevice3119.wDeviceNum); + + /* if no adapter */ + if (u16TotalPciDev == 0) + return FALSE; + + sg_aGAdapter = (PSAdapterInfo) malloc(sizeof(SAdapterInfo)); + if (sg_aGAdapter == NULL) { + printf("Memory allocation error %s, %d\n", __FILE__, __LINE__); + return FALSE; + /* exit(0); */ + } + + memset(sg_aGAdapter, 0, sizeof(SAdapterInfo)); + + /* init first one adapter */ + if (bySlotNum == 0xFF) { + s_vInit(&sg_aGAdapter[0], u16TotalPciDev, 0, + apisrNetProc[0], pciDevice3119.awBusDevFunID[0]); + *ppAdapter = &sg_aGAdapter[0]; + return TRUE; + } else { + /* init adapter by slot number specified */ + u16IdxPciDev = 0; + for (ii = 0; ii < pciDevice3119.wDeviceNum; ii++, u16IdxPciDev++) { + if (bySlotNum == GET_DEVID(pciDevice3119.awBusDevFunID[ii])) { + s_vInit( + &sg_aGAdapter[u16IdxPciDev], + u16TotalPciDev, + u16IdxPciDev, + apisrNetProc[u16IdxPciDev], + pciDevice3119.awBusDevFunID[ii] + ); + *ppAdapter = &sg_aGAdapter[u16IdxPciDev]; + return TRUE; + } + } + } + + return FALSE; +} + +static BOOL s_bDynaAllocBuf(PSAdapterInfo pAdapter) +{ + int i; + + /* Allocate RD pointer array */ + pAdapter->apRD = (PSRxDesc *)malloc(sizeof(PSRxDesc)*pAdapter->cbRD); + + if (pAdapter->apRD == NULL) + return FALSE; + + /* Allocate TD pointer array & DescBuf SAllocMap array for every TD ring. */ + /* we allocate 7 SAllocMap for 7 data buffer pool. */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + pAdapter->aapTD[i] = (PSTxDesc *)malloc(sizeof(PSTxDesc)*pAdapter->cbTD); + pAdapter->aaamTxDescBufPool[i] = (PSAllocMap)malloc(sizeof(SAllocMap)*CB_MAX_SEG_PER_PKT); + + if ((pAdapter->aapTD[i] == NULL) || (pAdapter->aaamTxDescBufPool[i] == NULL)) + return FALSE; + + memset(pAdapter->aaamTxDescBufPool[i], 0, sizeof(SAllocMap)*CB_MAX_SEG_PER_PKT); + } + + return TRUE; +} + +/* Init pAdapter data structure */ +static void s_vInit( + PSAdapterInfo pAdapter, + UINT uTotalNum, + UINT uIdx, + PISR pisrNetIsr, + WORD wBusDevFunID +) +{ + /* allocate new buffer dynamically. */ + pAdapter->cbTotalAdapterNum = uTotalNum; + pAdapter->uAdapterIndex = uIdx; + pAdapter->pisrAdapterIsr = pisrNetIsr; + + /* Save Memory Mapped IO base address */ + switch (uIdx) { + case 0: + pAdapter->dwIoBase = BA_MAC0; + break; + + case 1: + pAdapter->dwIoBase = BA_MAC1; + break; + + default: + break; + } + + /* Get Device ID */ + VPCIvReadW(pAdapter->dwIoBase, PCI_REG_DEVICE_ID, &pAdapter->wDeviceId); + /* MacDump( MACDBG_INFO, ("Device ID:%04X\n", pAdapter->wDevId)); */ + + /* Get Revision ID */ + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_REV_ID, &pAdapter->byRevId); + /* MacDump( MACDBG_INFO, ("Revision ID:%02X\n", pAdapter->byRevId)); */ + + /* Save IRQ number */ + switch (uIdx) { + case 0: + pAdapter->byIrqLevel = IRQ_ETH0; + break; + + case 1: + pAdapter->byIrqLevel = IRQ_ETH0; + break; + + default: + break; + } + + if (sOptions.byRevId != 0) + pAdapter->byRevId = sOptions.byRevId; + + pAdapter->cbRD = (sOptions.iRDescNum) ? sOptions.iRDescNum : CB_INIT_RD_NUM; + pAdapter->cbTD = (sOptions.iTDescNum) ? sOptions.iTDescNum : CB_INIT_TD_NUM; + + VPCIvReadD(pAdapter->dwIoBase, PCI_REG_EXP_ROM_BAR, &pAdapter->dwBootRomBase); + + /* PCIvReadConfigB(NULL, pAdapter->wBusDevFunID, PCI_REG_INT_LINE, &pAdapter->byIrqLevel); */ + /* PCIvReadConfigD(NULL, pAdapter->wBusDevFunID, PCI_REG_EXP_ROM_BAR, &pAdapter->dwBootRomBase); */ + + pAdapter->byIntNum = (BYTE)((pAdapter->byIrqLevel <= 7) ? + (pAdapter->byIrqLevel + 0x08) : (pAdapter->byIrqLevel + 0x68)); + + /* Get the offset of PM Capability and save it */ + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_CAP, &pAdapter->byPMRegOffset); + + /* Get Boot ROM Size */ + pAdapter->byBootRomSize = GMACbyGetBootRomSize(pAdapter->dwIoBase); + + /* Get PHY ID */ + pAdapter->byPhyId = GMACbyGetPhyId(pAdapter->dwIoBase); + + /* get Ethernet address and the string */ + MACvReadEtherAddress(pAdapter->dwIoBase, pAdapter->abyEtherAddr); + CVTvBy6ToStr12(pAdapter->abyEtherAddr, pAdapter->aszEtherAddrStr); + + /* + * INIT VALUE + */ + /* allocate RD/TD poiter array & DescBuf array data structure */ + if (!s_bDynaAllocBuf(pAdapter)) { + printf("s_bDynaAllocBuf() can'nt allocate buffer"); + freemem(); + return ; + } + /* for TD/RD alignment */ + pAdapter->dwCacheLineSize = sizeof(DWORD) * 16; /* 64 bytes */ + + /* init pAdapter->bSharedIrqSupport */ + pAdapter->bSharedIrqSupport = TRUE; + + /* set connection type to MEDIA_AUTO by default */ + pAdapter->uConnectionType = MEDIA_AUTO; + + /* init default data segment number per packet in monitor mode */ + pAdapter->uTxDataSegsPerPacket = CB_MIN_SEG_PER_PKT; + + /* init default Tx packet size */ + pAdapter->uTxPktSize = MAX_PACKET_LEN;/* MIN_PACKET_LEN + 4; */ + pAdapter->cbPktSize = MAX_PACKET_LEN; + /* init MIB2 counter */ + strcpy(pAdapter->mibCounter.ifDescr, " Gigabit Ether"); + + pAdapter->mibCounter.ifType = ETHERNETCSMACD; + pAdapter->mibCounter.ifMtu = MAX_DATA_LEN; + MEMvCopy((PVOID)pAdapter->mibCounter.ifPhysAddress, (PVOID)pAdapter->abyEtherAddr, U_ETHER_ADDR_LEN); + pAdapter->mibCounter.ifAdminStatus = UP; + + /* init RMON counter */ + pAdapter->rmonCounter.etherStatsStatus = VALID; + + /* background timer send as default */ + pAdapter->bTxContFunTest = TRUE; + + /* init packet driver */ + pAdapter->wRcvTypeLen = 0; + pAdapter->pisrReceiver = NULL; +} + +BOOL GADPbInitialize(PSAdapterInfo pAdapter) +{ + int i; + /* write-clear PME status bit */ + BYTE byOrgData, byPMRegOffset; + /* fill default value */ + GALCvSetDefaultRD(pAdapter); + GALCvSetDefaultTD(pAdapter, 0); /* initial first data segment */ + /* init PCI */ + /* NPCIvInitialize(NULL, pAdapter->wBusDevFunID, pAdapter->byRevId); */ + VPCIvInitialize(pAdapter->dwIoBase, pAdapter->byRevId); + + VPCIvReadB(pAdapter->dwIoBase, PCI_REG_CAP, &byPMRegOffset); + VPCIvReadB(pAdapter->dwIoBase, (BYTE)(byPMRegOffset + PM_PMCSR1), &byOrgData); + VPCIvWriteB(pAdapter->dwIoBase, (BYTE)(byPMRegOffset + PM_PMCSR1), + (BYTE)(PMCSR1_PME_STATUS | byOrgData)); + /* + PCIvReadConfigB(NULL, pAdapter->wBusDevFunID, PCI_REG_CAP, &byPMRegOffset); + PCIvReadConfigB(NULL, pAdapter->wBusDevFunID, (BYTE)(byPMRegOffset + PM_PMCSR1), &byOrgData); + PCIvWriteConfigB(NULL, pAdapter->wBusDevFunID, (BYTE)(byPMRegOffset + PM_PMCSR1), + (BYTE)(PMCSR1_PME_STATUS | byOrgData)); + */ + if (!sOptions.bNoInit) { + + /* init MAC */ + GMACvInitialize(pAdapter, pAdapter->dwIoBase, pAdapter->byRevId); + /* set address filter to accept any packet */ + /* 2009/4/20 remove it for tftp with checksum bad message */ + /* GMACvSetPacketFilter(pAdapter->dwIoBase, PKT_TYPE_PROMISCUOUS); */ + + /* Eric */ + /* Turn On RCR_SEP to receive CRC error packet */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_RCR, RCR_SEP); + + /* detect PHY is from which company */ + /* MIIvReadPhyCmrId(pAdapter->dwIoBase, pAdapter->byRevId, &pAdapter->dwPhyCmrId); */ + + if (sOptions.ulInitCmds & INIT_CMD_FORCE_PHYRST) { + /* if it's cicada PHY, force PHY reset to avoid 2-card test link fail */ + + if ((pAdapter->dwPhyCmrId & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS8201 || + (pAdapter->dwPhyCmrId & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS3216I || + (pAdapter->dwPhyCmrId & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS3216I64) { + /* force PHY reset on */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_SET, CR3_FPHYRST); + /* delay 300ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 300); + /* force PHY reset off */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_CLR, CR3_FPHYRST); + /* delay 50ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 50); + } else if ((pAdapter->dwPhyCmrId & CID_REV_ID_MASK_OFF) == CID_ICPLAUS_IP1001) { + /* force PHY reset on */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_SET, CR3_FPHYRST); + /* delay 300ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 300); + /* force PHY reset off */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_CLR, CR3_FPHYRST); + /* delay 50ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 50); + } else { + /* force PHY reset on */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_SET, CR3_FPHYRST); + /* delay 300ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 300); + /* force PHY reset off */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_CR3_CLR, CR3_FPHYRST); + /* delay 50ms */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 50); + } + } + + /* init MII */ + GMIIvInitialize(pAdapter->dwIoBase, pAdapter->byRevId, pAdapter->dwPhyCmrId); + + /* set media mode */ + GCARDvSetLoopbackMode(pAdapter->dwIoBase, pAdapter->byRevId, CARD_LB_NONE); + GCARDvSetMediaLinkMode(pAdapter->dwIoBase, pAdapter->byRevId, pAdapter->uConnectionType); + + /* set up flow-control, MIB counter, and tagging initials */ + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_RBRDU, (BYTE)pAdapter->cbRD); + + /* set MIB counter near full condition to 0x00C00000 */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_MIBCR, MIBCR_MIBHI); + + GSTAvClearHWMIBCounter(pAdapter->dwIoBase); + GSTAvEnableHWMIBCounter(pAdapter->dwIoBase); + + MACvRegBitsOff(pAdapter->dwIoBase, MAC_REG_MCFG0, MCFG0_PQEN); + } + + /* set init rx/tx descriptor address into chip */ + MACvSetDescBaseHi32(pAdapter->dwIoBase, 0UL); + MACvSetDbfBaseHi16(pAdapter->dwIoBase, 0U); + MACvSetRxDescBaseLo32(pAdapter->dwIoBase, pAdapter->amRxDescRing.dwPAddr); + MACvSetRqIndex(pAdapter->dwIoBase, 0); + MACvSetRqSize(pAdapter->dwIoBase, (WORD)(pAdapter->cbRD - 1)); + + for (i = 0; i < CB_TD_RING_NUM; i++) { + MACvSetTxDescBaseLo32(pAdapter->dwIoBase, pAdapter->aamTxDescRing[i].dwPAddr, i); + GMACvSetTqIndex(pAdapter->dwIoBase, (BYTE)i, 0); + } + + MACvSetTqSize(pAdapter->dwIoBase, (WORD)(pAdapter->cbTD - 1)); + + /* set current rx/tx descriptor index to 0 */ + pAdapter->uRxDequeDescIdx = 0; + for (i = 0; i < CB_TD_RING_NUM; i++) { + pAdapter->uTxEnqueDescIdx[i] = 0; + pAdapter->uTxDequeDescIdx[i] = 0; + } + pAdapter->idxRxPktStartDesc = 0; + /* + // Set Random VCAM + + WORD wInitVID; + WORD wGetVID; + int ii; + for (i = 0; i < VCAMSIZE; i++) { + while (TRUE) { + wInitVID = (WORD)(rand() & 0x0FFF); + + if (i > 0) { + for (ii = 0; ii < i; ii++) { + GMACvGetVCAM(pAdapter->dwIoBase, (BYTE)ii, &wGetVID); + if (wInitVID == wGetVID) + break; + } + if (i == ii) + break; + } else + break; + } // end while + + GMACvSetVCAM(pAdapter->dwIoBase, (BYTE)i, wInitVID); + } + */ + /* Set Random MCAM */ + /* + BYTE abyInitMCAM[6]; + BYTE abyGetMCAM[6]; + UINT uMCamIdx; + for (i = 0; i < MCAMSIZE; i++) { + while (TRUE) { + // Gen One MCAM + for (uMCamIdx = 0; uMCamIdx < 6; uMCamIdx++) + abyInitMCAM[uMCamIdx] = (BYTE)rand(); + + if (i > 0) { + for (ii = 0; ii < i; ii++) { + GMACvGetMCAM(pAdapter->dwIoBase, (BYTE)ii, abyGetMCAM); + // If they are the same?? + if ( (*(PDWORD)(abyInitMCAM) == *(PDWORD)(abyGetMCAM)) && + (*(PWORD)(abyInitMCAM + 4) == *(PWORD)(abyGetMCAM + 4)) ) + break; + } + if (i == ii) + break; + } else + break; + } // end while + + GMACvSetMCAM(pAdapter->dwIoBase, (BYTE)i, abyInitMCAM); + } + */ + return TRUE; +} + +BOOL GADPbBind(PSAdapterInfo pAdapter) +{ + /* build RDR/TDR */ + if (!GALCbAllocateRdrMemory(pAdapter)) + return FALSE; + + if (!GALCbAllocateTdrMemory(pAdapter)) + return FALSE; + + GALCvChainRdrMemory(pAdapter); + GALCvChainTdrMemory(pAdapter, 0); /* chain first data segment */ + + if (!GADPbInitialize(pAdapter)) + return FALSE; + + /* Hook Interrupt Service Routine on IRQ */ + /* set_irq_handlers(pAdapter->byIrqLevel, pAdapter->pisrAdapterIsr); */ + + /* enable Interrupt Mask in PIC */ + /* unmask_interrupt(pAdapter->byIrqLevel); */ + /* must clear it */ + MACvClearISR(pAdapter->dwIoBase, pAdapter->byRevId); + /* start ISR */ + MACvIntEnable(pAdapter->dwIoBase, IMR_MASK_VALUE); + + /* wait MAUTO to poll twice, then MIISR_LNKFL will */ + /* be correct status */ + PCAvDelayByIO(CB_DELAY_MII_STABLE * 2); + + /* update link status */ + GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 2000); + pAdapter->bLinkPass = GMACbIsCableLinkOk(pAdapter->dwIoBase); + + if (pAdapter->bLinkPass) { + /* update duplex status */ + /* NOTE.... here we don't call MIIbIsInFullDuplexMode(), because */ + /* we won't turn on/off MAUTO */ + pAdapter->bFullDuplex = GMACbIsInFullDuplexMode(pAdapter->dwIoBase); + /* update speed status */ + pAdapter->bSpeed1G = GMACbIsIn1GMode(pAdapter->dwIoBase, pAdapter->byRevId); + pAdapter->bSpeed100M = GMACbIsIn100MMode(pAdapter->dwIoBase, pAdapter->byRevId); + + /* set flow control capability according to PHYSR0 register */ + if (GMIIbIsAutoNegotiationOn(pAdapter->dwIoBase, pAdapter->byRevId)) { + /* enable/disable RX flow control */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_PHYSR0, PHYSR0_RXFLC)) + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_SET, CR2_FDXRFCEN); + else + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_CLR, CR2_FDXRFCEN); + + /* enable/disable TX flow control */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_PHYSR0, PHYSR0_TXFLC)) + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_SET, CR2_FDXTFCEN); + else + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_CLR, CR2_FDXTFCEN); + } + + /* This is patch for VT3119A1 */ + /* Use TCR_TB2BDIS to prevent 1c_Reset failure in helf-duplex mode */ + /* Only use this in 10HD and 100HD */ + if (pAdapter->byRevId < REV_ID_VT3216_A0) { + if (!pAdapter->bSpeed1G) { + if (pAdapter->bFullDuplex) + MACvRegBitsOff(pAdapter->dwIoBase, MAC_REG_TCR, TCR_TB2BDIS); + else + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_TCR, TCR_TB2BDIS); + } + } + + /* This is patch for VT3119/VT3216 */ + /* Patch HW MIB TXSQEErr Bug, this should only function in 10HD */ + if (pAdapter->byRevId < REV_ID_VT3284_A0) { + if ((!pAdapter->bSpeed1G) && (!pAdapter->bSpeed100M) && (!pAdapter->bFullDuplex)) { + /* Enable count TXSQEErr in 10HD */ + MACvRegBitsOff(pAdapter->dwIoBase, MAC_REG_TESTCFG, 0x80); + } else { + /* Disable count TXSQEErr in 10FD, 100HD, 100FD, 1G */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_TESTCFG, 0x80); + } + } + + } + + /*pAdapter->pbyTmpBuff = (PBYTE)malloc(CB_MAX_BUF_SIZE);*/ + +#if defined(_RUN_SCRIPT) + pAdapter->mempool = malloc(U_STACKSIZE); +#endif + + return TRUE; +} + +BOOL GADPbShutdown(PSAdapterInfo pAdapter) +{ + /* stop chip */ + if (!GMACbSafeStop(pAdapter->dwIoBase, pAdapter->byRevId)) + return FALSE; + + /* stop MAC INT */ + MACvIntDisable(pAdapter->dwIoBase); + + /* stop ISR */ + /* mask_interrupt(pAdapter->byIrqLevel); */ + + /* disconnect irq and restore org ISR */ + /* unset_irq_handlers(pAdapter->byIrqLevel); */ + + /* destroy RDR/TDR */ + GALCvFreeRdrMemory(pAdapter); + GALCvFreeTdrMemory(pAdapter); + + if (pAdapter->pbyTmpBuff != NULL) { + MEMvFree(pAdapter->pbyTmpBuff, CB_MAX_BUF_SIZE); + pAdapter->pbyTmpBuff = NULL; + } + + return TRUE; +} diff --git a/cpu/arm920t/wmt/galloct.c b/cpu/arm920t/wmt/galloct.c new file mode 100755 index 0000000..12ec543 --- /dev/null +++ b/cpu/arm920t/wmt/galloct.c @@ -0,0 +1,349 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__ALLOCT_H__) +#include "alloct.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +static BOOL ALCbAllocateTdrBufferPool(PSAdapterInfo pAdapter, SAllocMap asMaps[], UINT cbTD, int iSegNo) +{ + /* asMaps[iSegNo].dwRawSize = CB_MAX_BUF_SIZE*cbTD + pAdapter->dwCacheLineSize; */ + /* asMaps[iSegNo].dwSize = CB_MAX_BUF_SIZE*cbTD; */ + asMaps[iSegNo].dwRawSize = MAX_PACKET_LEN*cbTD + pAdapter->dwCacheLineSize; + asMaps[iSegNo].dwSize = MAX_PACKET_LEN*cbTD; + GMEMvAllocateShared(&asMaps[iSegNo]); + + if (asMaps[iSegNo].dwRawVAddr == 0) + return FALSE; + + /* make data buf 4 dwords alignment for convenience */ + /* MEMvAlign(&asMaps[iSegNo], 16); */ + + /* Tx buffers, make it byte-alignment */ + if (asMaps[iSegNo].dwRawVAddr % 2 != 0) { + asMaps[iSegNo].dwVAddr = asMaps[iSegNo].dwRawVAddr + 1; + asMaps[iSegNo].dwPAddr = LODWORD(asMaps[iSegNo].qwRawPAddr) + 1; + } else { + asMaps[iSegNo].dwVAddr = asMaps[iSegNo].dwRawVAddr; + asMaps[iSegNo].dwPAddr = LODWORD(asMaps[iSegNo].qwRawPAddr); + } + + return TRUE; +} + +/*--------------------- Export Variables --------------------------*/ +PVOID +GMEMvAllocate( + UINT uCount + ) +{ + PVOID pvMemAddr; + + pvMemAddr = g_pvGBufferIndex; + g_pvGBufferIndex += uCount; + return pvMemAddr; +} +VOID +GMEMvAllocateShared( + PSAllocMap pamMem + ) +{ + /* printf("pamMem->dwRawVAddr1 = %x\n",pamMem->dwRawVAddr); */ + pamMem->dwRawVAddr = (DWORD)GMEMvAllocate((size_t)pamMem->dwRawSize * (size_t)sizeof(BYTE)); + /* If allocation failed, virtual/phisical address == NULL */ + if ((PVOID)pamMem->dwRawVAddr == NULL) { + LODWORD(pamMem->qwRawPAddr) = 0; + HIDWORD(pamMem->qwRawPAddr) = 0; + return; + } + /* + else { + memset((PVOID)pamMem->dwRawVAddr, 0, (size_t)pamMem->dwRawSize * (size_t)sizeof(BYTE)); + } + */ + LODWORD(pamMem->qwRawPAddr) = pamMem->dwRawVAddr; + HIDWORD(pamMem->qwRawPAddr) = 0; +} + +BOOL GALCbAllocateRdrMemory(PSAdapterInfo pAdapter) +{ + /* Allocate the Receive Descriptor ring */ + /* (Physically contiguous and non cached) */ + pAdapter->amRxDescRing.dwRawSize = sizeof(SRxDesc) * pAdapter->cbRD + pAdapter->dwCacheLineSize; + pAdapter->amRxDescRing.dwSize = sizeof(SRxDesc) * pAdapter->cbRD; + GMEMvAllocateShared(&pAdapter->amRxDescRing); + if (pAdapter->amRxDescRing.dwRawVAddr == 0) + return FALSE; + + /* descriptor MUST aligned by 16 dword */ + MEMvAlign(&pAdapter->amRxDescRing, (UINT)pAdapter->dwCacheLineSize); + /* allocate contiguous data buffers for RD ring */ + pAdapter->amRxDescBuf.dwRawSize = CB_MAX_BUF_SIZE*pAdapter->cbRD + pAdapter->dwCacheLineSize; + pAdapter->amRxDescBuf.dwSize = CB_MAX_BUF_SIZE*pAdapter->cbRD; + + GMEMvAllocateShared(&pAdapter->amRxDescBuf); + + if (pAdapter->amRxDescBuf.dwRawVAddr == 0) + return FALSE; + + /* make data buf 4 dwords alignment for convenience */ + MEMvAlign(&pAdapter->amRxDescBuf, 16); + /* MEMvAlign(&pAdapter->amRxDescBuf, 1); //byte alignment */ + + return TRUE; +} + +BOOL GALCbAllocateTdSegMemory(PSAdapterInfo pAdapter, int iSegNo) +{ + int i; + + /* for 4 TD rings */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + if (!ALCbAllocateTdrBufferPool(pAdapter, pAdapter->aaamTxDescBufPool[i], + pAdapter->cbTD, iSegNo)) + return FALSE; + } + + return TRUE; +} + +BOOL GALCbAllocateTdrMemory(PSAdapterInfo pAdapter) +{ + int i; + + /* for 3119 allocating 4 TD rings */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + /* Allocate the transmit descriptor ring */ + /* (Physically contiguous and non cached) */ + pAdapter->aamTxDescRing[i].dwRawSize = + sizeof(STxDesc) * pAdapter->cbTD + pAdapter->dwCacheLineSize; + pAdapter->aamTxDescRing[i].dwSize = sizeof(STxDesc) * pAdapter->cbTD; + + GMEMvAllocateShared(&pAdapter->aamTxDescRing[i]); + + if (pAdapter->aamTxDescRing[i].dwRawVAddr == 0) + return FALSE; + + /* descriptor MUST aligned by 16 dword */ + MEMvAlign(&pAdapter->aamTxDescRing[i], (UINT)pAdapter->dwCacheLineSize); + + /* for 3119, only allocate first data segment buffer pool for each TD queue */ + if (!GALCbAllocateTdSegMemory(pAdapter, 0)) + return FALSE; + } + + return TRUE; +} + +void GALCvChainRdrMemory(PSAdapterInfo pAdapter) +{ + int ii; + PSRxDesc pRD; + DWORD dwBufPAddr; + + /* initialize the receive descriptor poniter array and */ + /* each individual receive descriptor */ + pRD = (PSRxDesc)pAdapter->amRxDescRing.dwVAddr; + dwBufPAddr = pAdapter->amRxDescBuf.dwPAddr; + + for (ii = 0; ii < pAdapter->cbRD; ii++) { + pAdapter->apRD[ii] = pRD; + + /* init descriptor value */ + pRD->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; + pRD->m_f15RxBufSize = (WORD)CB_MAX_BUF_SIZE; + pRD->m_wRxBufAddrHi = LOWORD(HIDWORD(pAdapter->amRxDescBuf.qwRawPAddr)); + pRD->m_dwRxBufAddrLo = dwBufPAddr; + pRD->m_f1IntCtlEn = 1; /* enable RIC */ + + /* (PBYTE)pRD += sizeof(SRxDesc); */ + pRD = (PSRxDesc)(pAdapter->amRxDescRing.dwVAddr + sizeof(SRxDesc)*(ii+1)); + dwBufPAddr = pAdapter->amRxDescBuf.dwPAddr + CB_MAX_BUF_SIZE*(ii+1); + } +} + +void dumprd(PSAdapterInfo pAdapter) +{ + return; +} + +void GALCvChainTdrMemory(PSAdapterInfo pAdapter, int iSegNo) +{ + int i, ii; + PSTxDesc pTD; + /* DWORD dwBufPAddr; */ + + /* For VT3119 4 TDs */ + /* Initialize the Transmit Descriptor pointer array & */ + /* the tx desc ring */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + pTD = (PSTxDesc)pAdapter->aamTxDescRing[i].dwVAddr; + /* dwBufPAddr = pAdapter->aaamTxDescBufPool[i][iSegNo].dwPAddr; */ + + /* set tx descriptors owner to host(0) */ + /* set TCPLS_SOF = 1, TCPLS_EOF = 1 (normal packet) */ + for (ii = 0; ii < pAdapter->cbTD; ii++) { + pAdapter->aapTD[i][ii] = pTD; + + /* init descriptor value */ + /* init Owner & Que bit */ + pTD->m_td0TD0.f1Owner = B_OWNED_BY_HOST; + pTD->m_asTxBufs[0].f1Que = B_TD_LIST_END; + + pTD->m_td1TD1.byTCR0 = TCR0_TIC; + + pTD->m_td0TD0.f14TxPktSize = MAX_PACKET_LEN; + pTD->m_td1TD1.f2TCPLS = 0x03; + + /* set up data segment */ + pTD->m_td1TD1.f4CMDZ = (BYTE)(iSegNo + 2); + pTD->m_asTxBufs[iSegNo].f14TxBufSize = MAX_PACKET_LEN; + pTD->m_asTxBufs[iSegNo].wTxBufAddrHi = + LOWORD(HIDWORD(pAdapter->aaamTxDescBufPool[i][iSegNo].qwRawPAddr)); + /* pTD->m_asTxBufs[iSegNo].dwTxBufAddrLo = + pAdapter->aaamTxDescBufPool[i][iSegNo].dwPAddr + CB_MAX_BUF_SIZE*ii + (ii % 16); */ + pTD->m_asTxBufs[iSegNo].dwTxBufAddrLo = + pAdapter->aaamTxDescBufPool[i][iSegNo].dwPAddr + MAX_PACKET_LEN*ii + (ii % 16); + + /* (PBYTE)pTD += sizeof(STxDesc); */ + pTD = (PSTxDesc)(pAdapter->aamTxDescRing[i].dwVAddr + sizeof(STxDesc)*(ii+1)); + } + /* printf("addr0 = %x\n",pAdapter->aapTD[0][0]->m_asTxBufs[0].dwTxBufAddrLo); */ + /* printf("addr1 = %x\n",pAdapter->aapTD[0][1]->m_asTxBufs[0].dwTxBufAddrLo); */ + } + + /* init adapter's sturcture also, init value = MAX_PACKET_LEN */ + pAdapter->uTxPktSize = MAX_PACKET_LEN; + +} + +void dumptd(PSAdapterInfo pAdapter) +{ + int data; + int i; + int ii; + for (ii = 0; ii < 32; ii++) { + for (i = 0; i < 0x10; i += 4) { + VNSvInPortD(pAdapter->aamTxDescRing[0].dwVAddr+i+ii*sizeof(STxDesc), &data); + printf("TD %4x:%8x\n", i, data); + } + } + return; +} + +void GALCvFreeRdrMemory(PSAdapterInfo pAdapter) +{ + /* Free the receive descriptor ring. */ + if (pAdapter->amRxDescRing.dwRawVAddr != 0) { + MEMvFreeShared(&pAdapter->amRxDescRing); + pAdapter->amRxDescRing.dwRawVAddr = 0; + } + + /* Free the Receive buffer pool */ + if (pAdapter->amRxDescBuf.dwRawVAddr != 0) { + MEMvFreeShared(&pAdapter->amRxDescBuf); + pAdapter->amRxDescBuf.dwRawVAddr = 0; + } +} + +void GALCvFreeTdrMemory(PSAdapterInfo pAdapter) +{ + int i, ii; + + /* Free all TD Rings */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + if (pAdapter->aamTxDescRing[i].dwRawVAddr != 0) { + MEMvFreeShared(&pAdapter->aamTxDescRing[i]); + pAdapter->aamTxDescRing[i].dwRawVAddr = 0; + } + } + + /* Free the Transmit Buffers */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + for (ii = 0; ii < CB_MAX_SEG_PER_PKT; ii++) { + if (pAdapter->aaamTxDescBufPool[i][ii].dwRawVAddr != 0) { + MEMvFreeShared(&pAdapter->aaamTxDescBufPool[i][ii]); + pAdapter->aaamTxDescBufPool[i][ii].dwRawVAddr = 0; + } + } + } +} + +void GALCvFreeTdSegMemory(PSAdapterInfo pAdapter, int iSegNo) +{ + int i, ii; + + PSTxDesc pTD; + + /* Free the Transmit Buffers for one segment */ + for (i = 0; i < CB_TD_RING_NUM; i++) { + pTD = (PSTxDesc)pAdapter->aamTxDescRing[i].dwVAddr; + + if (pAdapter->aaamTxDescBufPool[i][iSegNo].dwRawVAddr != 0) { + MEMvFreeShared(&pAdapter->aaamTxDescBufPool[i][iSegNo]); + pAdapter->aaamTxDescBufPool[i][iSegNo].dwRawVAddr = 0; + } + + for (ii = 0; ii < pAdapter->cbTD; ii++) { + pTD->m_asTxBufs[iSegNo].f14TxBufSize = 0; + pTD->m_asTxBufs[iSegNo].wTxBufAddrHi = 0; + pTD->m_asTxBufs[iSegNo].dwTxBufAddrLo = 0; + pTD = (PSTxDesc)(pAdapter->aamTxDescRing[i].dwVAddr + sizeof(STxDesc)*(ii+1)); + } + } +} + +void GALCvSetAllRdOwnerToMac(PSAdapterInfo pAdapter) +{ + int ii; + + for (ii = pAdapter->cbRD - 1; ii >= 0; ii--) + pAdapter->apRD[ii]->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; +} + +void GALCvSetAllTdOwnerToMac(PSAdapterInfo pAdapter) +{ + int i, ii; + + for (i = 0; i < CB_TD_RING_NUM; i++) + for (ii = pAdapter->cbTD - 1; ii >= 0; ii--) + pAdapter->aapTD[i][ii]->m_td0TD0.f1Owner = B_OWNED_BY_CHIP; +} + +void GALCvSetDefaultRD(PSAdapterInfo pAdapter) +{ + /* set init RD value */ + GALCvChainRdrMemory(pAdapter); +} + +void GALCvSetDefaultTD(PSAdapterInfo pAdapter, int iSegNo) +{ + /* set init TD value */ + GALCvChainTdrMemory(pAdapter, iSegNo); /*chain first data segment */ +} diff --git a/cpu/arm920t/wmt/gcard.c b/cpu/arm920t/wmt/gcard.c new file mode 100755 index 0000000..08eeef0 --- /dev/null +++ b/cpu/arm920t/wmt/gcard.c @@ -0,0 +1,170 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* For IO-IO */ +#if defined(__WATCOMC__) +/* #include <conio.h> */ +#endif + +#if !defined(__UASSERT_H__) +#include "uassert.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +void GCARDvSetMediaLinkMode(DWORD dwIoBase, BYTE byRevId, UINT uConnectionType) +{ + DWORD dwData; + + /* detect the the brand of PHY */ + GMIIbReadEmbeded(dwIoBase, byRevId, MII_REG_PHYID2, (PWORD)&dwData); + GMIIbReadEmbeded(dwIoBase, byRevId, MII_REG_PHYID1, (PWORD)&dwData + 1); + + if ((dwData & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS8201 || + (dwData & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS3216I || + (dwData & CID_REV_ID_MASK_OFF) == CID_CICADA_CIS3216I64) { + /* Patch VT3119/VT3216 speed polling bug of MII Full-Duplex mode */ + if (uConnectionType == MEDIA_100M_FULL || uConnectionType == MEDIA_10M_FULL) + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_TCSR, TCSR_ECHODIS); + else + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_TCSR, TCSR_ECHODIS); + } + + /* clear force MAC mode bit */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCMODE); + + /* if connection type is AUTO */ + if (uConnectionType == MEDIA_AUTO) { + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_100FD|ANAR_100|ANAR_10FD|ANAR_10); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_GCR, GCR_1000FD|GCR_1000); + /* enable AUTO-NEGO mode */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + } else { + /* Nway force */ + WORD wANAR, wGTCR; + + /* In forced mode, always turn-on MAC FCMODE */ + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCMODE); + + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + + GMIIbReadEmbeded(dwIoBase, byRevId, MII_REG_ANAR, &wANAR); + GMIIbReadEmbeded(dwIoBase, byRevId, MII_REG_GCR, &wGTCR); + + wANAR &= (~(ANAR_100FD | ANAR_100 | ANAR_10FD | ANAR_10)); + wGTCR &= (~(GCR_1000FD | GCR_1000)); + + switch (uConnectionType) { + case MEDIA_1G_FULL: + wGTCR |= GCR_1000FD; + /* Turn on the forced mode of MAC */ + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + case MEDIA_1G_HALF: + wGTCR |= GCR_1000; + /* Turn on the forced mode of MAC */ + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + case MEDIA_100M_FULL: + wANAR |= ANAR_100FD; + /* Turn on the forced mode of MAC */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + case MEDIA_100M_HALF: + wANAR |= ANAR_100; + /* Turn on the forced mode of MAC */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + case MEDIA_10M_FULL: + wANAR |= ANAR_10FD; + /* Turn on the forced mode of MAC */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + case MEDIA_10M_HALF: + wANAR |= ANAR_10; + /* Turn on the forced mode of MAC */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCGMII); + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_FCFDX); + break; + default: + DBG_ASSERT(FALSE); + break; + } + + GMIIbWriteEmbeded(dwIoBase, byRevId, MII_REG_ANAR, wANAR); + GMIIbWriteEmbeded(dwIoBase, byRevId, MII_REG_GCR, wGTCR); + + /* enable AUTO-NEGO mode */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + + } /* end if */ +} + +void GCARDvSetLoopbackMode(DWORD dwIoBase, BYTE byRevId, WORD wLoopbackMode) +{ + switch (wLoopbackMode) { + case CARD_LB_NONE: + case CARD_LB_MAC: + case CARD_LB_MII: + break; + default: + DBG_ASSERT(FALSE); + break; + } + + /* set MAC loopback */ + GMACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode)); + /* set MII loopback */ + GMIIvSetLoopbackMode(dwIoBase, byRevId, HIBYTE(wLoopbackMode)); +} + +BOOL GCARDbSoftwareReset(DWORD dwIoBase, BYTE byRevId) +{ + /* reset MAC */ + if (!GMACbSafeSoftwareReset(dwIoBase, byRevId)) + return FALSE; + /* reset PHY */ + if (!GMIIbSafeSoftwareReset(dwIoBase, byRevId)) + return FALSE; + + return TRUE; +} diff --git a/cpu/arm920t/wmt/gisr.c b/cpu/arm920t/wmt/gisr.c new file mode 100755 index 0000000..1543633 --- /dev/null +++ b/cpu/arm920t/wmt/gisr.c @@ -0,0 +1,779 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif +#if !defined(__ISR_H__) +#include "gisr.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +void static s_ISRvPacketReceive(PSAdapterInfo pAdapter); +void static s_ISRvPacketTransmit(PSAdapterInfo pAdapter, BYTE byTxQue); +/*--------------------- Export Variables --------------------------*/ +extern SAdapterOpts sOptions; +/*--------------------- Export Functions --------------------------*/ +void ISRvIsrForNetwork_Card0(void) +{ + GISRvIsrForNetwork(&sg_aGAdapter[0]); +} + +void ISRvIsrForNetwork_Card1(void) +{ + GISRvIsrForNetwork(&sg_aGAdapter[1]); +} + +void ISRvIsrForNetwork_Card2(void) +{ + GISRvIsrForNetwork(&sg_aGAdapter[2]); +} + +void ISRvIsrForNetwork_Card3(void) +{ + GISRvIsrForNetwork(&sg_aGAdapter[3]); +} + +/* + * Description: This routine is called when MAC interrupt system + * + * NOTE : when into this routine something should be aware + * 1) interrupt has been disabled. + * 2) inside a critical section (time) + * 3) stack owned by unknown application + * + * Parameters: + * + */ +/* Note:In vpost, irq is not enanle after entering ISR ,so it is so called non-nest interrupt */ +void GISRvIsrForNetwork(PSAdapterInfo pAdapter) +{ + DWORD dwOrgIMR; + DWORD dwOrgISR; + WORD wOrgESR; + + DWORD dwIoBase; + BYTE byIrqLevel; + + + /* led 1 */ + VNSvOutPortD(0xD811005C, 1); + /* get IoBase address and IRQ level */ + dwIoBase = pAdapter->dwIoBase; + byIrqLevel = pAdapter->byIrqLevel; + + /* preserve original IMR value */ + VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwOrgIMR); + + /* read current ISR */ + MACvReadISR(dwIoBase, &dwOrgISR); + + /* read RXE_SR, TXE_SR */ + VNSvInPortW(dwIoBase + MAC_REG_TXE_SR, &wOrgESR); + + /* + * (1). if this is not our device's IRQ, then call original ISR and exit. + * (2). if this is our device's IRQ, then handle it and exit. + * we do not call original ISR. Because if another device also invoke + * the IRQ at the same time, then the IRQ will be invoked again after + * we had exited this ISR routine. + */ + + /* if is not our device's interrupt, */ + if ((dwOrgISR & dwOrgIMR) == 0) + return; + + /* mask off IMR, prevent MAC's other interrupt to reentry */ + MACvIntDisable(dwIoBase); + + /* write 1s to clear TXESR and RXESR */ + VNSvOutPortW(dwIoBase + MAC_REG_TXE_SR, wOrgESR); + + /* write 1s to clear ISR active interrupts */ + MACvWriteISR(dwIoBase, dwOrgISR); + + /* prevent All 1's ISR */ + if (dwOrgISR == 0xFFFFFFFFUL) + goto IntDone; + + /* SERVICE RD/TD */ + /* handle rx */ + s_ISRvPacketReceive(pAdapter); + /* led 2 */ + VNSvOutPortD(0xD811005C, 2); + + /* handle tx */ + s_ISRvPacketTransmit(pAdapter, 0); + /* led 3 */ + VNSvOutPortD(0xD811005C, 4); + + /* Must do this after doing rx/tx, cause ISR bit is slower */ + /* than RD/TD write back */ + /* update ISR counter */ + GSTAvUpdateIsrStatCounter(&pAdapter->scStatistic, dwOrgISR, wOrgESR); + + /* Read HWMIBCounter */ + if (BITbIsBitOn(dwOrgISR, ISR_MIBFI)) + GSTAvUpdateHWMIBCounter(pAdapter->dwIoBase, &pAdapter->sHWMibCounter); + + /* + * ERROR HANDLING + */ + + /* if link change */ + if (BITbIsBitOn(dwOrgISR, ISR_SRCI)) { + /* Enable MII Auto-Polling */ + GMACvEnableMiiAutoPoll(dwIoBase); + + /* check the cable link status */ + /* link OK */ + pAdapter->bLinkPass = GMACbIsCableLinkOk(dwIoBase); + + if (pAdapter->bLinkPass) { + /* each time int invoked, this counter will plus 1 */ + pAdapter->scStatistic.dwIntLinkUp++; + + /* update duplex status */ + pAdapter->bFullDuplex = GMACbIsInFullDuplexMode(pAdapter->dwIoBase); + + /* update speed status */ + pAdapter->bSpeed1G = GMACbIsIn1GMode(pAdapter->dwIoBase, pAdapter->byRevId); + pAdapter->bSpeed100M = GMACbIsIn100MMode(dwIoBase, pAdapter->byRevId); + + /* set flow control capability according to PHYSR0 register */ + if (GMIIbIsAutoNegotiationOn(pAdapter->dwIoBase, pAdapter->byRevId)) { + /* enable/disable RX flow control */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_PHYSR0, PHYSR0_RXFLC)) + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_SET, CR2_FDXRFCEN); + else + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_CLR, CR2_FDXRFCEN); + + /* enable/disable TX flow control */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_PHYSR0, PHYSR0_TXFLC)) + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_SET, CR2_FDXTFCEN); + else + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_CR2_CLR, CR2_FDXTFCEN); + } + + /* This is patch for VT3119A1 */ + /* Use TCR_TB2BDIS to prevent 1c_Reset failure in helf-duplex mode */ + /* Only use this in 10HD and 100HD */ + if (pAdapter->byRevId < REV_ID_VT3216_A0) { + if (!pAdapter->bSpeed1G) { + if (pAdapter->bFullDuplex) + MACvRegBitsOff(pAdapter->dwIoBase, MAC_REG_TCR, TCR_TB2BDIS); + else + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_TCR, TCR_TB2BDIS); + } + } + + /* This is patch for VT3119/VT3216 */ + /* Patch HW MIB TXSQEErr Bug, this should only function in 10HD */ + if (pAdapter->byRevId < REV_ID_VT3284_A0) { + if ((!pAdapter->bSpeed1G) && + (!pAdapter->bSpeed100M) && + (!pAdapter->bFullDuplex)) { + /* Enable count TXSQEErr in 10HD */ + MACvRegBitsOff(pAdapter->dwIoBase, MAC_REG_TESTCFG, 0x80); + } else { + /* Disable count TXSQEErr in 10FD, 100HD, 100FD, 1G */ + MACvRegBitsOn(pAdapter->dwIoBase, MAC_REG_TESTCFG, 0x80); + } + } + + } else { + /* link fail */ + /* each time int invoked, this counter will plus 1 */ + pAdapter->scStatistic.dwIntLinkDown++; + } + } + + if (BITbIsBitOn(dwOrgISR, ISR_LSTEI)) { + /* + * if Rx no buffer error, don't do software reset + * 1. turn on owner bit in all Rx descriptor + * 2. point current Rx to first descriptor + * 3. Rx on + * 4. RX WAK + */ + /* + for (ii = 0; ii < pAdapter->cbRD; ii++) + pAdapter->apRD[ii]->m_rd0RD0.f1Owner = 1; + MACvSetRxDescBaseLo32(pAdapter->dwIoBase, pAdapter->amRxDescRing.dwPAddr); + pAdapter->uRxDequeDescIdx = pAdapter->idxRxPktStartDesc = 0; + PCAvDelayByIO(200); + MACvRxOn(pAdapter->dwIoBase); + */ + } + + /* if Rx/Tx DMA stall */ + if (BITbIsBitOn(dwOrgISR, ISR_RXSTLI)) { + /* + // TBD.... + // rx off -> sw reset -> start + // reset the adapter + if (pAdapter->byRevId < REV_ID_VT3065_A) + MACbSafeSoftwareReset(pAdapter->dwIoBase, pAdapter->byRevId); + // rx was shutdowned, turn on rx + MACvRxOn(pAdapter->dwIoBase); + MACvTransmit(pAdapter->dwIoBase); + */ + } + + if (BITbIsBitOn(dwOrgISR, ISR_TXSTLI)) { + /* + if (BITbIsBitOn(ptdCurr->m_td0TD0.byTSR1, TSR1_TBUFF)) { + // chip may be shutdowned, so re-start it + MACvTxOn(pAdapter->dwIoBase); + MACvTxQueueWake(pAdapter->dwIoBase,(BYTE)(0x40>>byTxQue)); + // re-assert TDMD + MACvTransmit(pAdapter->dwIoBase); + } + */ + } + + /* TXESR */ + if (BITbIsBitOn((BYTE)(wOrgESR & 0x000F), TXESR_TDSTR)) + pAdapter->bTxOn = FALSE; + if (BITbIsBitOn((BYTE)(wOrgESR & 0x000F), TXESR_TDRBS)) + pAdapter->bTxOn = FALSE; + if (BITbIsBitOn((BYTE)(wOrgESR & 0x000F), TXESR_TDWBS)) + pAdapter->bTxOn = FALSE; + if (BITbIsBitOn((BYTE)(wOrgESR & 0x000F), TXESR_TFDBS)) + pAdapter->bTxOn = FALSE; + + /* RXESR */ + if (BITbIsBitOn((BYTE)((wOrgESR & 0x00F0) >> 8), RXESR_RDSTR)) + ; + if (BITbIsBitOn((BYTE)((wOrgESR & 0x00F0) >> 8), RXESR_RDRBS)) + ; + if (BITbIsBitOn((BYTE)((wOrgESR & 0x00F0) >> 8), RXESR_RDWBS)) + ; + if (BITbIsBitOn((BYTE)((wOrgESR & 0x00F0) >> 8), RXESR_RFDBS)) + ; + +IntDone: + /* + * disable CPU's int to prevent reentry: if next statement enable + * MAC's int, and MAC happen to invoke int will cause reentry, + * so disable CPU's int here, let RETI to enable CPU's int + */ + /* PCAvIntDisable(); */ + + /* restore original IMR value */ + MACvIntEnable(dwIoBase, dwOrgIMR); + /* led off */ + VNSvOutPortD(0xD811005C, 0); +} + +void static s_ISRvPacketReceive(PSAdapterInfo pAdapter) +{ + void (CALLBACK * pisrCallBack)(PSAdapterInfo, PBYTE, UINT); + + UINT uCurrDescIdx; + PSRxDesc pCurrRD; + int ii; + UINT uu; + + BYTE byRsr0, byRsr1; + UINT uRxFreeRD = 0; + UINT uRxFreeRDIdx = pAdapter->uRxDequeDescIdx; + UINT FrameSize; + + DWORD dwRxFifoLength; + UINT FrameSizeWithCRC; + + PBYTE pbyRxBufAddr ; + PBYTE pbyHwCRC32 ; + DWORD dwHwCRC32 ; + DWORD dwSwCRC32 ; + + /* added by kevin to not upload to uper layer */ + pisrCallBack = NULL; + + if (pAdapter->byRevId >= REV_ID_VT3216_A0) + dwRxFifoLength = 48896; /* 48*1024 - 32*8 */ + else + dwRxFifoLength = 32512; /* 32*1024 - 32*8 */ + + while (TRUE) { + uCurrDescIdx = pAdapter->uRxDequeDescIdx; + pCurrRD = pAdapter->apRD[uCurrDescIdx]; + byRsr0 = pCurrRD->m_rd0RD0.byRSR0; + byRsr1 = pCurrRD->m_rd0RD0.byRSR1; + FrameSizeWithCRC = pCurrRD->m_rd0RD0.f14RMBC; + + /* if the RD is owned by the chip, we are done. */ + if (pCurrRD->m_rd0RD0.f1Owner == B_OWNED_BY_CHIP) + break; + + /* expected both STP and EDP are zero as single RD receive case */ + /* else it's multiple RD receive case */ + /* [STP, EDP] = [0,0] single RD received */ + /* [STP, EDP] = [1,0] first RD in multiple RD received */ + /* [STP, EDP] = [1,1] middle RD in multiple RD received */ + /* [STP, EDP] = [0,1] last RD in multiple RD received */ + if (BITbIsBitOn(byRsr1, (RSR1_STP | RSR1_EDP))) { + /* Drop this RD, move to next RD */ + uRxFreeRD++; + ADD_ONE_WITH_WRAP_AROUND(pAdapter->uRxDequeDescIdx, pAdapter->cbRD); + + /* [1.14], Calculate Rx Fifo Address */ + pAdapter->dwRxFifoAddr += FrameSizeWithCRC; + if (pAdapter->dwRxFifoAddr >= dwRxFifoLength) + pAdapter->dwRxFifoAddr -= dwRxFifoLength; + + /* branch code to while(TRUE) */ + continue; + } + + /* increase handled rx counter */ + pAdapter->iRxPktHandled++; + + /* get the frame size */ + FrameSize = pCurrRD->m_rd0RD0.f14RMBC; + + /* DBG: Get hardware and software-generated CRC32 */ + pbyRxBufAddr = (PBYTE)pAdapter->amRxDescBuf.dwVAddr + uCurrDescIdx*CB_MAX_BUF_SIZE; + pbyHwCRC32 = pbyRxBufAddr + (FrameSize-4); + dwHwCRC32 = *((PDWORD)pbyHwCRC32); + dwSwCRC32 = 0; + + if (pAdapter->bSoftwareCheckCrc) { + /* TBD */ + /* calculate crc by software */ + PCAvIntDisable(); + dwSwCRC32 = CRCdwGetCrc32(pbyRxBufAddr, FrameSize - 4); + PCAvIntEnable(); + } /* end if (pAdapter->bSoftwareCheckCrc) */ + + + /* + * handle this RD + */ + /* update receive statistic counter */ + GSTAvUpdateRDStatCounterEx( + &pAdapter->scStatistic, + pCurrRD, + pbyRxBufAddr, + FrameSize, + dwHwCRC32, + dwSwCRC32 + ); + + if (pAdapter->bWhenRxDataErrOutPort0x80 && GMACbIsInLoopbackMode(pAdapter->dwIoBase)) { + if (dwHwCRC32 != dwSwCRC32) { + /* Stop TX if CRC32 inconsistent */ + pAdapter->bTxOn = FALSE; + pAdapter->bShowLbPacketComp = TRUE; + } + } + + + /* + * RX ERROR + */ + if (BITbIsBitOff(byRsr1, RSR1_RXOK)) { + if (BITbIsBitOn(byRsr0, RSR0_CRC) && pAdapter->bWhenRxCrcErrNoBuf) { + /* goto IPR_NoReleaseOwner; */ + /* Stop RX */ + GMACbSafeRxOff(pAdapter->dwIoBase, pAdapter->byRevId); + break; + } + + /* Drop this RD, move to next RD */ + uRxFreeRD++; + ADD_ONE_WITH_WRAP_AROUND(pAdapter->uRxDequeDescIdx, pAdapter->cbRD); + + /* [1.16], Calculate Rx Fifo Address */ + pAdapter->dwRxFifoAddr += FrameSizeWithCRC; + /* + if (pAdapter->dwRxFifoAddr >= pAdapter->dwRxFifoSize) + pAdapter->dwRxFifoAddr -= pAdapter->dwRxFifoSize; + */ + if (pAdapter->dwRxFifoAddr >= dwRxFifoLength) + pAdapter->dwRxFifoAddr -= dwRxFifoLength; + + /* branch code to while(TRUE) */ + continue; + } + + + /* + * RX OK + */ + + /* for pingpong: copy buffer to upper layer buffer */ + /*because we don't need,we mark the function */ + /* + pisrCallBack = (void (CALLBACK *)(PSAdapterInfo, PBYTE, UINT))pAdapter->pisrPptReceiver; + if (pisrCallBack != NULL) { + (*pisrCallBack)( + pAdapter, + pbyRxBufAddr, + FrameSize + ); + } + */ + + /* Release this RD */ + uRxFreeRD++; + ADD_ONE_WITH_WRAP_AROUND(pAdapter->uRxDequeDescIdx, pAdapter->cbRD); + + /* [1.16], Calculate Rx Fifo Address */ + pAdapter->dwRxFifoAddr += FrameSizeWithCRC; + /* + if (pAdapter->dwRxFifoAddr >= pAdapter->dwRxFifoSize) { + pAdapter->dwRxFifoAddr -= pAdapter->dwRxFifoSize; + } + */ + if (pAdapter->dwRxFifoAddr >= dwRxFifoLength) + pAdapter->dwRxFifoAddr -= dwRxFifoLength; + } /* end while (TRUE) */ + + + /* batch append RD here (4X RDs appended each time) */ + /* count the difference between uRxDequeDescIdx and uRxAppendDescIdx */ + /* why we should release RD wit 4 multiple */ + if ((pAdapter->cbToBeFreeRD + uRxFreeRD) >= 4) { + /* calculate the number of RD to be free, it must be 4X */ + ii = (pAdapter->cbToBeFreeRD + uRxFreeRD) - ((pAdapter->cbToBeFreeRD + uRxFreeRD) % 4); + /* decrease the RD index */ + SUB_ONE_WITH_WRAP_AROUND(uRxFreeRDIdx, pAdapter->cbRD); + /* calculate the end RD index to be free in this time */ + ADD_N_WITH_WRAP_AROUND(uRxFreeRDIdx, (ii - pAdapter->cbToBeFreeRD), pAdapter->cbRD); + + for (uu = 0; uu < ii; uu++) { + pAdapter->apRD[uRxFreeRDIdx]->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; + SUB_ONE_WITH_WRAP_AROUND(uRxFreeRDIdx, pAdapter->cbRD); + } + + /* update RXRDU in FlowCR0 */ + VNSvOutPortB(pAdapter->dwIoBase + MAC_REG_RBRDU, (BYTE)ii); + + /* calculate to-be-free RD for next time */ + pAdapter->cbToBeFreeRD = (pAdapter->cbToBeFreeRD + uRxFreeRD) % 4; + } else { + /* calculate to-be-free RD for next time */ + pAdapter->cbToBeFreeRD += uRxFreeRD; + } +} + +void static s_ISRvPacketTransmit(PSAdapterInfo pAdapter, BYTE byTxQue) +{ + PSTxDesc ptdCurr; + int ii; + WORD wPktSize; + BOOL bIsTxISR = FALSE; + UINT uCurrTdIdx; + + DWORD dwTxFifoLength; + PBYTE pbyBuffer; + + if (pAdapter->byRevId >= REV_ID_VT3216_A0) + dwTxFifoLength = 16384; /* 16*1024 */ + else + dwTxFifoLength = 10240; /* 10*1024 */ + + while (TRUE) { + uCurrTdIdx = pAdapter->uTxDequeDescIdx[byTxQue]; + ptdCurr = pAdapter->aapTD[byTxQue][uCurrTdIdx]; + + /* If the ring is empty or the current descriptor */ + /* is not owned by the system, we are done. */ + if (ptdCurr->m_td0TD0.f1Owner == B_OWNED_BY_CHIP) + break; + + if (pAdapter->auTxPktPosted[byTxQue] == 0) + break; + + /* it's Interrupt for Tx */ + bIsTxISR = TRUE; + + /* if there is a number limit to tx */ + /* pAdapter->lTxPacketNum==0 means, tx number is un-limited */ + if (pAdapter->lTxPacketNum != 0) { + /* decrease lTxPacketNumShadow */ + pAdapter->lTxPacketNumShadow--; + + /* if exceed the tx number */ + if (pAdapter->lTxPacketNumShadow == 0) + pAdapter->bTxOn = FALSE; + } + + /* calculate the total buffer size */ + wPktSize = 0; + for (ii = 0; ii < ptdCurr->m_td1TD1.f4CMDZ - 1; ii++) + wPktSize += ptdCurr->m_asTxBufs[ii].f14TxBufSize; + + /* + * handle this TD + */ + + /* update transmit statistic counter */ + GSTAvUpdateTDStatCounterEx( + &pAdapter->ascStatistic[byTxQue], + &pAdapter->mibCounter, + ptdCurr, + (PBYTE)(pAdapter->aapTD[byTxQue][uCurrTdIdx]->m_asTxBufs[0].dwTxBufAddrLo), + /* wPktSize */ + ptdCurr->m_asTxBufs[0].f14TxBufSize + ptdCurr->m_asTxBufs[1].f14TxBufSize + + ptdCurr->m_asTxBufs[2].f14TxBufSize + ptdCurr->m_asTxBufs[3].f14TxBufSize + + ptdCurr->m_asTxBufs[4].f14TxBufSize + ptdCurr->m_asTxBufs[5].f14TxBufSize + + ptdCurr->m_asTxBufs[6].f14TxBufSize + ); + + if (byTxQue == 0) { /* default TD queue */ + GSTAvUpdateTDStatCounterTq0( + &pAdapter->scStatistic, /* for diag tool counter display */ + ptdCurr, + (PBYTE)(pAdapter->aapTD[byTxQue][uCurrTdIdx]->m_asTxBufs[0].dwTxBufAddrLo), + /* wPktSize */ + ptdCurr->m_asTxBufs[0].f14TxBufSize + ptdCurr->m_asTxBufs[1].f14TxBufSize + + ptdCurr->m_asTxBufs[2].f14TxBufSize + ptdCurr->m_asTxBufs[3].f14TxBufSize + + ptdCurr->m_asTxBufs[4].f14TxBufSize + ptdCurr->m_asTxBufs[5].f14TxBufSize + + ptdCurr->m_asTxBufs[6].f14TxBufSize + ); + } + + /* + * TX OK + */ + if (BITbIsBitOff(ptdCurr->m_td0TD0.byTSR1, TSR1_TERR)) { + /* decrease posted tx packet counter */ + pAdapter->auTxPktPosted[byTxQue]--; + } else { + /* + * TX ERROR HANDLING + */ + + if (pAdapter->bWhenTxErrOutPort0x80) { + PCBvOutPortB(0x80, 0xAA); + /* PCBvOutPortB(0x80, 0x00); */ + + pAdapter->bTxOn = FALSE; + } + + /* (1). tx abort */ + + /* tx abort don't do retry */ + if (BITbIsBitOn(ptdCurr->m_td0TD0.byTSR0, TSR0_ABT)) { + /* chip may be shutdowned, so re-start it */ + MACvTxOn(pAdapter->dwIoBase); + MACvTxQueueRUN(pAdapter->dwIoBase, byTxQue); + MACvTxQueueWake(pAdapter->dwIoBase, byTxQue); + } + + /* decrease posted tx packet counter */ + pAdapter->auTxPktPosted[byTxQue]--; + } /* end Tx error handling */ + + /* clear td status */ + ptdCurr->m_td0TD0.byTSR0 = 0; + ptdCurr->m_td0TD0.byTSR1 = 0; + /* VT3119A1 must clear Quebit, MAC doesn't write back QueBit */ + ptdCurr->m_asTxBufs[0].f1Que = 0; + + /* move DequeTdIdx to next */ + pAdapter->uTxDequeDescIdx[byTxQue] = (uCurrTdIdx + 1) % pAdapter->cbTD; + + /* [1.14], Calculate Tx Fifo Address */ + pAdapter->dwTxFifoAddr[byTxQue] += ( + 8 + ptdCurr->m_asTxBufs[0].f14TxBufSize + ptdCurr->m_asTxBufs[1].f14TxBufSize + + ptdCurr->m_asTxBufs[2].f14TxBufSize + ptdCurr->m_asTxBufs[3].f14TxBufSize + + ptdCurr->m_asTxBufs[4].f14TxBufSize + ptdCurr->m_asTxBufs[5].f14TxBufSize + + ptdCurr->m_asTxBufs[6].f14TxBufSize + ); + + if (pAdapter->dwTxFifoAddr[byTxQue] >= dwTxFifoLength) + pAdapter->dwTxFifoAddr[byTxQue] -= dwTxFifoLength; + + /* for specific purpose we add owner bit automatically */ + if (pAdapter->bTxContPerfTest && + pAdapter->bTxOn && + !pAdapter->bTxSinglePacket) { + + /* Set this TD */ + UINT uTxPktSize; + if (pAdapter->bRandomPktLength) { + /* TBD */ + UINT uRandomPktSize = MAX_PACKET_LEN ; /* RANDOM(MAX_PACKET_LEN) + 1; */ + + /* ??? */ + /* In loopback test, hardware wouldn't generate 4-byte CRC, + * software make the minumum TX buffer size to be 64 bytes + * to avoid generating runt packet + */ + /* + if (uRandomPktSize < (MIN_PACKET_LEN + 4)) { + // TBD.... + CRC 4 bytes + uRandomPktSize = MIN_PACKET_LEN + 4; + } + */ + if (pAdapter->bSoftwareGenCrc) { + if (uRandomPktSize < (MIN_PACKET_LEN + 4)) + uRandomPktSize = MIN_PACKET_LEN + 4; + } else { + if (uRandomPktSize < MIN_PACKET_LEN) + uRandomPktSize = MIN_PACKET_LEN; + } + /* + if (uRandomPktSize > MAX_PACKET_LEN) { + uRandomPktSize = MAX_PACKET_LEN; + } + */ + uTxPktSize = uRandomPktSize; + } else if (pAdapter->bIncPktLength) { + uTxPktSize = pAdapter->uTxPktSize; + + /* increase packet length */ + pAdapter->uTxPktSize++; + if (pAdapter->bSoftwareGenCrc) { + if (pAdapter->uTxPktSize > (MAX_PACKET_LEN + 4)) + pAdapter->uTxPktSize = MIN_PACKET_LEN + 4; + } else { + if (pAdapter->uTxPktSize > MAX_PACKET_LEN) + pAdapter->uTxPktSize = MIN_PACKET_LEN; + } + } else + uTxPktSize = pAdapter->cbPktSize; + + /* [1.12] */ + pbyBuffer = (PBYTE)(ptdCurr->m_asTxBufs[0].dwTxBufAddrLo); + + if (pAdapter->bRandomPktData) { + UINT kk; + UINT uPosition; + + /* RANDOM DATA */ + /* Get random position in Random Table */ + /* TBD */ + uPosition = 3072 - uTxPktSize;/* RANDOM((3072 - uTxPktSize)); */ + for (kk = 0; kk < uTxPktSize; kk++) + *(pbyBuffer + kk) = *((PBYTE)sg_abyRandomTable + uPosition + kk); + } + + if (pAdapter->bSoftwareGenCrc) { + PDWORD pdwCRC = (PDWORD)(pbyBuffer + uTxPktSize - 4); + DWORD dwCRC; + PCAvIntDisable(); + dwCRC = CRCdwGetCrc32(pbyBuffer, uTxPktSize - 4); + *pdwCRC = dwCRC; + PCAvIntEnable(); + } + + ptdCurr->m_td0TD0.f14TxPktSize = (WORD)uTxPktSize; + + /* Calculate each segment's buffer size */ + UINT uSegNum; + UINT i; + if (pAdapter->bRandDatSegsPerPacket) { + /* TBD */ + uSegNum = CB_MAX_SEG_PER_PKT+1 ;/* RANDOM(CB_MAX_SEG_PER_PKT) + 1; */ + } else + uSegNum = pAdapter->uTxDataSegsPerPacket; + + if (uSegNum > 1) { + WORD wTempBufSize; + + /* The BufLen of first Buf is 14 */ + ptdCurr->m_asTxBufs[0].f14TxBufSize = 14; + + /* The rest */ + /* Equal the buffer length */ + wTempBufSize = (WORD)((uTxPktSize - 14) / (uSegNum - 1)); + for (i = 1; i < uSegNum; i++) { + if (i == (uSegNum - 1)) { + ptdCurr->m_asTxBufs[i].f14TxBufSize = + (WORD)((uTxPktSize - 14) - + (wTempBufSize*(uSegNum - 2))); + } else + ptdCurr->m_asTxBufs[i].f14TxBufSize = wTempBufSize; + ptdCurr->m_asTxBufs[i].dwTxBufAddrLo = + ptdCurr->m_asTxBufs[i-1].dwTxBufAddrLo + + ptdCurr->m_asTxBufs[i-1].f14TxBufSize; + } /* end for */ + + for ( ; i < CB_MAX_SEG_PER_PKT; i++) { + ptdCurr->m_asTxBufs[i].f14TxBufSize = 0; + ptdCurr->m_asTxBufs[i].dwTxBufAddrLo = 0; + } + } else { + /* uSegNum = 1 */ + /* only one descriptor; it occupies the whole packet size */ + ptdCurr->m_asTxBufs[0].f14TxBufSize = (WORD)uTxPktSize; + for (i = 1; i < CB_MAX_SEG_PER_PKT; i++) { + ptdCurr->m_asTxBufs[i].f14TxBufSize = 0; + ptdCurr->m_asTxBufs[i].dwTxBufAddrLo = 0; + } + } /* end if (uSegNum > 1) */ + ptdCurr->m_td1TD1.f4CMDZ = (BYTE)(uSegNum + 1); + ptdCurr->m_td0TD0.f1Owner = B_OWNED_BY_CHIP; + + pAdapter->auTxPktPosted[byTxQue]++; + + /* Get last TD Idx */ + UINT uLastTdIdx = (uCurrTdIdx - 1 + pAdapter->cbTD) % pAdapter->cbTD; + if (pAdapter->aapTD[byTxQue][uLastTdIdx]->m_td0TD0.f1Owner == B_OWNED_BY_CHIP) { + /* VT3119A0 */ + /* vSetBit((PDWORD)(pAdapter->aapTD[byTxQue][wLastTdIdx])); */ + /* VT3119A1 */ + pAdapter->aapTD[byTxQue][uLastTdIdx]->m_asTxBufs[0].f1Que = B_TD_LIST_NOT_END; + } + } /* end if */ + + } /* end while (TRUE) */ + + if (pAdapter->bTxContPerfTest && + pAdapter->bTxOn && + !pAdapter->bTxSinglePacket) + MACvTxQueueWake(pAdapter->dwIoBase, byTxQue); +} + +VOID +PCAvIntEnable( + void + ) +{ + asm volatile ("MRS r0, CPSR\n"); + asm volatile ("BIC r0, r0, #0x80\n"); + asm volatile ("MSR CPSR_c, r0\n"); +} + +VOID +PCAvIntDisable( + void + ) +{ + asm volatile ("MRS r0, CPSR\n"); + asm volatile ("ORR r0, r0, #0x80\n"); + asm volatile ("MSR CPSR_c, r0\n"); +} diff --git a/cpu/arm920t/wmt/gisr.h b/cpu/arm920t/wmt/gisr.h new file mode 100755 index 0000000..23bbe43 --- /dev/null +++ b/cpu/arm920t/wmt/gisr.h @@ -0,0 +1,72 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __GISR_H__ +#define __GISR_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ +VOID +PCAvIntEnable( + void + ); + +VOID +PCAvIntDisable( + void + ); + +DWORD +CRCdwGetCrc32( + PBYTE pbyData, + UINT cbByte +); + +/* supports max 6 cards */ +void ISRvIsrForNetwork_Card0(void); +void ISRvIsrForNetwork_Card1(void); +void ISRvIsrForNetwork_Card2(void); +void ISRvIsrForNetwork_Card3(void); + + +/* interrupt service routine for adapter */ +void GISRvIsrForNetwork(PSAdapterInfo pAdapter); + + +#if defined(__cplusplus) +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __ISR_H__ */ diff --git a/cpu/arm920t/wmt/gmac.c b/cpu/arm920t/wmt/gmac.c new file mode 100755 index 0000000..f7b1282 --- /dev/null +++ b/cpu/arm920t/wmt/gmac.c @@ -0,0 +1,1238 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__UASSERT_H__) +#include "uassert.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(_MACIF_H_) +#include "macif.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ +#define CB_DELAY_NM9346 (10) /* 10ms */ +#define CB_DELAY_SOFT_RESET (50) /* 50ms */ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +VOID GMACvReadAllRegs(DWORD dwIoBase, PSMacReg pMacRegs, BYTE byRevId) +{ + int ii; + PBYTE pbyData = (PBYTE)pMacRegs; + + for (ii = 0; ii < MAC_REG_DEC_BASE_HI; ii++) { + VNSvInPortB(dwIoBase + ii, pbyData); + pbyData++; + } + + for ( ; ii < MAC_REG_ISR_CTL; ii += sizeof(DWORD), pbyData += sizeof(DWORD)) + VNSvInPortD(dwIoBase + ii, (PDWORD)pbyData); + + for ( ; ii < MAC_REG_RDBASE_LO; ii++, pbyData++) + VNSvInPortB(dwIoBase + ii, pbyData); + + for ( ; ii < MAC_REG_CAMADDR; ii += sizeof(DWORD), pbyData += sizeof(DWORD)) + VNSvInPortD(dwIoBase + ii, (PDWORD)pbyData); + + for ( ; ii < MAC_REG_MIBREAD; ii++, pbyData++) + VNSvInPortB(dwIoBase + ii, pbyData); + + ii += 4; + pbyData += 4; /* skip MIB_READ_PORT, because it may have side effect. */ + + for ( ; ii < MAC_REG_WOLCR0_SET; ii++, pbyData++) + VNSvInPortB(dwIoBase + ii, pbyData); + + for ( ; ii < MAC_REG_BYTEMSK3_3 + 4; ii += sizeof(DWORD), pbyData += sizeof(DWORD)) + VNSvInPortD(dwIoBase + ii, (PDWORD)pbyData); + + return; +} + +BOOL GMACbIsRegBitsOn(DWORD dwIoBase, BYTE byRegOfs, BYTE byTestBits) +{ + BYTE byData; + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOn(byData, byTestBits); +} + +BOOL GMACbIsRegBitsOff(DWORD dwIoBase, BYTE byRegOfs, BYTE byTestBits) +{ + BYTE byData; + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOff(byData, byTestBits); +} + +BYTE GMACbyReadEECSR(DWORD dwIoBase) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_EECSR, &byData); + /* PCAvDelayByIO(CB_DELAY_NM9346); */ + return byData; +} + +VOID GMACvWriteEECSR(DWORD dwIoBase, BYTE byValue) +{ + VNSvOutPortB(dwIoBase + MAC_REG_EECSR, byValue); + /* delay 1 ms using MAC hardware timer */ + GMACvTimer0MiniSDelay(dwIoBase, REV_ID_VT3119_A0, 1); +} + +/* +void MACvWriteEECSR (DWORD dwIoBase, BYTE byValue) +{ + VNSvOutPortB(dwIoBase + MAC_REG_EECSR, byValue); + PCAvDelayByIO(CB_DELAY_NM9346); +} +*/ + +BYTE GMACbyReadMIICR(DWORD dwIoBase) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_MIICR, &byData); + return byData; +} + +VOID GMACvWriteMIICR(DWORD dwIoBase, BYTE byValue) +{ + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, byValue); +} + + +BYTE GMACbyReadMultiAddr(DWORD dwIoBase, UINT uByteIdx) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_MAR + uByteIdx, &byData); + return byData; +} + + +VOID GMACvWriteMultiAddr(DWORD dwIoBase, UINT uByteIdx, BYTE byData) +{ + VNSvOutPortB(dwIoBase + MAC_REG_MAR + uByteIdx, byData); +} + + +BOOL GMACbIsIntDisable(DWORD dwIoBase, BYTE byRevId) +{ + DWORD dwData; + + VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData); + if (dwData != 0x00000000UL) + return FALSE; + + return TRUE; +} + +/* + * Description: Set this hash index into multicast address register + * bit + * + * Parameters: + * + */ +VOID GMACvSetMultiAddrByHash(DWORD dwIoBase, BYTE byHashIdx) +{ + UINT uByteIdx; + BYTE byBitMask; + BYTE byOrgValue; + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select MAR regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)(byOrgCAMCR & ~(CAMCR_PS1|CAMCR_PS0)); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* calculate byte position */ + uByteIdx = byHashIdx / 8; + DBG_ASSERT(uByteIdx < 8); + /* calculate bit position */ + byBitMask = 1; + byBitMask <<= (byHashIdx % 8); + /* turn on the bit */ + byOrgValue = GMACbyReadMultiAddr(dwIoBase, uByteIdx); + GMACvWriteMultiAddr(dwIoBase, uByteIdx, (BYTE)(byOrgValue | byBitMask)); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +/* + * Description: Reset this hash index into multicast address register + * bit + * + * Parameters: + * + */ +VOID GMACvResetMultiAddrByHash(DWORD dwIoBase, BYTE byHashIdx) +{ + UINT uByteIdx; + BYTE byBitMask; + BYTE byOrgValue; + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select MAR regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)(byOrgCAMCR & ~(CAMCR_PS1|CAMCR_PS0)); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* calculate byte position */ + uByteIdx = byHashIdx / 8; + DBG_ASSERT(uByteIdx < 8); + /* calculate bit position */ + byBitMask = 1; + byBitMask <<= (byHashIdx % 8); + /* turn off the bit */ + byOrgValue = GMACbyReadMultiAddr(dwIoBase, uByteIdx); + GMACvWriteMultiAddr(dwIoBase, uByteIdx, (BYTE)(byOrgValue & (~byBitMask))); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +BYTE GMACbyGetBootRomSize(DWORD dwIoBase) +{ + BYTE byOrgValue; + + VNSvInPortB(dwIoBase + MAC_REG_CFGC, &byOrgValue); + return (BYTE)(byOrgValue & 0x07); +} + +VOID GMACvSetPhyId(DWORD dwIoBase, BYTE byRevId, BYTE byPhyId) +{ + BYTE byData; + + /* set PHY address */ + VNSvInPortB(dwIoBase + MAC_REG_MIICFG, &byData); + byData = (BYTE)((byData & 0xE0) | (byPhyId & 0x1F)); + VNSvOutPortB(dwIoBase + MAC_REG_MIICFG, byData); +} + +BYTE GMACbyGetPhyId(DWORD dwIoBase) +{ + BYTE byOrgValue; + + VNSvInPortB(dwIoBase + MAC_REG_MIICFG, &byOrgValue); + return (BYTE)(byOrgValue & 0x1F); +} + +VOID GMACvSetRxThreshold(DWORD dwIoBase, BYTE byThreshold) +{ + BYTE byOrgValue; + + DBG_ASSERT(byThreshold < 4); + + /* set MCFG0 */ + VNSvInPortB(dwIoBase + MAC_REG_MCFG0, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & ~(MCFG0_RFT1|MCFG0_RFT0)) | (byThreshold << 4)); + VNSvOutPortB(dwIoBase + MAC_REG_MCFG0, byOrgValue); +} + +VOID GMACvGetRxThreshold(DWORD dwIoBase, PBYTE pbyThreshold) +{ + /* first, get MCFG0 */ + VNSvInPortB(dwIoBase + MAC_REG_MCFG0, pbyThreshold); + *pbyThreshold = (BYTE)((*pbyThreshold >> 4) & 0x03); +} + +VOID GMACvSetDmaLength(DWORD dwIoBase, BYTE byDmaLength) +{ + BYTE byOrgValue; + + DBG_ASSERT(byDmaLength < 8); + + /* set DCFG0 */ + VNSvInPortB(dwIoBase + MAC_REG_DCFG0, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xF8) | byDmaLength); + VNSvOutPortB(dwIoBase + MAC_REG_DCFG0, byOrgValue); +} + +VOID GMACvGetDmaLength(DWORD dwIoBase, PBYTE pbyDmaLength) +{ + /* get DCFG0 */ + VNSvInPortB(dwIoBase + MAC_REG_DCFG0, pbyDmaLength); + *pbyDmaLength &= 0x07; +} + +VOID GMACvSetLoopbackMode(DWORD dwIoBase, BYTE byLoopbackMode) +{ + BYTE byOrgValue; + + DBG_ASSERT(byLoopbackMode < 3); + + /* set TCR */ + VNSvInPortB(dwIoBase + MAC_REG_TCR, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xFC) | byLoopbackMode); + VNSvOutPortB(dwIoBase + MAC_REG_TCR, byOrgValue); +} + +BOOL GMACbIsInLoopbackMode(DWORD dwIoBase) +{ + BYTE byOrgValue; + + VNSvInPortB(dwIoBase + MAC_REG_TCR, &byOrgValue); + if (BITbIsAnyBitsOn(byOrgValue, TCR_LB1 | TCR_LB0)) + return TRUE; + + return FALSE; +} + +BOOL GMACbIsIn1GMode(DWORD dwIoBase, BYTE byRevId) +{ + UINT ii; + + for (ii = 0; ii < 30; ii++) + PCAvDelayByIO(CB_DELAY_LOOP_WAIT); + + /* NOTE.... */ + /* when link fail, MAC will report in 1G mode, */ + return GMACbIsRegBitsOn(dwIoBase, MAC_REG_PHYSR0, PHYSR0_SPDG); +} + +BOOL GMACbIsIn100MMode(DWORD dwIoBase, BYTE byRevId) +{ + UINT ii; + + for (ii = 0; ii < 30; ii++) + PCAvDelayByIO(CB_DELAY_LOOP_WAIT); + + /* NOTE.... */ + /* when link fail, MAC will report in 1G mode, */ + return GMACbIsRegBitsOff(dwIoBase, MAC_REG_PHYSR0, PHYSR0_SPDG) && + GMACbIsRegBitsOff(dwIoBase, MAC_REG_PHYSR0, PHYSR0_SPD10); +} + +BOOL GMACbIsInFullDuplexMode(DWORD dwIoBase) +{ + return GMACbIsRegBitsOn(dwIoBase, MAC_REG_PHYSR0, PHYSR0_FDPX); +} + +BOOL GMACbIsCableLinkOk(DWORD dwIoBase) +{ + return GMACbIsRegBitsOn(dwIoBase, MAC_REG_PHYSR0, PHYSR0_LINKGD); +} + +VOID GMACvDisableMiiAutoPoll(DWORD dwIoBase) +{ + WORD ww; + BYTE byData; + + /* turn off MAUTO */ + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, 0); + + /* as soon as MIDLE is on, MAUTO is really stoped */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1000); + VNSvInPortB(dwIoBase + MAC_REG_MIISR, &byData); + if (BITbIsBitOn(byData, MIISR_MIIDL)) + break; + } +} + +/* + * NOTE.... + * first, disable MIICR_MAUTO, then + * set MII reg offset to BMSR == 0x01 + * must set offset before re-enable MIICR_MAUTO + */ +VOID GMACvEnableMiiAutoPoll(DWORD dwIoBase) +{ + WORD ww; + BYTE byData; + + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, 0); + + /* polling once before MAUTO is turned on */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, MIIADR_SWMPL); + + /* as soon as MIIDL is on, polling is really completed */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1000); + VNSvInPortB(dwIoBase + MAC_REG_MIISR, &byData); + if (BITbIsBitOn(byData, MIISR_MIIDL)) + break; + } + + /* Turn on MAUTO */ + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, MIICR_MAUTO); + + /* as soon as MIIDL is off, MAUTO is really started */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_MIISR, &byData); + if (BITbIsBitOff(byData, MIISR_MIIDL)) + break; + } +} + +VOID GMACvSetPacketFilter(DWORD dwIoBase, WORD wFilterType) +{ + BYTE byOldRCR; + BYTE byNewRCR = 0; + BYTE byOrgCAMCR, byData; + + + /* modify CAMCR to select MAR regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)(byOrgCAMCR & ~(CAMCR_PS1|CAMCR_PS0)); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* if only in DIRECTED mode, multicast-address will set to zero, */ + /* but if other mode exist (e.g. PROMISCUOUS), multicast-address */ + /* will be open */ + if (BITbIsBitOn(wFilterType, PKT_TYPE_DIRECTED)) { + /* set multicast address to accept none */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR, 0L); + /* PCAvDelayByIO(1); */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR + sizeof(DWORD), 0L); + /* PCAvDelayByIO(1); */ + } + + if (BITbIsAnyBitsOn(wFilterType, PKT_TYPE_PROMISCUOUS | PKT_TYPE_ALL_MULTICAST)) { + /* set multicast address to accept all */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR, 0xFFFFFFFFL); + /* PCAvDelayByIO(1); */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR + sizeof(DWORD), 0xFFFFFFFFL); + /* PCAvDelayByIO(1); */ + } + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); + + + if (BITbIsBitOn(wFilterType, PKT_TYPE_PROMISCUOUS)) + byNewRCR |= (RCR_PROM | RCR_AM | RCR_AB); + + if (BITbIsAnyBitsOn(wFilterType, PKT_TYPE_MULTICAST | PKT_TYPE_ALL_MULTICAST)) + byNewRCR |= RCR_AM; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_BROADCAST)) + byNewRCR |= RCR_AB; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_RUNT)) + byNewRCR |= RCR_AR; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_ERROR)) + byNewRCR |= RCR_SEP; + + VNSvInPortB(dwIoBase + MAC_REG_RCR, &byOldRCR); + if (byNewRCR != (byOldRCR & 0x1F)) { + /* Modify the Receive Command Register */ + byNewRCR |= (BYTE)(byOldRCR & 0xE0); + VNSvOutPortB(dwIoBase + MAC_REG_RCR, byNewRCR); + } +} + +VOID GMACvSaveContext(DWORD dwIoBase, BYTE byRevId, PBYTE pbyCxtBuf) +{ + int ii; + + /* save RCR,TCR,CR,ISR,IMR... */ + for (ii = MAC_REG_PAR; ii < MAC_REG_DEC_BASE_HI; ii++) { + if (ii >= MAC_REG_CR0_CLR && ii <= MAC_REG_CR3_CLR) + continue; + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + } + + /* save MAC_REG_DEC_BASE_HI... */ + for (ii = MAC_REG_DEC_BASE_HI; ii < MAC_REG_ISR_CTL; ii += 4) + VNSvInPortD(dwIoBase + ii, (PDWORD)(pbyCxtBuf + ii)); + + /* save ISR_CTL,ISR,IMR,TDCSR,RDCSR.. */ + for (ii = MAC_REG_ISR_CTL; ii < MAC_REG_TDCSR_CLR; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + + /* save MAC_REG_RDBASE_LO,MAC_REG_TDBASE_LO... */ + for (ii = MAC_REG_RDBASE_LO; ii < MAC_REG_FIFO_TEST0; ii += 4) + VNSvInPortD(dwIoBase + ii, (PDWORD)(pbyCxtBuf + ii)); + + /* save MIICFG... */ + for (ii = MAC_REG_MIICFG; ii < MAC_REG_TBIST; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + + /* save GHIPGSR, WOLCR, PWCFG, TestReg, WOLCG ... */ + for (ii = MAC_REG_CHIPGSR; ii < MAC_REG_WOLCR0_CLR; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + + /* save pattern, mask */ + for (ii = MAC_REG_PATRN_CRC0; ii < MAC_REG_BYTEMSK3_3 + 4; ii += 4) + VNSvInPortD(dwIoBase + ii, (PDWORD)(pbyCxtBuf + ii)); +} + +VOID GMACvRestoreContext(DWORD dwIoBase, BYTE byRevId, PBYTE pbyCxtBuf) +{ + int ii; + + /* restore RCR,TCR,CR,ISR,IMR... */ + for (ii = MAC_REG_PAR; ii < MAC_REG_DEC_BASE_HI; ii++) { + if (ii >= MAC_REG_CR0_CLR && ii <= MAC_REG_CR3_CLR) + continue; + /* except CR0, because we don't want to start chip now */ + if (ii != MAC_REG_CR0_SET) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + } + + /* restore MAC_REG_DEC_BASE_HI... */ + for (ii = MAC_REG_DEC_BASE_HI; ii < MAC_REG_ISR_CTL; ii += 4) { + VNSvOutPortD(dwIoBase + ii, *(PDWORD)(pbyCxtBuf + ii)); + /* PCAvDelayByIO(1); */ + } + + /* restore ISR_CTL,ISR,IMR,TDCSR,RDCSR.. */ + for (ii = MAC_REG_ISR_CTL; ii < MAC_REG_TDCSR_CLR; ii++) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + + /* restore MAC_REG_RDBASE_LO,MAC_REG_TDBASE_LO... */ + for (ii = MAC_REG_RDBASE_LO; ii < MAC_REG_FIFO_TEST0; ii += 4) { + VNSvOutPortD(dwIoBase + ii, *(PDWORD)(pbyCxtBuf + ii)); + /* PCAvDelayByIO(1); */ + } + + /* restore MIICFG... */ + for (ii = MAC_REG_MIICFG; ii < MAC_REG_TBIST; ii++) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + + /* restore GHIPGSR, WOLCR, PWCFG, TestReg, WOLCG ... */ + for (ii = MAC_REG_CHIPGSR; ii < MAC_REG_WOLCR0_CLR; ii++) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + + /* restore pattern, mask */ + for (ii = MAC_REG_PATRN_CRC0; ii < MAC_REG_BYTEMSK3_3 + 4; ii += 4) { + VNSvOutPortD(dwIoBase + ii, *(PDWORD)(pbyCxtBuf + ii)); + /* PCAvDelayByIO(1); */ + } +} + +VOID GMACvTimer0MiniSDelay(DWORD dwIoBase, BYTE byRevId, UINT udelay) +{ + BYTE byData; + + /* Disable Timer0 Interrupt */ + MACvRegBitsOff(dwIoBase, MAC_REG_IMR + 2, (BYTE)(ISR_TMR0I >> 16)); + + /* Set resolution to mini second */ + MACvRegBitsOff(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_TM0US); + + /* set delay time to udelay, unit is mini-second */ + VNSvOutPortW(dwIoBase + MAC_REG_SOFT_TIMER0, (WORD)udelay); + + /* enable timer0 */ + VNSvOutPortB(dwIoBase + MAC_REG_CR1_SET, CR1_TM0EN); + + /* wait for TM0EN self clear */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR1_SET, CR1_TM0EN)) { + /* clear TMR0I */ + VNSvInPortB(dwIoBase + MAC_REG_ISR + 2, &byData); + VNSvOutPortB(dwIoBase + MAC_REG_ISR + 2, byData); + break; + } + } + + /* Enable Timer0 Interrupt */ + MACvRegBitsOn(dwIoBase, MAC_REG_IMR + 2, (BYTE)(ISR_TMR0I >> 16)); +} + +VOID GMACvTimer0MicroSDelay(DWORD dwIoBase, BYTE byRevId, UINT udelay) +{ + BYTE byData; + + /* Notice!!! */ + /* Disable Timer0 Interrupt */ + MACvRegBitsOff(dwIoBase, MAC_REG_IMR + 2, (BYTE)(ISR_TMR0I >> 16)); + + /* Set resolution to micro second */ + MACvRegBitsOn(dwIoBase, MAC_REG_CHIPGCR, CHIPGCR_TM0US); + + /* set delay time to udelay, unit is micro-second */ + VNSvOutPortW(dwIoBase + MAC_REG_SOFT_TIMER0, (WORD)udelay); + + /* enable timer0 */ + VNSvOutPortB(dwIoBase + MAC_REG_CR1_SET, CR1_TM0EN); + + /* wait for TM0EN self clear */ + while (TRUE) { + /* Method 1 -> OK, and safe */ + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR1_SET, CR1_TM0EN)) { + /* clear TMR0I */ + VNSvInPortB(dwIoBase + MAC_REG_ISR + 2, &byData); + VNSvOutPortB(dwIoBase + MAC_REG_ISR + 2, byData); + break; + } + + /* + // Method 2 -> OK, but not safe + VNSvInPortB(dwIoBase + MAC_REG_ISR + 2, &byData); + if (BITbIsBitOn(byData, (BYTE)(ISR_TMR0I >> 16))) { + VNSvOutPortB(dwIoBase + MAC_REG_ISR + 2, byData); + break; + } + */ + /* + // Method 3 -> OK, but not safe + if (MACbIsRegBitsOn(dwIoBase, MAC_REG_ISR + 2, (BYTE)(ISR_TMR0I >> 16))) { + // clear TMR0I + VNSvOutPortB(dwIoBase + MAC_REG_ISR + 2, (BYTE)(ISR_TMR0I >> 16)); + break; + } + */ + } + + /* Notice !!! */ + /* Enable Timer0 Interrupt */ + MACvRegBitsOn(dwIoBase, MAC_REG_IMR + 2, (BYTE)(ISR_TMR0I >> 16)); +} + +BOOL GMACbSoftwareReset(DWORD dwIoBase, BYTE byRevId) +{ + WORD ww; + + /* turn on CR1_SFRST */ + MACvRegBitsOn(dwIoBase, MAC_REG_CR1_SET, CR1_SFRST); + + /* polling till software reset complete */ + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR1_SET, (BYTE)CR1_SFRST)) + break; + } + + if (ww == W_MAX_TIMEOUT) { + /* turn on force reset */ + MACvRegBitsOn(dwIoBase, MAC_REG_CR3_SET, CR3_FORSRST); + /* delay 2ms */ + GMACvTimer0MiniSDelay(dwIoBase, byRevId, 2); + } + return TRUE; +} + +BOOL GMACbSafeSoftwareReset(DWORD dwIoBase, BYTE byRevId) +{ + BYTE abyTmpRegData[0x100]; + BOOL bRetVal; + + /* PATCH.... */ + /* save some important register's value, then do */ + /* reset, then restore register's value */ + + /* save MAC context */ + GMACvSaveContext(dwIoBase, byRevId, abyTmpRegData); + /* do reset */ + bRetVal = GMACbSoftwareReset(dwIoBase, byRevId); + /* restore MAC context, except CR0 */ + GMACvRestoreContext(dwIoBase, byRevId, abyTmpRegData); + + return bRetVal; +} + +BOOL GMACbSafeRxOff(DWORD dwIoBase, BYTE byRevId) +{ + WORD ww; + + /* clear RUN Rx */ + VNSvOutPortB(dwIoBase + MAC_REG_RDCSR_CLR, TRDCSR_RUN); + + MACvRxOff(dwIoBase); + + /* safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR0_SET, (BYTE)CR0_RXON)) + break; + } + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL GMACbSafeTxOff(DWORD dwIoBase, BYTE byRevId) +{ + WORD ww; + + /* clear RUN Tx */ + VNSvOutPortW(dwIoBase + MAC_REG_TDCSR_CLR, 0x1111); + + /* try to safe shutdown TX */ + MACvTxOff(dwIoBase); + + /* safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR0_SET, (BYTE)CR0_TXON)) + break; + } + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL GMACbStop(DWORD dwIoBase) +{ + WORD ww; + + VNSvOutPortB(dwIoBase + MAC_REG_CR0_SET, CR0_STOP); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CR0_SET, (BYTE)(CR0_TXON | CR0_RXON))) + break; + } + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL GMACbSafeStop(DWORD dwIoBase, BYTE byRevId) +{ + if (!GMACbSafeTxOff(dwIoBase, byRevId)) + return FALSE; + if (!GMACbSafeRxOff(dwIoBase, byRevId)) + return FALSE; + if (!GMACbStop(dwIoBase)) + return FALSE; + + return TRUE; +} + +BOOL GMACbShutdown(DWORD dwIoBase, BYTE byRevId) +{ + /* disable MAC IMR */ + MACvIntDisable(dwIoBase); + /* disable MII auto-poll */ + GMACvDisableMiiAutoPoll(dwIoBase); + /* stop the adapter */ + if (!GMACbSafeStop(dwIoBase, byRevId)) + return FALSE; + + return TRUE; +} + +int GMACiWriteVee(DWORD dwIoBase, unsigned char i8Addr, unsigned short i16Data) +{ + int i32Data; + i8Addr = i8Addr & 0xf; + i32Data = i16Data|(i8Addr<<16); + VPCIvWriteD(dwIoBase, Gmac_PCI_VEE_WRITE, i32Data); + return 1; +} + +VOID GMACLoadVEE(DWORD dwIoBase) +{ + unsigned char gmac[32] = { + 0, 0x02, 0x2a, 0xdd, 0x44, 0xb0, 0x7, 0x0, 0x10, + 0x01, 0x6, 0x11, 0x19, 0x31, 0x6, 0x11, 0x1f, 0x10, + 0x0, 0x0, 0x00, 0x01, 0x3, 0x8, 0x01, 0x10, 0x13, + 0x10, 0x40, 0x30, 0x73, 0x21 + }; + /* unsigned char check; */ + DWORD i32Data; + int ii = 0; + + /* fill virtual eeprom */ + for (ii = 0; ii < 16; ii++) + GMACiWriteVee(dwIoBase, ii, *(((unsigned short *)gmac)+ii)); + + /* enable read process */ + VPCIvReadD(dwIoBase, Gmac_PCI_VEE_READ, &i32Data); + i32Data = i32Data | 0x08000000; + VPCIvWriteD(dwIoBase, Gmac_PCI_VEE_READ, i32Data); + /* set SEEPR */ + VPCIvReadD(dwIoBase, Gmac_PCI_VEE_READ, &i32Data); + i32Data = i32Data|0x01000000; + VPCIvWriteD(dwIoBase, Gmac_PCI_VEE_READ, i32Data); + MACvRegBitsOn(dwIoBase, MAC_REG_EECSR, EECSR_RELOAD); + /* wait SEELD */ + while (1) { + VPCIvReadD(dwIoBase, Gmac_PCI_VEE_READ, &i32Data); + if (i32Data & 0x02000000) + break; + } + /* clean SEEPR */ + VPCIvReadD(dwIoBase, Gmac_PCI_VEE_READ, &i32Data); + i32Data = i32Data & ~0x01000000; + VPCIvWriteD(dwIoBase, Gmac_PCI_VEE_READ, i32Data); + /* disable read process */ + VPCIvReadD(dwIoBase, Gmac_PCI_VEE_READ, &i32Data); + i32Data = i32Data & ~0x08000000; + VPCIvWriteD(dwIoBase, Gmac_PCI_VEE_READ, i32Data); +} + +VOID GMACvInitialize(PSAdapterInfo pAdapter, DWORD dwIoBase, BYTE byRevId) +{ + BYTE byTemp; + BYTE check; + + /* clear sticky bits */ + MACvClearStckDS(dwIoBase); + + /* disable force PME-enable */ + + VNSvOutPortB(dwIoBase + MAC_REG_WOLCFG_CLR, WOLCFG_PMEOVR); + /* disable power-event config bit */ + + MACvPwrEvntDisable(dwIoBase); + + /* clear power status */ + VNSvOutPortW(dwIoBase + MAC_REG_WOLSR0_CLR, 0xFFFF); + + /* do reset */ + GMACbSoftwareReset(dwIoBase, byRevId); + + /* for AUTOLD be effect, safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + + VNSvInPortB(dwIoBase + MAC_REG_JMPSR1, &check); + + /* VNSvInPortB(pAdapter->dwIoBase+Gmac_Jumper_Strapping3, &check) */ + /* if (!(check & JMPSR1_J_VEESEL)) + GMACLoadVEE(dwIoBase); + else { */ + if (check & JMPSR1_J_VEESEL) { + /* issue RELOAD in EECSR to reload eeprom */ + MACvRegBitsOn(dwIoBase, MAC_REG_EECSR, EECSR_RELOAD); + + /* wait until EEPROM loading complete */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_EECSR, EECSR_RELOAD)) + break; + } + } + + /* EEPROM reloaded will cause bit 0 in MAC_REG_CFGA turned on. */ + /* it makes MAC receive magic packet automatically. So, driver turn it off. */ + MACvRegBitsOff(dwIoBase, MAC_REG_CFGA, CFGA_PACPI); + + /* set rx-FIFO/DMA threshold */ + /* set rx threshold, 128 bytes */ + /*GMACvSetRxThreshold(dwIoBase, 3);*/ + + /* set DMA length, 16 DWORDs = 64 bytes */ + /*GMACvSetDmaLength(dwIoBase, 1);*/ + + /* suspend-well accept broadcast, multicast */ + VNSvOutPortB(dwIoBase + MAC_REG_WOLCFG_SET, WOLCFG_SAM | WOLCFG_SAB); + + /* back off algorithm use original IEEE standard */ + MACvRegBitsOff(dwIoBase, MAC_REG_CFGB, CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT); + + /* set packet filter */ + /* receive directed and broadcast address */ + GMACvSetPacketFilter(dwIoBase, PKT_TYPE_DIRECTED | PKT_TYPE_BROADCAST); + + /* Eric */ +#if defined(__USE_GMASK1__) + VNSvOutPortD(dwIoBase + MAC_REG_IMR, IMR_MASK_VALUE); +#else + /* Turn on GenIntMask1 */ + VNSvOutPortB(dwIoBase + MAC_REG_CR3_SET, CR3_GINTMSK1); +#endif +#if 0 + VNSvInPortB(dwIoBase, &byTemp); + printf("address0 = %x\n ", byTemp); + VNSvInPortB(dwIoBase + 1, &byTemp); + printf("address1 = %x\n ", byTemp); + VNSvInPortB(dwIoBase + 2, &byTemp); + printf("address2 = %x\n ", byTemp); + VNSvInPortB(dwIoBase + 3, &byTemp); + printf("address3 = %x\n ", byTemp); + VNSvInPortB(dwIoBase + 4, &byTemp); + printf("address4 = %x\n ", byTemp); + VNSvInPortB(dwIoBase + 5, &byTemp); + printf("address6 = %x\n ", byTemp); +#endif + /* Adaptive Interrupt: Init is disabled */ + + /* Select page to interrupt hold timer */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byTemp); + byTemp &= ~(CAMCR_PS0 | CAMCR_PS1); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byTemp); + /* Set Interrupt hold timer = 0 */ + VNSvOutPortB(dwIoBase + MAC_REG_ISR_HOTMR, 0x00); + + /* Select Page to Tx-sup threshold */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byTemp); + byTemp = (BYTE)((byTemp | CAMCR_PS0) & ~CAMCR_PS1); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byTemp); + /* Set Tx interrupt suppression threshold = 0 */ + VNSvOutPortB(dwIoBase + MAC_REG_ISR_TSUPTHR, 0x00); + + /* Select Page to Rx-sup threshold */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byTemp); + byTemp = (BYTE)((byTemp | CAMCR_PS1) & ~CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byTemp); + /* Set Rx interrupt suppression threshold = 0 */ + VNSvOutPortB(dwIoBase + MAC_REG_ISR_RSUPTHR, 0x00); + + /* Select page to interrupt hold timer */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byTemp); + byTemp &= ~(CAMCR_PS0 | CAMCR_PS1); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byTemp); + + /* enable MIICR_MAUTO */ + GMACvEnableMiiAutoPoll(dwIoBase); +} + +VOID GMACvSetVCAM(DWORD dwIoBase, BYTE byAddress, WORD wVID) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM DATA regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR | CAMCR_PS1) & ~CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* enable/select VCAM */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, (BYTE)(CAMADDR_CAMEN | CAMADDR_VCAMSL | byAddress)); + + /* set VCAM data */ + VNSvOutPortW(dwIoBase + MAC_REG_CAM, wVID); + + /* issue write command */ + MACvRegBitsOn(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMWR); + + /* Wait for CAMWR self clear */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMWR)) + break; + } + + /* disable CAMEN */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetMCAM(DWORD dwIoBase, BYTE byAddress, PBYTE pbyData) +{ + BYTE byOrgCAMCR, byData; + /* DWORD dwData; */ + + /* modify CAMCR to select CAM DATA regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR | CAMCR_PS1) & ~CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* enable/select MCAM */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, (BYTE)(CAMADDR_CAMEN | byAddress)); + + /* set MCAM Data */ + VNSvOutPortD(dwIoBase + MAC_REG_CAM, *(PDWORD)pbyData); + /* VNSvInPortD(dwIoBase + MAC_REG_CAM, &dwData); */ + VNSvOutPortW(dwIoBase + MAC_REG_CAM + 4, *(PWORD)(pbyData + 4)); + /* VNSvInPortW(dwIoBase + MAC_REG_CAM + 4, (PWORD)(&dwData)); */ + + /* issue write command */ + MACvRegBitsOn(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMWR); + + /* Wait for CAMWR self clear */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMWR)) + break; + } + + /* disable CAMEN */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetVCAM(DWORD dwIoBase, BYTE byAddress, PWORD pwData) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM DATA regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR | CAMCR_PS1) & ~CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* enable/select VCAM */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, (BYTE)(CAMADDR_CAMEN | CAMADDR_VCAMSL | byAddress)); + + /* issue read command */ + MACvRegBitsOn(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMRD); + + /* Wait for CAMRD self clear */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMRD)) + break; + } + + /* read VID CAM data */ + VNSvInPortW(dwIoBase + MAC_REG_CAM, pwData); + + /* disable CAMEN */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetMCAM(DWORD dwIoBase, BYTE byAddress, PBYTE pbyData) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM DATA regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR | CAMCR_PS1) & ~CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* enable/select MCAM */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, (BYTE)(CAMADDR_CAMEN | byAddress)); + + /* issue read command */ + MACvRegBitsOn(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMRD); + + /* Wait for CAMRD self clear */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_CAMCR, CAMCR_CAMRD)) + break; + } + + VNSvInPortD(dwIoBase + MAC_REG_CAM, (PDWORD)pbyData); + VNSvInPortW(dwIoBase + MAC_REG_CAM + 4, (PWORD)(pbyData + 4)); + + /* disable CAMEN */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetVCAMMask(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + /* DWORD dwData; */ + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select VCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, CAMADDR_VCAMSL); + + VNSvOutPortD(dwIoBase + MAC_REG_CAM, *(PDWORD)pbyMask); + /* VNSvInPortD(dwIoBase + MAC_REG_CAM, &dwData); */ + VNSvOutPortD(dwIoBase + MAC_REG_CAM + 4, *(PDWORD)(pbyMask + 4)); + /* VNSvInPortD(dwIoBase + MAC_REG_CAM + 4, &dwData); */ + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetMCAMMask(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + /* DWORD dwData; */ + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select MCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + VNSvOutPortD(dwIoBase + MAC_REG_CAM, *(PDWORD)pbyMask); + /* VNSvInPortD(dwIoBase + MAC_REG_CAM, &dwData); */ + VNSvOutPortD(dwIoBase + MAC_REG_CAM + 4, *((PDWORD)(pbyMask + 4))); + /* VNSvInPortD(dwIoBase + MAC_REG_CAM + 4, &dwData); */ + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetVCAMMask(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* select VCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, CAMADDR_VCAMSL); + + VNSvInPortD(dwIoBase + MAC_REG_CAM, (PDWORD)pbyMask); + VNSvInPortD(dwIoBase + MAC_REG_CAM + 4, (PDWORD)(pbyMask + 4)); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetMCAMMask(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select MCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + /* select CAM and read CAM mask data (don't need to set CAMEN) */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + VNSvInPortD(dwIoBase + MAC_REG_CAM, (PDWORD)pbyMask); + VNSvInPortD(dwIoBase + MAC_REG_CAM + 4, (PDWORD)(pbyMask + 4)); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetVCAMMaskByBR(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select VCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, CAMADDR_VCAMSL); + + UINT uu; + for (uu = 0; uu < 8; uu++) { + VNSvOutPortB(dwIoBase + MAC_REG_CAM + uu, *(pbyMask + uu)); + /* PATCH...Read back for daley */ + /* VNSvInPortB(dwIoBase + MAC_REG_CAM + uu, &byData); */ + } + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetMCAMMaskByBR(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select MCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + UINT uu; + for (uu = 0; uu < 8; uu++) { + VNSvOutPortB(dwIoBase + MAC_REG_CAM + uu, *(pbyMask + uu)); + /* PATCH...Read back for delay */ + /* VNSvInPortB(dwIoBase + MAC_REG_CAM + uu, &byData); */ + } + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetVCAMMaskByBR(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* select VCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, CAMADDR_VCAMSL); + + UINT uu; + for (uu = 0; uu < 8; uu++) + VNSvInPortB(dwIoBase + MAC_REG_CAM + uu, (pbyMask + uu)); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvGetMCAMMaskByBR(DWORD dwIoBase, PBYTE pbyMask) +{ + BYTE byOrgCAMCR, byData; + + /* modify CAMCR to select CAM MASK regs */ + VNSvInPortB(dwIoBase + MAC_REG_CAMCR, &byOrgCAMCR); + byData = (BYTE)((byOrgCAMCR & ~CAMCR_PS1) | CAMCR_PS0); + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byData); + + /* Select MCAM Mask */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMADDR, 0); + + UINT uu; + for (uu = 0; uu < 8; uu++) + VNSvInPortB(dwIoBase + MAC_REG_CAM + uu, (pbyMask + uu)); + + /* restore to original CAMCR */ + VNSvOutPortB(dwIoBase + MAC_REG_CAMCR, byOrgCAMCR); +} + +VOID GMACvSetTqIndex(DWORD dwIoBase, BYTE byTxQue, WORD wTdIdx) +{ + BYTE byData; + + /* Clear RUN */ + VNSvOutPortB(dwIoBase + MAC_REG_TDCSR_CLR + (byTxQue / 2), (BYTE)(TRDCSR_RUN << ((byTxQue % 2)*4))); + + /* Wait for RUN clear */ + while (TRUE) { + VNSvInPortB(dwIoBase + MAC_REG_TDCSR_SET + (byTxQue / 2), &byData); + if (BITbIsBitOff(byData, TRDCSR_RUN << ((byTxQue % 2)*4))) + break; + } + + /* Set TdIdx */ + VNSvOutPortW(dwIoBase + MAC_REG_TDINDX + byTxQue*2, wTdIdx); + /* Set RUN */ + VNSvOutPortB(dwIoBase + MAC_REG_TDCSR_SET + (byTxQue / 2), (BYTE)(TRDCSR_RUN << ((byTxQue % 2)*4))); +} + +void dumpmac(int iobase) +{ + int i = 0; + DWORD data; + for (i = 0; i < 0x80; i += 4) { + VNSvInPortD(iobase+i, &data); + printf("mac %8x:%8x\n", i, data); + } + return; +} diff --git a/cpu/arm920t/wmt/gmacif.c b/cpu/arm920t/wmt/gmacif.c new file mode 100755 index 0000000..c67dfcf --- /dev/null +++ b/cpu/arm920t/wmt/gmacif.c @@ -0,0 +1,409 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__SETUP_H__) +#include "setup.h" +#endif +#if !defined(__ALLOCT_H__) +#include "alloct.h" +#endif + +#include <net.h> + +/* added by kevin */ +BOOL g_bInit = FALSE; +unsigned int sg_i32GError_status; +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/* static BOOL s_bFind_ConfigGmac(); */ +/*--------------------- Export Variables --------------------------*/ +PVOID g_pvGBufferIndex = (PVOID)GMEMORY_BUFFER_START; + +SCmdParaSet sCmdPara; +extern SAdapterOpts sOptions; +/*--------------------- Export Functions --------------------------*/ + +int +gmac_startio(bd_t *bd) +{ + int ii; + UINT uTotalAdapterNum = 0; + int i32TotalAdapterNum = 0; + UINT uAdapterInWork = 0; + PSAdapterInfo apAdapter[MAX_NET_DEVICE]; + UINT uSTAdapter, uEDAdapter; + PSAdapterInfo pAdapter; + static int gmac_init = 1; + DWORD isr_status; + int i; + BYTE Data; + + if (gmac_init == 0) { + pAdapter = &sg_aGAdapter[0]; + /* 2009/4/20-s add it for check port status change and re-enable MII auto-polling */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_ISR1, 0x80)) + { + VNSvOutPortB(0xd8004025, 0x80); + VNSvOutPortB(0xd8004070, 0x00); + VNSvOutPortB(0xd8004071, 0x80); + while(1) + { + VNSvInPortB(0xd800406d, &Data); + if(Data & 0x80) + break; + } + VNSvOutPortB(0xd8004070, 0x80); + } + /* 2009/4/20-e add it for check port status change and re-enable MII auto-polling */ + if (GMACbIsRegBitsOn(pAdapter->dwIoBase, MAC_REG_ISR1, 0x20)) { + MACvReadISR(pAdapter->dwIoBase, &isr_status); + MACvWriteISR(pAdapter->dwIoBase, isr_status); + if (!GMACbSafeStop(pAdapter->dwIoBase, pAdapter->byRevId)) + return FALSE; + GALCvChainRdrMemory(pAdapter); + GALCvChainTdrMemory(pAdapter, 0); /* chain first data segment */ + /* set init rx/tx descriptor address into chip */ + MACvSetDescBaseHi32(pAdapter->dwIoBase, 0UL); + MACvSetDbfBaseHi16(pAdapter->dwIoBase, 0U); + MACvSetRxDescBaseLo32(pAdapter->dwIoBase, pAdapter->amRxDescRing.dwPAddr); + MACvSetRqIndex(pAdapter->dwIoBase, 0); + MACvSetRqSize(pAdapter->dwIoBase, (WORD)(pAdapter->cbRD - 1)); + + for (i = 0; i < CB_TD_RING_NUM; i++) { + MACvSetTxDescBaseLo32(pAdapter->dwIoBase, pAdapter->aamTxDescRing[i].dwPAddr, i); + GMACvSetTqIndex(pAdapter->dwIoBase, (BYTE)i, 0); + } + MACvSetTqSize(pAdapter->dwIoBase, (WORD)(pAdapter->cbTD - 1)); + /* set current rx/tx descriptor index to 0 */ + pAdapter->uRxDequeDescIdx = 0; + for (i = 0; i < CB_TD_RING_NUM; i++) { + pAdapter->uTxEnqueDescIdx[i] = 0; + pAdapter->uTxDequeDescIdx[i] = 0; + } + pAdapter->idxRxPktStartDesc = 0; + MACvRxOn(pAdapter->dwIoBase); + MACvRxQueueRUN(pAdapter->dwIoBase); + MACvRxQueueWake(pAdapter->dwIoBase); + MACvTxOn(pAdapter->dwIoBase); + MACvTxQueueRUN(pAdapter->dwIoBase, 0); + } + /* 2009/4/20-s update mac address from ethaddr environment variable */ + for(ii = 0; ii < U_ETHER_ADDR_LEN; ii++) + VNSvOutPortB(pAdapter->dwIoBase+MAC_REG_PAR+ii,bd->bi_enetaddr[ii]); + /* 2009/4/20-e update mac address from ethaddr environment variable */ + return 1; + } + gmac_init = 0; + + /* 1.Init option & parameter */ + /*sOptions.ulInitCmds = INIT_CMD_FORCE_PHYRST;*/ + sOptions.ulInitCmds = 0; + sOptions.iRDescNum = 64; + sOptions.iTDescNum = 64; + sOptions.bNoInit = FALSE; + /* set initial value of parameter set */ + sCmdPara.uCardNum = 0; + + /* 2.Confure PCI device configuration space */ + /* s_bFind_ConfigGmac(); */ + + /* 3.Init adapter(find adapter) */ + uTotalAdapterNum = GADPuInitAll(); + + if (uTotalAdapterNum == 0) { + printf("Cannot find the adapter or initialization is failed.\n"); + freemem(); + return -1; + } + + if (uTotalAdapterNum > MAX_NET_DEVICE) { + printf("Cannot support over %d adapters.\n", MAX_NET_DEVICE); + freemem(); + return -1; + } + + /* determine if it's a multi-adapter initialization */ + if (sCmdPara.uCardNum != 0) { + uSTAdapter = (sCmdPara.uCardNum-1); + uEDAdapter = uSTAdapter + 1; + } else { + uSTAdapter = 0; + uEDAdapter = uTotalAdapterNum; + } + + for (ii = uSTAdapter; ii < uEDAdapter; ii++) { + /* WORD wEECheckSum; */ + if (GMACbIsRegBitsOn(sg_aGAdapter[ii].dwIoBase, MAC_REG_CR0_SET, CR0_STRT)) { + /* printf("Adapter %d is already running!\n", ii); */ + /* printf("\n"); */ + } + + /* Check if EEP-less strapping is wrong */ + if (sg_aGAdapter[ii].byRevId >= 0x10) { + BOOL bEEPless; + + /* check the EEPROM path strapping, 0 => serial EEPROM */ + /* 1 => EEPROM from shadow */ + + if (sg_aGAdapter[ii].byRevId < REV_ID_VT3286_A1) { + bEEPless = GMACbIsRegBitsOn( + sg_aGAdapter[ii].dwIoBase, + MAC_REG_JMPSR1, + JMPSR1_J_VEESEL + ); + } else { + bEEPless = GMACbIsRegBitsOn( + sg_aGAdapter[ii].dwIoBase, + MAC_REG_JMPSR1, + JMPSR1_J_VEESEL + ); + } + + if ((!bEEPless)) { + /* it means either customer do the wrong strapping (serial EEP to EEP-less) + or BIOS doesn't copy EEPROM content form persistent storage to shadow */ + /* printf("Adapter %d EEP-less strapping check failed!\n", ii); */ + printf("EEP-less strapping = TRUE\n"); + /* freemem(); */ + /* return ; */ + } else { + if (GMACbIsRegBitsOff(sg_aGAdapter[ii].dwIoBase, MAC_REG_CHIPGSR, 0x10)) { + printf("Adapter %d EEPROM signature is not correct!\n", ii); + printf("\n"); + freemem(); + return -1; + } + } + } /* if */ + } /* for */ + + /* 4.init MAC, MII, MIB, IRQ */ + i32TotalAdapterNum = uTotalAdapterNum; + uTotalAdapterNum = 0; + + for (ii = 0; ii < i32TotalAdapterNum; ii++) { + /* Start driver(create TD/RD and ISR) */ + if (!GADPbBind(&sg_aGAdapter[ii])) { + printf("Initialize adapter fail.\n"); + freemem(); + return -1; + } + apAdapter[uAdapterInWork] = &sg_aGAdapter[ii]; + uAdapterInWork++; + uTotalAdapterNum++; + } + + if (uTotalAdapterNum == 0) { + printf("Cannot find the adapter or initialization is failed.\n"); + freemem(); + return -1; + } + + /* Wait 2s for connection is stable... */ + /* GMACvTimer0MiniSDelay(pAdapter->dwIoBase, pAdapter->byRevId, 3000); */ + /* set parameter */ + pAdapter = &sg_aGAdapter[0]; + /* 2009/4/20-s update mac address from ethaddr environment variable */ + for(ii = 0; ii < U_ETHER_ADDR_LEN; ii++) + VNSvOutPortB(pAdapter->dwIoBase+MAC_REG_PAR+ii,bd->bi_enetaddr[ii]); + /* 2009/4/20-e update mac address from ethaddr environment variable */ + pAdapter->bTxOn = FALSE; + pAdapter->bRandomPktLength = FALSE; + pAdapter->bRandomPktData = FALSE; + pAdapter->bWhenRxCrcErrNoBuf = FALSE; + pAdapter->bWhenRxDataErrNoBuf = FALSE; + pAdapter->bIncPktLength = FALSE; + pAdapter->bSoftwareGenCrc = FALSE; + pAdapter->bTxSinglePacket = FALSE; + pAdapter->bTxContFunTest = FALSE; + /* clear statisic */ + GSTAvClearAllCounter(&pAdapter->scStatistic); + /* set init rx/tx descriptor address into chip, it will return hw rd/td index to 0 */ + MACvSetRqIndex(pAdapter->dwIoBase, 0); + GMACvSetTqIndex(pAdapter->dwIoBase, 0, 0); + + /* start ISR, ISR should has enabled, but we want to make sure */ + MACvIntEnable(pAdapter->dwIoBase, IMR_MASK_VALUE); + MACvStart(pAdapter->dwIoBase); + /* start rx */ + MACvRxOn(pAdapter->dwIoBase); + MACvRxQueueRUN(pAdapter->dwIoBase); + MACvRxQueueWake(pAdapter->dwIoBase); + /* start tx */ + MACvTxOn(pAdapter->dwIoBase); + MACvTxQueueRUN(pAdapter->dwIoBase, 0); + + return 1; +} + +/* +static BOOL s_bFind_ConfigGmac() +{ + SPciDevice pciDevice3119; + + // 1.allocate memory space + NPCIbPCIAlloc(NULL,W_VENDOR_ID,W_DEVICE_ID_3119A,&pciDevice3119); + return TRUE; +} +*/ + +int gmac_send(volatile void *packet, int length) +{ + PBYTE pbyTxDescBuffer; + UINT uCurrTdIdx; + PSTxDesc pTD; + PSAdapterInfo pAdapter = &sg_aGAdapter[0]; + + + uCurrTdIdx = pAdapter->uTxEnqueDescIdx[0]; + pTD = pAdapter->aapTD[0][uCurrTdIdx]; + + /* if tx queue is full */ + if (pTD->m_td0TD0.f1Owner == B_OWNED_BY_CHIP) + return FALSE; + + /* copy buffer */ + pbyTxDescBuffer = (PBYTE)(pAdapter->aapTD[0][uCurrTdIdx]->m_asTxBufs[0].dwTxBufAddrLo); + MEMvSet((PVOID)pbyTxDescBuffer, 0, 60); + MEMvCopy((PVOID)pbyTxDescBuffer, (PVOID)packet, length); + + if (length < MIN_PACKET_LEN) + length = MIN_PACKET_LEN; + + /* Set TD PktLen */ + pTD->m_td0TD0.f14TxPktSize = (WORD)length; + + /* set up data segment */ + pTD->m_td1TD1.f4CMDZ = 2; + pTD->m_asTxBufs[0].f14TxBufSize = (WORD)length; + + /* + * Set Qwner Bit and Que Bit + */ + /* Get Last TdIdx */ + UINT uLastTdIdx = (uCurrTdIdx + pAdapter->cbTD - 1) % pAdapter->cbTD; + + /* Set last Td's que bit */ + if (pAdapter->aapTD[0][uLastTdIdx]->m_td0TD0.f1Owner == B_OWNED_BY_CHIP) { + /* VT3119A0 */ + /* vSetBit((PDWORD)(pAdapter->aapTD[byTxQue][uLastTdIdx])); */ + /* VT3119A1 */ + pAdapter->aapTD[0][uLastTdIdx]->m_asTxBufs[0].f1Que = B_TD_LIST_NOT_END; + } + + /* set tx descriptors owner to chip */ + pTD->m_td0TD0.f1Owner = B_OWNED_BY_CHIP; + + /* post one TD */ + pAdapter->auTxPktPosted[0]++; + + /* Move EnqueTdIdx to next */ + pAdapter->uTxEnqueDescIdx[0] = (WORD)((uCurrTdIdx + 1) % pAdapter->cbTD); + + /* TX */ + MACvTxOn(pAdapter->dwIoBase); + MACvTxQueueRUN(pAdapter->dwIoBase, 0); + MACvTxQueueWake(pAdapter->dwIoBase, 0); + + return 0; +} + +int gmac_receive(void) +{ + PSAdapterInfo pAdapter = &sg_aGAdapter[0]; + int length = 0; + DWORD isr_status; + UINT uCurrDescIdx; + PSRxDesc pCurrRD; + BYTE byRsr0, byRsr1; + + /* 1.store ISR */ + MACvReadISR(pAdapter->dwIoBase, &isr_status); + + /* 2.disable IMR */ + MACvIntDisable(pAdapter->dwIoBase); + /* 3.clear ISR */ + MACvWriteISR(pAdapter->dwIoBase, isr_status); + /* 4.handle received packets until owner==chip */ + while (TRUE) { + uCurrDescIdx = pAdapter->uRxDequeDescIdx; + pCurrRD = pAdapter->apRD[uCurrDescIdx]; + byRsr0 = pCurrRD->m_rd0RD0.byRSR0; + byRsr1 = pCurrRD->m_rd0RD0.byRSR1; + + /* if the RD is owned by the chip, we are done. */ + if (pCurrRD->m_rd0RD0.f1Owner == B_OWNED_BY_CHIP) + break; + + if ((pCurrRD->m_rd0RD0.byRSR1 & RSR1_RXOK)) { + NetReceive((volatile uchar *)pCurrRD->m_dwRxBufAddrLo, pCurrRD->m_rd0RD0.f14RMBC-4); + length += (pCurrRD->m_rd0RD0.f14RMBC-4); + } else { + printf("receive error status:%02X %02X%\n", + pCurrRD->m_rd0RD0.byRSR1, pCurrRD->m_rd0RD0.byRSR0); + /* handler will do later */ + } + /* reset RD own bit */ + pCurrRD->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; + + /* increase to next RD */ + pAdapter->uRxDequeDescIdx = (++pAdapter->uRxDequeDescIdx)%pAdapter->cbRD; + } + + /* 5.enable IMR */ + MACvIntEnable(pAdapter->dwIoBase, IMR_MASK_VALUE); + + return length; +} + +void gmac_halt(void) +{ + if (g_bInit) + GADPbShutdown(&sg_aGAdapter[0]); + return; +} + +void mii_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + PSAdapterInfo pAdapter; + pAdapter = &sg_aGAdapter[0]; + GMIIbReadEmbeded(pAdapter->dwIoBase, pAdapter->byRevId, addr, value); +#if MACDBG + printf("%02X %02X %04X\n", addr, reg, value); +#endif +} +void mii_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + PSAdapterInfo pAdapter; + pAdapter = &sg_aGAdapter[0]; + GMIIbWriteEmbeded(pAdapter->dwIoBase, pAdapter->byRevId, addr, value); +#if MACDBG + printf("%02X %02X %04X\n", addr, reg, value); +#endif +} diff --git a/cpu/arm920t/wmt/gmacif.h b/cpu/arm920t/wmt/gmacif.h new file mode 100755 index 0000000..db1c94e --- /dev/null +++ b/cpu/arm920t/wmt/gmacif.h @@ -0,0 +1,64 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef _GMACIF_H_ +#define _GMACIF_H_ + + +/*--------------------- Export Definitions -------------------------*/ +#define BA_MAC0 0xd8004000 /* MAC0 Base Address */ +#define BA_MAC1 0xd8005000 /* MAC1 Base Address */ +#define GMEMORY_BUFFER_START 0x03C00000 /* Start address of allocated memory buffer */ +#define MAX_NET_DEVICE 4 /* max. # of the devices */ +#define W_MAX_TIMEOUT 0x0FFFU +#define MACDBG 0 /* Switch to control debug message (0/1 = Disable/Enable) */ + +#define PCI_Configuration_Space_Offset 0x100 +#define VEE 0x5c +#define VMSTS 0x7c +#define MaxTimeOut 1000 + +#define __MMIO__ +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +#include <asm/u-boot.h> + +int gmac_startio(bd_t *bd); +int gmac_send(volatile void *packet, int length); +int gmac_receive(void); +void gmac_halt(void); +void mii_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value); +void mii_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) ; + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* _GMACIF_H_ */ diff --git a/cpu/arm920t/wmt/gmib.c b/cpu/arm920t/wmt/gmib.c new file mode 100755 index 0000000..27a84a9 --- /dev/null +++ b/cpu/arm920t/wmt/gmib.c @@ -0,0 +1,453 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MIB_H__) +#include "mib.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +VOID GSTAvClearAllCounter(PSStatCounter pStatistic) +{ + /* set memory to zero */ + MEMvSet(pStatistic, 0, sizeof(SStatCounter)); +} + +VOID GSTAvClearAllSwMibCounter(PSMib2Counter pMib2Counter) +{ + /* set memory to zero */ + /* Not work ??? */ + /*ZERO_MEMORY(pMib2Counter, sizeof(PSMib2Counter)); */ + + pMib2Counter->ifOutOctets = 0; + pMib2Counter->ifOutNUcastPkts = 0; + pMib2Counter->ifOutUcastPkts = 0; + pMib2Counter->ifOutDiscards = 0; + pMib2Counter->ifOutErrors = 0; +} + +VOID GSTAvUpdateEsrStatCounter(PSStatCounter pStatistic, BYTE byEsr, BOOL bTx) +{ + if (bTx) { + if (BITbIsBitOn(byEsr, TXESR_TDSTR)) + pStatistic->dwTxEsrTDStrErr++; + if (BITbIsBitOn(byEsr, TXESR_TDRBS)) + pStatistic->dwTxEsrTDRBusErr++; + if (BITbIsBitOn(byEsr, TXESR_TDWBS)) + pStatistic->dwTxEsrTDWBusErr++; + if (BITbIsBitOn(byEsr, TXESR_TFDBS)) + pStatistic->dwTxEsrDmaBusErr++; + } else { + if (BITbIsBitOn(byEsr, RXESR_RDSTR)) + pStatistic->dwRxEsrRDStrErr++; + if (BITbIsBitOn(byEsr, RXESR_RDRBS)) + pStatistic->dwRxEsrRDRBusErr++; + if (BITbIsBitOn(byEsr, RXESR_RDWBS)) + pStatistic->dwRxEsrRDWBusErr++; + if (BITbIsBitOn(byEsr, RXESR_RFDBS)) + pStatistic->dwRxEsrDmaBusErr++; + } +} + +VOID GSTAvUpdateIsrStatCounter(PSStatCounter pStatistic, DWORD dwIsr, WORD wEsr) +{ + /* + * ABNORMAL interrupt + * not any IMR bit invoke irq + */ + if (dwIsr == 0) { + pStatistic->dwIsrUnknown++; + return; + } + + if (BITbIsBitOn(dwIsr, ISR_PRXI)) { + pStatistic->dwIsrRxOK++; + /* PATCH.... */ + /* if rx OK, reset packet-race counter */ + pStatistic->dwIsrContinuePktRace = 0; + /* if rx OK, reset no-buffer counter */ + pStatistic->dwIsrContinueNoBuf = 0; + } + if (BITbIsBitOn(dwIsr, ISR_PTXI)) + pStatistic->dwIsrTxOK++; + + if (BITbIsBitOn(dwIsr, ISR_PPRXI)) + pStatistic->dwIsrPRxOK++; + if (BITbIsBitOn(dwIsr, ISR_PPTXI)) + pStatistic->dwIsrPTxOK++; + + if (BITbIsBitOn(dwIsr, ISR_TXWB0I)) + pStatistic->dwIsrTxWB0I++; + if (BITbIsBitOn(dwIsr, ISR_TXWB1I)) + pStatistic->dwIsrTxWB1I++; + + if (BITbIsBitOn(dwIsr, ISR_RACEI)) { + pStatistic->dwIsrRxPktRace++; + /* PATCH.... */ + /* if irq continuous invoked by packet-race, plus counter */ + pStatistic->dwIsrContinuePktRace++; + } + if (BITbIsBitOn(dwIsr, ISR_LSTEI)) { + pStatistic->dwIsrRxNoBuf++; + /* PATCH.... */ + /* if irq continuous invoked by no-buffer, plus counter */ + pStatistic->dwIsrContinueNoBuf++; + } + + if (BITbIsBitOn(dwIsr, ISR_OVFI)) + pStatistic->dwIsrRxFifoOvfl++; + if (BITbIsBitOn(dwIsr, ISR_FLONI)) + pStatistic->dwIsrRxFlowOn++; + + if (BITbIsBitOn(dwIsr, ISR_LSTPEI)) + pStatistic->dwIsrRxNoBufP++; + if (BITbIsBitOn(dwIsr, ISR_SRCI)) + pStatistic->dwIsrLinkStatusChg++; + + /* update counters for MISR */ + if (BITbIsBitOn(dwIsr, ISR_TMR0I)) + pStatistic->dwMisrSoftTimer0++; + if (BITbIsBitOn(dwIsr, ISR_TMR1I)) + pStatistic->dwMisrSoftTimer1++; + if (BITbIsBitOn(dwIsr, ISR_PWEI)) + pStatistic->dwMisrPWE++; + if (BITbIsBitOn(dwIsr, ISR_PHYI)) + pStatistic->dwMisrPhyStatChg++; + if (BITbIsBitOn(dwIsr, ISR_SHDNI)) + pStatistic->dwMisrShutDown++; + if (BITbIsBitOn(dwIsr, ISR_MIBFI)) + pStatistic->dwMisrMibOvfl++; + if (BITbIsBitOn(dwIsr, ISR_UDPI)) + pStatistic->dwMisrUserDef++; + + if (BITbIsBitOn(dwIsr, ISR_TXSTLI)) { + pStatistic->dwMisrTxDmaErr++; + GSTAvUpdateEsrStatCounter(pStatistic, (BYTE)wEsr, TRUE); + } + if (BITbIsBitOn(dwIsr, ISR_RXSTLI)) { + pStatistic->dwMisrRxDmaErr++; + GSTAvUpdateEsrStatCounter(pStatistic, (BYTE)(wEsr>>8), FALSE); + } +} + +VOID GSTAvUpdateRDStatCounter( + PSStatCounter pStatistic, + PSRxDesc prdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength + ) +{ + pbyBuffer = pbyBuffer; + BYTE byRSR0 = prdCurr->m_rd0RD0.byRSR0; + BYTE byRSR1 = prdCurr->m_rd0RD0.byRSR1; + + /* increase rx packet count */ + pStatistic->dwRsrRxPacket++; + pStatistic->dwRsrRxOctet += cbFrameLength; + + if (BITbIsBitOn(byRSR0, RSR0_CRC)) + pStatistic->dwRsrCRCErr++; + if (BITbIsBitOn(byRSR0, RSR0_FAE)) + pStatistic->dwRsrFrmAlgnErr++; + if (BITbIsBitOn(byRSR0, RSR0_CE)) + pStatistic->dwRsrCheckSumErr++; + if (BITbIsBitOn(byRSR0, RSR0_RL)) + pStatistic->dwRsrLengthErr++; + if (BITbIsBitOn(byRSR0, RSR0_RXER)) + pStatistic->dwRsrPCSSymErr++; + if (BITbIsBitOn(byRSR0, RSR0_SNTAG)) + pStatistic->dwRsrSNTAG++; + if (BITbIsBitOn(byRSR0, RSR0_DETAG)) + pStatistic->dwRsrDETAG++; + + if (BITbIsBitOn(byRSR1, RSR1_RXOK)) + pStatistic->dwRsrOK++; + + if (BITbIsBitOn(byRSR1, RSR1_VTAG)) + pStatistic->dwRsrRxTagFrame = (DWORD)(prdCurr->m_rd1RD1.wPQTAG); + else + pStatistic->dwRsrRxTagFrame = 0x0; + + if (BITbIsBitOn(byRSR1, RSR0_VIDM)) + pStatistic->dwRsrVIDMiss++; + + if (BITbIsBitOn(byRSR1, RSR1_VTAG)) + pStatistic->dwRsrRxTag++; + + if (BITbIsBitOn(byRSR1, RSR1_PFT)) + pStatistic->dwRsrPerfectMatch++; + + if (cbFrameLength >= U_ETHER_ADDR_LEN) { + /* + if (IS_BROADCAST_ADDRESS(pbyBuffer)) + pStatistic->dwRsrBroadcast++; + else if (IS_MULTICAST_ADDRESS(pbyBuffer)) + pStatistic->dwRsrMulticast++; + else + pStatistic->dwRsrDirected++; + */ + if (BITbIsBitOn(byRSR1, RSR1_BAR)) + pStatistic->dwRsrBroadcast++; + if (BITbIsBitOn(byRSR1, RSR1_MAR)) + pStatistic->dwRsrMulticast++; + if (BITbIsBitOn(byRSR1, RSR1_PHY)) + pStatistic->dwRsrDirected++; + } + + if (cbFrameLength == MIN_PACKET_LEN + 4) + pStatistic->dwRsrRxFrmLen64++; + else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) + pStatistic->dwRsrRxFrmLen65_127++; + else if ((128 <= cbFrameLength) && (cbFrameLength <= 255)) + pStatistic->dwRsrRxFrmLen128_255++; + else if ((256 <= cbFrameLength) && (cbFrameLength <= 511)) + pStatistic->dwRsrRxFrmLen256_511++; + else if ((512 <= cbFrameLength) && (cbFrameLength <= 1023)) + pStatistic->dwRsrRxFrmLen512_1023++; + else if ((1024 <= cbFrameLength) && (cbFrameLength <= MAX_PACKET_LEN + 4)) + pStatistic->dwRsrRxFrmLen1024_1518++; +} + +VOID GSTAvUpdateRDStatCounterEx( + PSStatCounter pStatistic, + PSRxDesc prdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength, + DWORD dwHwCRC32, + DWORD dwSwCRC32 + ) +{ + GSTAvUpdateRDStatCounter(pStatistic, prdCurr, pbyBuffer, cbFrameLength); + + /* rx length */ + pStatistic->dwCntRxFrmLength = cbFrameLength; + /* Rx Hardware generate CRC32 */ + pStatistic->dwHwCRC32 = dwHwCRC32; + /* Rx Software generate CRC32 */ + pStatistic->dwSwCRC32 = dwSwCRC32; + + /* DRV32.LIB [1.05] */ + if ((dwHwCRC32 != dwSwCRC32) && + (dwSwCRC32 != 0x00000000UL)) + pStatistic->dwCntRxDataErr++; + + /* rx pattern, we just see 16 bytes for sample */ + MEMvCopy((PVOID)pStatistic->abyCntRxPattern, (PVOID)pbyBuffer, 16); +} + +VOID GSTAvUpdateTDStatCounter( + PSStatCounter pStatistic, + PSMib2Counter pMib2Counter, + PSTxDesc ptdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength + ) +{ + BYTE byTSR0 = ptdCurr->m_td0TD0.byTSR0; + BYTE byTSR1 = ptdCurr->m_td0TD0.byTSR1; + + /* increase tx packet count */ + pStatistic->dwTsrTxPacket++; + pStatistic->dwTsrTxOctet += cbFrameLength; + pMib2Counter->ifOutOctets += cbFrameLength; + + if (BITbIsBitOn(byTSR0, TSR0_COLS)) { + pStatistic->dwTsrCollision++; + pStatistic->dwTsrTotalColRetry += (byTSR0 & 0x0F); + + if ((byTSR0 & 0x0F) == 1) + pStatistic->dwTsrOnceCollision++; + else + pStatistic->dwTsrMoreThanOnceCollision++; + } + + if (BITbIsBitOff(byTSR1, TSR1_TERR | TSR1_LNKFL | TSR1_CRS | TSR1_CDH)) + pStatistic->dwTsrOK++; + else { + if (BITbIsBitOn(byTSR0, TSR0_ABT)) + pStatistic->dwTsrAbort++; + if (BITbIsBitOn(byTSR0, TSR0_OWC)) + pStatistic->dwTsrLateCollision++; + if (BITbIsBitOn(byTSR0, TSR0_OWT)) + pStatistic->dwTsrJumboAbort++; + + if (BITbIsBitOn(byTSR1, TSR1_CDH)) + pStatistic->dwTsrHeartBeat++; + if (BITbIsBitOn(byTSR1, TSR1_CRS)) + pStatistic->dwTsrCarrierLost++; + if (BITbIsBitOn(byTSR1, TSR1_LNKFL)) + pStatistic->dwTsrLNKFL++; + if (BITbIsBitOn(byTSR1, TSR1_SHDN)) + pStatistic->dwTsrShutDown++; + if (BITbIsBitOn(byTSR1, TSR1_TERR)) + pStatistic->dwTsrErr++; + } + + if (cbFrameLength >= U_ETHER_ADDR_LEN) { + if (IS_BROADCAST_ADDRESS(pbyBuffer)) { + pStatistic->dwTsrBroadcast++; + pMib2Counter->ifOutNUcastPkts++; + } else if (IS_MULTICAST_ADDRESS(pbyBuffer)) { + pStatistic->dwTsrMulticast++; + pMib2Counter->ifOutNUcastPkts++; + } else { + pStatistic->dwTsrDirected++; + pMib2Counter->ifOutUcastPkts++; + } + } +} + +VOID GSTAvUpdateTDStatCounterEx( + PSStatCounter pStatistic, + PSMib2Counter pMib2Counter, + PSTxDesc ptdCurr, + PBYTE pbyBuffer, + DWORD cbFrameLength + ) +{ + UINT uPktLength = (UINT)cbFrameLength; + + GSTAvUpdateTDStatCounter(pStatistic, pMib2Counter, ptdCurr, pbyBuffer, uPktLength); + + /* tx length */ + pStatistic->dwCntTxBufLength = uPktLength; + /* tx pattern, we just see 16 bytes for sample */ + MEMvCopy((PVOID)pStatistic->abyCntTxPattern, (PVOID)pbyBuffer, 16); +} + +VOID GSTAvUpdateTDStatCounterTq0( + PSStatCounter pStatistic, + PSTxDesc ptdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength + ) +{ + BYTE byTSR0 = ptdCurr->m_td0TD0.byTSR0; + BYTE byTSR1 = ptdCurr->m_td0TD0.byTSR1; + UINT uPktLength = (UINT)cbFrameLength; + + /* tx length */ + pStatistic->dwCntTxBufLength = uPktLength; + /* tx pattern, we just see 16 bytes for sample */ + MEMvCopy((PVOID)pStatistic->abyCntTxPattern, (PVOID)pbyBuffer, 16); + + /* increase tx packet count */ + pStatistic->dwTsrTxPacket++; + pStatistic->dwTsrTxOctet += cbFrameLength; + + if (BITbIsBitOn(byTSR0, TSR0_COLS)) { + pStatistic->dwTsrCollision++; + pStatistic->dwTsrTotalColRetry += (byTSR0 & 0x0F); + + if ((byTSR0 & 0x0F) == 1) + pStatistic->dwTsrOnceCollision++; + else + pStatistic->dwTsrMoreThanOnceCollision++; + } + + if (BITbIsBitOff(byTSR1, TSR1_TERR | TSR1_LNKFL | TSR1_CRS | TSR1_CDH)) + pStatistic->dwTsrOK++; + else { + if (BITbIsBitOn(byTSR0, TSR0_ABT)) + pStatistic->dwTsrAbort++; + if (BITbIsBitOn(byTSR0, TSR0_OWC)) + pStatistic->dwTsrLateCollision++; + if (BITbIsBitOn(byTSR0, TSR0_OWT)) + pStatistic->dwTsrJumboAbort++; + + if (BITbIsBitOn(byTSR1, TSR1_CDH)) + pStatistic->dwTsrHeartBeat++; + if (BITbIsBitOn(byTSR1, TSR1_CRS)) + pStatistic->dwTsrCarrierLost++; + if (BITbIsBitOn(byTSR1, TSR1_LNKFL)) + pStatistic->dwTsrLNKFL++; + if (BITbIsBitOn(byTSR1, TSR1_SHDN)) + pStatistic->dwTsrShutDown++; + if (BITbIsBitOn(byTSR1, TSR1_TERR)) + pStatistic->dwTsrErr++; + } + + if (cbFrameLength >= U_ETHER_ADDR_LEN) { + if (IS_BROADCAST_ADDRESS(pbyBuffer)) + pStatistic->dwTsrBroadcast++; + else if (IS_MULTICAST_ADDRESS(pbyBuffer)) + pStatistic->dwTsrMulticast++; + else + pStatistic->dwTsrDirected++; + } +} + +VOID GSTAvClearHWMIBCounter(DWORD dwIoBase) +{ + MACvRegBitsOn(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBFRZ); + MACvRegBitsOn(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBCLR); + /* wait until MIB counter clear done */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBCLR)) + break; + } +} + +VOID GSTAvEnableHWMIBCounter(DWORD dwIoBase) +{ + MACvRegBitsOff(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBFRZ); +} + +VOID GSTAvDisableHWMIBCounter(DWORD dwIoBase) +{ + MACvRegBitsOn(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBFRZ); +} + +VOID GSTAvUpdateHWMIBCounter(DWORD dwIoBase, PSHWMibCounter psHWCounters) +{ + DWORD dwTmp = 0; + PDWORD pdwTmp = (PDWORD)psHWCounters; + int ii; + /* flush real-time counter value to MIB SRAM */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBFLSH); + + /* wait until flush done */ + while (TRUE) { + if (GMACbIsRegBitsOff(dwIoBase, MAC_REG_MIBCR, MIBCR_MIBFLSH)) + break; + } + + /* return MIB pointer to 0 */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIBCR, MIBCR_MPTRINI); + + for (ii = 0; ii < MAX_HW_MIB_COUNTER; ii++, pdwTmp++) { + VNSvInPortD(dwIoBase + MAC_REG_MIBREAD, &dwTmp); + *pdwTmp += dwTmp & 0x00FFFFFFUL; + } +} diff --git a/cpu/arm920t/wmt/gmii.c b/cpu/arm920t/wmt/gmii.c new file mode 100755 index 0000000..10fc27b --- /dev/null +++ b/cpu/arm920t/wmt/gmii.c @@ -0,0 +1,535 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* #include <conio.h> */ + +/* #if !defined(__UPC_H__) */ +/* #include "upc.h" */ +/* #endif */ +#if !defined(__UASSERT_H__) +#include "uassert.h" +#endif +/* #if !defined(__TMACRO_H__) */ +/* #include "tmacro.h" */ +/* #endif */ +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__MII_H__) +#include "mii.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ +#define CB_DELAY_MII_LB_STABLE (1000) + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: Read a word from MII, by embeded programming + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byRevId - chip revision id + * byMiiAddr - address of register in MII + * Out: + * pwData - data read + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL GMIIbReadEmbeded(DWORD dwIoBase, BYTE byRevId, BYTE byMiiAddr, PWORD pwData) +{ + byRevId = byRevId; + WORD ww; + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + GMACvDisableMiiAutoPoll(dwIoBase); + + /* MII reg offset */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, byMiiAddr); + + /* turn on MIICR_RCMD */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIICR, MIICR_RCMD); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1000); + if (BITbIsBitOff(GMACbyReadMIICR(dwIoBase), MIICR_RCMD)) + break; + } + + /* get MII data */ + VNSvInPortW(dwIoBase + MAC_REG_MIIDATA, pwData); + + GMACvEnableMiiAutoPoll(dwIoBase); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +/* + * Description: Write a word to MII, by embeded programming + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byRevId - chip revision id + * byMiiAddr - address of register in MII + * wData - data to write + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL GMIIbWriteEmbeded(DWORD dwIoBase, BYTE byRevId, BYTE byMiiAddr, WORD wData) +{ + byRevId = byRevId; + WORD ww; + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + GMACvDisableMiiAutoPoll(dwIoBase); + + /* MII reg offset */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, byMiiAddr); + + /* set MII data */ + VNSvOutPortW(dwIoBase + MAC_REG_MIIDATA, wData); + + /* turn on MIICR_WCMD */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIICR, MIICR_WCMD); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1000); + if (BITbIsBitOff(GMACbyReadMIICR(dwIoBase), MIICR_WCMD)) + break; + } + + GMACvEnableMiiAutoPoll(dwIoBase); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL GMIIbIsRegBitsOn(DWORD dwIoBase, BYTE byRevId, BYTE byMiiAddr, WORD wTestBits) +{ + static WORD wOrgData; + + GMIIbReadEmbeded(dwIoBase, byRevId, byMiiAddr, &wOrgData); + return BITbIsAllBitsOn(wOrgData, wTestBits); +} + +BOOL GMIIbIsRegBitsOff(DWORD dwIoBase, BYTE byRevId, BYTE byMiiAddr, WORD wTestBits) +{ + static WORD wOrgData; + + GMIIbReadEmbeded(dwIoBase, byRevId, byMiiAddr, &wOrgData); + return BITbIsAllBitsOff(wOrgData, wTestBits); +} + +BOOL GMIIbReadAllRegs(DWORD dwIoBase, BYTE byRevId, PSMiiReg pMiiRegs) +{ + UINT ii; + PWORD pwData; + UINT cbWords; + + pwData = (PWORD)pMiiRegs; + cbWords = sizeof(SMiiReg) / sizeof(WORD); + + /* ii = Reg Address */ + for (ii = 0; ii < cbWords; ii++) { + if (!GMIIbReadEmbeded(dwIoBase, byRevId, (BYTE)ii, pwData)) + return FALSE; + pwData++; + } + + return TRUE; +} + +VOID GMIIvWaitForNwayCompleted(DWORD dwIoBase, BYTE byRevId) +{ + UINT uu; + + /* delay about 8 sec. */ + /* wait for AUTO-NEGO to complete (may never complete if */ + /* no link), after that then, we can get correct link status */ + /* NOTE: because I have no timer, so looping is used, */ + /* if timer is available in your OS, use timer */ + /* in stead of looping */ + + /* wait for BMSR_AUTOCM to off */ + for (uu = 0; uu < CB_MAX_COUNT_AUTO_COMPLETE; uu++) { + if (GMIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMSR, BMSR_AUTOCM)) + break; + } + /* wait for BMSR_AUTOCM to on */ + /* NOTE.... read BMSR_AUTOCM bit will also clear BMSR_LNK bit */ + for (uu = 0; uu < CB_MAX_COUNT_AUTO_COMPLETE; uu++) { + /* if AUTO-NEGO completed, then go out this loop */ + /* otherwise, count down to time out */ + if (GMIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMSR, BMSR_AUTOCM)) + break; + } +} + +VOID GMIIvSetLoopbackMode(DWORD dwIoBase, BYTE byRevId, BYTE byLoopbackMode) +{ + /* handle AUTO-NEGO */ + switch (byLoopbackMode) { + case MII_LB_NONE: + if(GMIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK)) { + /* turn off MII loopback */ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* must turn on AUTO-NEGO after turn off BMCR_LBK, otherwise */ + /* the AUTO-NEGO process will never end in some PHY (e.g. ESI...) */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + }/* else do not thing */ + break; + + case MII_LB_INTERNAL: + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* select 1000M */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED1G); + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED100); + break; + + case MII_LB_ISO: + /* we achieve isolation by do loopback in MII not in Transceiver */ + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* select 1000M */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED1G); + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED100); + break; + + default: + DBG_ASSERT(FALSE); + break; + } + + /* wait for MII loopback to stable */ + PCAvDelayByIO(CB_DELAY_MII_LB_STABLE); +} + +VOID GMIIvSetDuplexMode(DWORD dwIoBase, BYTE byRevId, BOOL bFullDuplexOn) +{ + /* when force duplex mode, */ + /* AUTO-NEGO should off */ + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + + if (bFullDuplexOn) + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_FDX); + else + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_FDX); +} + +VOID GMIIvSetSpeedMode(DWORD dwIoBase, BYTE byRevId, BYTE bySpeed) +{ + /* when force speed mode, */ + /* AUTO-NEGO should off */ + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + + switch (bySpeed) { + case MII_SPD_1000: + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED1G); + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED100); + break; + case MII_SPD_100: + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED1G); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED100); + break; + case MII_SPD_10: + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED1G); + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED100); + break; + + default: + DBG_ASSERT(FALSE); + break; + } +} + +BOOL GMIIbIsAutoNegotiationOn(DWORD dwIoBase, BYTE byRevId) +{ + return GMIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_AUTO); +} + +/* +BOOL MIIbIsInFullDuplexMode(DWORD dwIoBase, BYTE byRevId) +{ + // if in AUTO-NEGO mode + if (byRevId>=REV_ID_VT3106J_A0) + return MACbIsRegBitsOn(dwIoBase, MAC_REG_MIISR, MIISR_N_FDX); + + if (MIIbIsAutoNegotiationOn(dwIoBase, byRevId)) { + + // if my TX_FD on, check both TX_FD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TXFD)) { + // partner's TX_FD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TXFD)) + return TRUE; + } + + // if my T4 on, check both T4 + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_T4)) { + // partner's T4 + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_T4)) + return FALSE; + } + + // if my TX_HD on, check both TX_HD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TX)) { + // partner's TX_HD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TX)) + return FALSE; + } + + // if my 10_FD on, check both 10_FD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_10FD)) { + // partner's 10_FD + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_10FD)) + return TRUE; + } + + // if all above is not, then it would be 10_HD or no link + // both case will be half duplex + return FALSE; + } else { + // if in force mode + if (MIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_FDX)) + return FALSE; + } + + return TRUE; +} +*/ + +BOOL GMIIbSafeSoftwareReset(DWORD dwIoBase, BYTE byRevId) +{ + WORD ww; + + /* turn on reset only, do not write other bits */ + GMIIbWriteEmbeded(dwIoBase, byRevId, MII_REG_BMCR, BMCR_RESET); + + /* polling till MII reset complete */ + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (GMIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_RESET)) + break; + } + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +/* + * Description: Scan how many PHY in MII bus, and put PYH id + * in the pbyPhyId array + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byRevId - chip revision id + * Out: + * puTotalPhyNum - total # of PHY + * pbyPhyId - PHY id array + * + * NOTE: size of pbyPhyId should larger than MAX_PHY_DEVICE + * otherwise, memory will corrupt + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +VOID GMIIvScanAllPhy(DWORD dwIoBase, BYTE byRevId, PBYTE pbyPhyId, PUINT puTotalPhyNum) +{ + BYTE byOrgMIIADR; + BYTE byOrgMIICR; + DWORD dwPhyCmrId; + UINT uPhyArrayIdx; + BYTE byPhyId, byOrgPhyId; + + /* keep original MIICR value */ + VNSvInPortB(dwIoBase + MAC_REG_MIIADR, &byOrgMIIADR); + VNSvInPortB(dwIoBase + MAC_REG_MIICR, &byOrgMIICR); + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + GMACvDisableMiiAutoPoll(dwIoBase); + + /* keep original phy ID */ + byOrgPhyId = GMACbyGetPhyId(dwIoBase); + + /* scan all PHY */ + uPhyArrayIdx = 0; + /* PHI id 0 is not a valid id */ + for (byPhyId = 1; byPhyId < MAX_PHY_DEVICE; byPhyId++) { + GMACvSetPhyId(dwIoBase, byRevId, byPhyId); + + /* detect if PHY exist? */ + MIIvReadPhyCmrId(dwIoBase, byRevId, &dwPhyCmrId); + if ((dwPhyCmrId != 0xFFFFFFFFUL) && (dwPhyCmrId != 0UL)) { + pbyPhyId[uPhyArrayIdx] = byPhyId; + uPhyArrayIdx++; + } + } + *puTotalPhyNum = uPhyArrayIdx; + + /* restore original phy id */ + GMACvSetPhyId(dwIoBase, byRevId, byOrgPhyId); + + /* restore MIICR */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, byOrgMIIADR); + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, byOrgMIICR); +} + +VOID GMIIvSetActiveForcedPhy(DWORD dwIoBase, BYTE byRevId, PBYTE pbyPhyId, UINT uTotalPhyNum, BYTE byPhyId) +{ + UINT uu; + BYTE byOrgMIIADR; + BYTE byOrgMIICR; + + /* keep original MIICR value */ + VNSvInPortB(dwIoBase + MAC_REG_MIIADR, &byOrgMIIADR); + VNSvInPortB(dwIoBase + MAC_REG_MIICR, &byOrgMIICR); + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + GMACvDisableMiiAutoPoll(dwIoBase); + + /* iso all PHY */ + for (uu = 0; uu < uTotalPhyNum; uu++) { + GMACvSetPhyId(dwIoBase, byRevId, pbyPhyId[uu]); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_ISO); + } + + /* finally, set correct PHY id */ + GMACvSetPhyId(dwIoBase, byRevId, byPhyId); + /* active this PHY */ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_ISO); + + /* restore MIICR */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, byOrgMIIADR); + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, byOrgMIICR); +} + +/* if no PHY linked, return FALSE */ +BOOL GMIIbSetActiveLinkedPhy(DWORD dwIoBase, BYTE byRevId, PBYTE pbyPhyId, UINT uTotalPhyNum) +{ + BOOL bRetVal = FALSE; + UINT uu; + BYTE byActPhyId, byOrgPhyId; + BYTE byOrgMIIADR; + BYTE byOrgMIICR; + + /* keep original MIICR value */ + VNSvInPortB(dwIoBase + MAC_REG_MIIADR, &byOrgMIIADR); + VNSvInPortB(dwIoBase + MAC_REG_MIICR, &byOrgMIICR); + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + GMACvDisableMiiAutoPoll(dwIoBase); + + byOrgPhyId = GMACbyGetPhyId(dwIoBase); + + for (uu = 0; uu < uTotalPhyNum; uu++) { + GMACvSetPhyId(dwIoBase, byRevId, pbyPhyId[uu]); + + if (GMIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMSR, BMSR_LNK)) { + + byActPhyId = pbyPhyId[uu]; + + /* iso all PHY */ + for (uu = 0; uu < uTotalPhyNum; uu++) { + GMACvSetPhyId(dwIoBase, byRevId, pbyPhyId[uu]); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_ISO); + } + + /* finally, set correct PHY id */ + GMACvSetPhyId(dwIoBase, byRevId, byActPhyId); + /* active this PHY */ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_ISO); + bRetVal = TRUE; + break; + } + } + + if (!bRetVal) + /* if no link, set original PHY id */ + GMACvSetPhyId(dwIoBase, byRevId, byOrgPhyId); + + /* restore MIICR */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIADR, byOrgMIIADR); + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, byOrgMIICR); + return bRetVal; +} + +VOID GMIIvInitialize(DWORD dwIoBase, BYTE byRevId, DWORD dwPhyCmrId) +{ + WORD wOrgData; + + /* PHY company/module, don't care revision id */ + dwPhyCmrId &= CID_REV_ID_MASK_OFF; + + switch (dwPhyCmrId) { + case CID_CICADA_CIS8201: + /* NOTICE!! For CICADA CS8201 PHY */ + /* Turn on AUX_MODE (bit 2) in MII AUX register (offset 1Ch) */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_AUXCSR, AUXCSR_MDPPS); + + /* Turn on bit 2 in offset 0x1B, this patch code only adopt to CIS8201, + not for integrated PHY in VT3216 */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_LED, LED_LALBE); + + break; + + case CID_CICADA_CIS3216I: + case CID_CICADA_CIS3216I64: + break; + + case CID_MARVELL_1000: + case CID_MARVELL_1000S: + /* Assert CRS on Transmit */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_PSCR, PSCR_ACRSTX); + break; + + default: + break; + } + + /* if ISO is on, turn it off */ + GMIIbReadEmbeded(dwIoBase, byRevId, MII_REG_BMCR, &wOrgData); + if (BITbIsBitOn(wOrgData, BMCR_ISO)) { + wOrgData &= ~BMCR_ISO; + GMIIbWriteEmbeded(dwIoBase, byRevId, MII_REG_BMCR, wOrgData); + } +} diff --git a/cpu/arm920t/wmt/gpio.h b/cpu/arm920t/wmt/gpio.h new file mode 100755 index 0000000..47ee1ae --- /dev/null +++ b/cpu/arm920t/wmt/gpio.h @@ -0,0 +1,317 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef _GPIO_H_ +#define _GPIO_H_ + +typedef struct _GPIO_REG_ { + volatile unsigned long CTRL_UR_LPC_SF; /* [Rx00] GPIO Enable Control Register for UARTS,LPC,SF */ + volatile unsigned long CTRL_SD_IIC_SPI_MS; /* [Rx04] GPIO Enable Control Register for SD,IIC,SPI,MS */ + volatile unsigned long CTRL_CF; /* [Rx08] GPIO Enable Control Register for CF */ + volatile unsigned long CTRL_NF; /* [Rx0C] GPIO Enable Control Register for NF */ + volatile unsigned long CTRL_PCIAD; /* [Rx10] GPIO Enable Control for PCI AD BUS */ + volatile unsigned long CTRL_PCI; /* [Rx14] GPIO Eanble Control for Non PCI AD BUS */ + volatile unsigned long CTRL_IDE; /* [Rx18] GPIO Enable Control for IDE */ + volatile unsigned long RESV_1C; /* [Rx1C] */ + + volatile unsigned long OC_UR_LPC_SF; /* [Rx20] GPIO Output Control Register for UARTS,LPC,SF */ + volatile unsigned long OC_SD_IIC_SPI_MS; /* [Rx24] GPIO Output Control Register for SD,IIC,SPI,MS */ + volatile unsigned long OC_CF; /* [Rx28] GPIO Output Control Register for CF */ + volatile unsigned long OC_NF; /* [Rx2C] GPIO Output Control Register for NF */ + volatile unsigned long OC_PCIAD; /* [Rx30] GPIO Output Control Register for PCI AD BUS */ + volatile unsigned long OC_PCI; /* [Rx34] GPIO Output Control Register for Non PCI AD BUS */ + volatile unsigned long OC_IDE; /* [Rx38] GPIO Output Control Register for IDE */ + volatile unsigned long OC_GPIO; /* [Rx3C] GPIO Output Control Register for GPIO */ + volatile unsigned long OD_UR_LPC_SF; /* [Rx40] GPIO Output Data Register for UARTS,LPC,SF */ + + volatile unsigned long OD_SD_IIC_SPI_MS; /* [Rx44] GPIO Output Data Register for SD,IIC,SPI,MS */ + volatile unsigned long OD_CF; /* [Rx48] GPIO Output Data Register for CF */ + volatile unsigned long OD_NF; /* [Rx4C] GPIO Output Data Register for NF */ + volatile unsigned long OD_PCIAD; /* [Rx50] GPIO Output Data Register for PCIAD */ + volatile unsigned long OD_PCI; /* [Rx54] GPIO Output Data Register for Non PCI AD BUS */ + volatile unsigned long OD_IDE; /* [Rx58] GPIO Output Data Register for IDE */ + volatile unsigned long OD_GPIO; /* [Rx5C] GPIO Output Data Register for GPIO */ + + volatile unsigned long ID_UR_LPC_SF; /* [Rx60] GPIO Input Data Register for UARTS,LPC,SF */ + volatile unsigned long ID_SD_IIC_SPI_MS; /* [Rx64] GPIO Input Data Register for SD,IIC,SPI,MS */ + volatile unsigned long ID_CF; /* [Rx68] GPIO Input Data Register for CF */ + volatile unsigned long ID_NF; /* [Rx6C] GPIO Input Data Register for NF */ + volatile unsigned long ID_PCIAD; /* [Rx70] GPIO Input Data Register for PCIAD */ + volatile unsigned long ID_PCI; /* [Rx74] GPIO Input Data Register for Non PCI AD BUS */ + volatile unsigned long ID_IDE; /* [Rx78] GPIO Input Data Register for IDE */ + volatile unsigned long ID_GPIO; /* [Rx7C] GPIO Input Data Register for GPIO */ + + volatile unsigned long RESV_80[0x20]; /* [Rx80-RxFF] */ + + volatile unsigned long STRAP_STS; /* [Rx100] Strapping Option Status Register */ + volatile unsigned long RESV_104; /* [Rx104] */ + volatile unsigned long AHB_CTRL; /* [Rx108] AHB Control Register */ + volatile unsigned long RESV_10C[0x3D]; /* [Rx10C-Rx1FF] */ + + volatile unsigned long SEL_CF_NF; /* [Rx200] CF/NF Selection Register */ + volatile unsigned long RESV_204[0x3F]; /* [Rx204-Rx2FF] */ + + volatile unsigned long INT_REQ_TYPE; /* [Rx300] GPIO Interrupt Request Type Register */ + volatile unsigned long INT_REQ_STS; /* [Rx304] GPIO Interrupt Request Status Register */ + volatile unsigned long RESV_308[0x3E]; /* [Rx308-Rx3FF] */ + + volatile unsigned long IDE_IO_DRV; /* [Rx400] IDE I/O Drive Strength Register */ + volatile unsigned long MS_IO_DRV; /* [Rx404] MS I/O Drive Strength and Slew Rate Register */ + volatile unsigned long PCI_IO_DRV; /* [Rx408] PCI Bus I/O Drive Strength and Slew */ + /* Rate Register */ + volatile unsigned long SD_IO_DRV; /* [Rx40C] SD I/O Drive Strength and Slwe Rate Register */ + volatile unsigned long SF_IO_DRV; /* [Rx410] Serial Flash Clock I/O Drive Strength */ + /* and Slew Rate Register */ + volatile unsigned long SPI_IO_DRV; /* [Rx414] SPI I/O Drive Strength and Slew Rate Register */ +} GPIO_REG, *PGPIO_REG; + +/* + * volatile unsigned long CTRL_UR_LPC_SF; //[Rx00] GPIO Enable Control Register for UARTS,LPC,SF + */ +#define GPIO_UR0_CTS 0x1 /* UART0 CTS signal GPIO Enable */ +#define GPIO_UR0_RTS 0x2 /* UART0 RTS signal GPIO Enable */ +#define GPIO_UR0_RXD 0x4 +#define GPIO_UR0_TXD 0x8 +#define GPIO_UR0_ALL 0xF + +#define GPIO_UR1_CTS 0x100 /* UART1 CTS signal GPIO Enable */ +#define GPIO_UR1_RTS 0x200 /* UART1 RTS signal GPIO Enable */ +#define GPIO_UR1_RXD 0x400 +#define GPIO_UR1_TXD 0x800 +#define GPIO_UR1_ALL 0xF00 + +#define GPIO_LPC_AD4 0xF0000 +#define GPIO_LPC_CLK 0x100000 +#define GPIO_LPC_DRQ 0x200000 +#define GPIO_LPC_FRAME 0x400000 +#define GPIO_LPC_RESET 0x800000 +#define GPIO_LPC_SERIRQ 0x1000000 + +#define GPIO_SF_CS2 0x6000000 +#define GPIO_SF_CLK 0x8000000 +#define GPIO_SF_DI 0x10000000 +#define GPIO_SF_DO 0x20000000 + +/* + * volatile unsigned long CTRL_SD_IIC_SPI_MS; //[Rx04] GPIO Enable Control Register for SD,IIC,SPI,MS + */ +#define GPIO_SD_DATA4 0xF + +#define GPIO_MMC_DATA4 0xF0 + +#define GPIO_SD_CLK 0x100 +#define GPIO_SD_CMD 0x200 + +#define GPIO_IIC_SCL 0x400 +#define GPIO_IIC_SDA 0x800 + +#define GPIO_SPI_CLK 0x1000 +#define GPIO_SPI_MISO 0x2000 +#define GPIO_SPI_MOSI 0x4000 +#define GPIO_SPI_SS 0x8000 + +#define GPIO_MS_ALL 0x7F0000 +#define GPIO_MS_DATA4 0xF0000 +#define GPIO_MS_BS 0x100000 +#define GPIO_MS_CLK 0x200000 +#define GPIO_MS_INS 0x400000 + +/* + * volatile unsigned long CTRL_CF; //[Rx08] GPIO Enable Control Register for CF + */ +#define GPIO_CF_DATA16 0xFFFF +#define GPIO_CF_AD3 0x70000 +#define GPIO_CF_CD2 0x180000 +#define GPIO_CF_CE2 0x600000 +#define GPIO_CF_IOR 0x800000 +#define GPIO_CF_IOW 0x1000000 +#define GPIO_CF_WAIT 0x2000000 +#define GPIO_CF_INTRQ 0x4000000 + +/* + * volatile unsigned long CTRL_NF; //[Rx0C] GPIO Enable Control Register for NF + */ +#define GPIO_NF_CE8 0xFF +#define GPIO_NF_ALE 0x100 +#define GPIO_NF_CLE 0x200 +#define GPIO_NF_RD 0x400 +#define GPIO_NF_RE 0x800 +#define GPIO_NF_WE 0x1000 +#define GPIO_NF_WP 0x2000 +#define GPIO_NF_WPD 0x4000 + +/* + * volatile unsigned long CTRL_PCIAD; //[Rx10] GPIO Enable Control for PCI AD BUS + */ +#define GPIO_PCI_ADALL 0xFFFFFFFF +#define GPIO_PCI_AD32 0xFFFFFFFF + +/* + * volatile unsigned long CTRL_PCI; //[Rx14] GPIO Eanble Control for Non PCI AD BUS + */ +#define GPIO_PCI_NOADALL 0x1FFFFFFF +#define GPIO_PCI_GNT4 0xF +#define GPIO_PCI_REQ4 0xF0 +#define GPIO_PCI_BE4 0xF00 +#define GPIO_PCI_INTA 0x1000 +#define GPIO_PCI_INTB 0x2000 +#define GPIO_PCI_INTC 0x4000 +#define GPIO_PCI_INTD 0x8000 +#define GPIO_PCI_DEVSEL 0x10000 +#define GPIO_PCI_FRAME 0x20000 +#define GPIO_PCI_IRDY 0x40000 +#define GPIO_PCI_M66EN 0x80000 +#define GPIO_PCI_PAR 0x100000 +#define GPIO_PCI_PERR 0x200000 +#define GPIO_PCI_SERR 0x400000 +#define GPIO_PCI_STOP 0x800000 +#define GPIO_PCI_TRDY 0x1000000 + +/* + * volatile unsigned long CTRL_IDE; //[Rx18] GPIO Enable Control for IDE + */ +#define GPIO_IDE_DD16 0xFFFF +#define GPIO_IDE_DA3 0x70000 +#define GPIO_IDE_CS1 0x80000 +#define GPIO_IDE_CS3 0x100000 +#define GPIO_IDE_DACK 0x200000 +#define GPIO_IDE_DREQ 0x400000 +#define GPIO_IDE_INTRQ 0x800000 +#define GPIO_IDE_IOR 0x1000000 +#define GPIO_IDE_IORDY 0x2000000 +#define GPIO_IDE_IOW 0x4000000 + +/* + * volatile unsigned long OC_UR_LPC_SF; //[Rx20] GPIO Output Control Register for UARTS,LPC,SF + */ +#define GPIO_OE_UR0_CTS 0x1 +#define GPIO_OE_UR0_RTS 0x2 +#define GPIO_OE_UR0_RXD 0x4 +#define GPIO_OE_UR0_TXD 0x8 +#define GPIO_OE_UR1_CTS 0x100 +#define GPIO_OE_UR1_RTS 0x200 +#define GPIO_OE_UR1_RXD 0x400 +#define GPIO_OE_UR1_TXD 0x800 +#define GPIO_OE_LPC_AD4 0xF0000 +#define GPIO_OE_LPC_CLK 0x100000 +#define GPIO_OE_LPC_DRQ 0x200000 +#define GPIO_OE_LPC_FRAME 0x400000 +#define GPIO_OE_LPC_RESET 0x800000 +#define GPIO_OE_LPC_SERIRQ 0x1000000 +#define GPIO_OE_SF_CS2 0x6000000 +#define GPIO_OE_SF_CLK 0x8000000 +#define GPIO_OE_SF_DI 0x10000000 +#define GPIO_OE_SF_DO 0x20000000 + +/* + * volatile unsigned long OC_SD_IIC_SPI_MS; //[Rx24] GPIO Output Control Register for SD,IIC,SPI,MS + */ +#define GPIO_OE_SD_DATA4 0xF +#define GPIO_OE_MMC_DATA4 0xF0 +#define GPIO_OE_SD_CLK 0x100 +#define GPIO_OE_SD_CMD 0x200 +#define GPIO_OE_IIC_SDA 0x400 +#define GPIO_OE_IIC_SCL 0x800 +#define GPIO_OE_SPI_CLK 0x1000 +#define GPIO_OE_SPI_MISO 0x2000 +#define GPIO_OE_SPI_MOSI 0x4000 +#define GPIO_OE_SPI_SS 0x8000 +#define GPIO_OE_MS_DATA0 0x10000 +#define GPIO_OE_MS_DATA1 0x20000 +#define GPIO_OE_MS_DATA2 0x40000 +#define GPIO_OE_MS_DATA3 0x80000 +#define GPIO_OE_MS_BS 0x100000 +#define GPIO_OE_MS_CLK 0x200000 +#define GPIO_OE_MS_INS 0x400000 + +/* + * volatile unsigned long OC_CF; //[Rx28] GPIO Output Control Register for CF + */ +#define GPIO_OE_CF_DATA16 0xFFFF +#define GPIO_OE_CF_ADDR3 0x70000 +#define GPIO_OE_CF_CD2 0x180000 +#define GPIO_OE_CF_CE2 0x600000 +#define GPIO_OE_CF_IORD 0x800000 +#define GPIO_OE_CF_IOW 0x1000000 +#define GPIO_OE_CF_WAIT 0x2000000 +#define GPIO_OE_CF_INTRQ 0x4000000 + +/* + * volatile unsigned long OC_NF; //[Rx2C] GPIO Output Control Register for NF + */ +#define GPIO_OE_NF_CE8 0xFF +#define GPIO_OE_NF_ALE 0x100 +#define GPIO_OE_NF_CLE 0x200 +#define GPIO_OE_NF_RD 0x400 +#define GPIO_OE_NF_RE 0x800 +#define GPIO_OE_NF_WE 0x1000 +#define GPIO_OE_NF_WP 0x2000 +#define GPIO_OE_NF_WPD 0x4000 + +/* + * volatile unsigned long OC_PCIAD; //[Rx30] GPIO Output Control Register for PCI AD BUS + */ +#define GPIO_OE_PCI_AD32 0xFFFFFFFF + +/* + * volatile unsigned long OC_PCI; //[Rx34] GPIO Output Control Register for Non PCI AD BUS + */ +#define GPIO_OE_PCI_GNT4 0xF +#define GPIO_OE_PCI_REQ4 0xF0 +#define GPIO_OE_PCI_BE4 0xF00 +#define GPIO_OE_PCI_INTA 0x1000 +#define GPIO_OE_PCI_INTB 0x2000 +#define GPIO_OE_PCI_INTC 0x4000 +#define GPIO_OE_PCI_INTD 0x8000 +#define GPIO_OE_PCI_DEVSEL 0x10000 +#define GPIO_OE_PCI_FRAME 0x20000 +#define GPIO_OE_PCI_IRDY 0x40000 +#define GPIO_OE_PCI_M66EN 0x80000 +#define GPIO_OE_PCI_PAR 0x100000 +#define GPIO_OE_PCI_PERR 0x200000 +#define GPIO_OE_PCI_SERR 0x400000 +#define GPIO_OE_PCI_STOP 0x800000 +#define GPIO_OE_PCI_TRDY 0x1000000 + +/* + * volatile unsigned long OC_IDE; //[Rx38] GPIO Output Control Register for IDE + */ +#define GPIO_OE_IDE_DATA16 0xFFFF +#define GPIO_OE_IDE_ADDR3 0x70000 +#define GPIO_OE_IDE_CS1 0x80000 +#define GPIO_OE_IDE_CS3 0x100000 +#define GPIO_OE_IDE_DACK 0x200000 +#define GPIO_OE_IDE_DREQ 0x400000 +#define GPIO_OE_IDE_INTRQ 0x800000 +#define GPIO_OE_IDE_IOR 0x1000000 +#define GPIO_OE_IDE_IORDY 0x2000000 +#define GPIO_OE_IDE_IOW 0x4000000 + +/* + * volatile unsigned long OC_GPIO; //[Rx3C] GPIO Output Control Register for GPIO + */ +#define GPIO_OE_GPIO_ALL 0xFF +#define GPIO_OE_GPIO_0 0x1 +#define GPIO_OE_GPIO_1 0x2 +#define GPIO_OE_GPIO_2 0x4 +#define GPIO_OE_GPIO_3 0x8 +#define GPIO_OE_GPIO_4 0x10 +#define GPIO_OE_GPIO_5 0x20 +#define GPIO_OE_GPIO_6 0x40 +#define GPIO_OE_GPIO_7 0x80 + +#endif /*_GPIO_H_ */ diff --git a/cpu/arm920t/wmt/interrupts.c b/cpu/arm920t/wmt/interrupts.c new file mode 100755 index 0000000..8663208 --- /dev/null +++ b/cpu/arm920t/wmt/interrupts.c @@ -0,0 +1,231 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +#include <common.h> + +#if defined(CONFIG_WMT) + +#include <asm/arch/common_def.h> +#include <asm/arch/hardware.h> + +#include "pmc.h" + +#define TIMER_LOAD_VAL 0xffffffff + +static PMC_REG *pmc_regs = (PMC_REG *) BA_PMC; + +/* macro to read the 32 bit timer */ +static inline ulong READ_TIMER(void) +{ + if ((pmc_regs->OS_Timer_Ctrl & OSTC_RDREQ) == 0) + pmc_regs->OS_Timer_Ctrl |= OSTC_RDREQ; + + while (pmc_regs->OS_Timer_Access_Sts & OSTA_RCA) + ; + + return pmc_regs->OS_Timer_Count; +} + +static ulong timestamp; +static ulong lastdec; + +/* nothing really to do with interrupts, just starts up a counter. */ +int interrupt_init(void) +{ + /* + * Disable all OS Timer Control functions. + */ + pmc_regs->OS_Timer_Ctrl = 0; + + /* + * Disable OS Timer Watchdog. + */ + pmc_regs->OS_Timer_WatchDog_Enable = 0; + + /* + * Disable all OS Timer Interrupts. + */ + pmc_regs->OS_Timer_Int_Enable = 0; + + + /* + * Clean all active OS Timer Match Status. + */ + pmc_regs->OS_Timer_Sts = (OSTS_M0 | OSTS_M1 | OSTS_M2 | OSTS_M3); + + /* + * Enable OS Timer update. + */ + if ((pmc_regs->OS_Timer_Ctrl & OSTC_ENABLE) == 0) + pmc_regs->OS_Timer_Ctrl |= OSTC_ENABLE; + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + tmp = get_timer(0); /* get current timestamp */ + if ((tmo + tmp + 1) < tmp) /* if setting this fordward will roll time stamp */ + reset_timer_masked(); /* reset "advancing" timestamp to 0, set lastdec value */ + else + tmo += tmp; /* else, set advancing stamp wake up time */ + + while (get_timer_masked() < tmo) /* loop till event */ + /* NOP */; +} + +void reset_timer_masked(void) +{ + /* reset time */ + lastdec = READ_TIMER(); /* capure current incrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER(); /* current tick value */ + + if (lastdec <= now) { /* normal mode (non roll) */ + /* normal mode */ + timestamp += now - lastdec; /* move stamp fordward with absoulte diff ticks */ + } else { + /* we have an overflow ... */ + timestamp += now + TIMER_LOAD_VAL - lastdec; + } + lastdec = now; + + return timestamp; +} + +void udelay_masked(unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked() + tmo; + + do { + ulong now = get_timer_masked(); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + + return tbclk; +} + +/* + * reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu(ulong ignored) +{ + /* Clean prevoius reset status */ + pmc_regs->Reset_Sts = (PMRS_PGR | PMRS_SHR | PMRS_SWR | PMRS_WDR | PMRS_HBR | PMRS_IOR | PMRS_PMR); + + /* set PLLC to default value */ + while (pmc_regs->PM_Sts2&0x3F0038) + ; + pmc_regs->PLLC = 0x02270001; + while (pmc_regs->PM_Sts2&0x3F0038) + ; + + /* Request software reset */ + pmc_regs->SW_Reset_Req = PMSR_SWR; + + while (1) /* loop forever and wait for reset to happen */ + ; + + /*NOTREACHED*/ +} + +#endif /* defined(CONFIG_WMT) */ diff --git a/cpu/arm920t/wmt/mac.c b/cpu/arm920t/wmt/mac.c new file mode 100755 index 0000000..2e80ec6 --- /dev/null +++ b/cpu/arm920t/wmt/mac.c @@ -0,0 +1,737 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MII_H__) +#include "mii.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ +#define CB_DELAY_NM9346 (10) /* 10ms */ +#define CB_DELAY_SOFT_RESET (50) /* 50ms */ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +BOOL +MACbIsCableLinkOk( + DWORD dwIoBase + ) +{ + return MACbIsRegBitsOff(dwIoBase, MAC_REG_MIISR, MIISR_LNKFL); +} + +BOOL +MACbIsIn100MMode( + DWORD dwIoBase, + BYTE byRevId + ) +{ + UINT ii; + + for (ii = 0; ii < 30; ii++) + PCAvDelayByIO(CB_DELAY_LOOP_WAIT); + + /* NOTE.... */ + /* when link fail, MAC will report in 100M mode, */ + /* but NS DP83840A will report in 10M mode, DAVICOM DM9101 depends */ + return MIIbIsIn100MMode(dwIoBase, byRevId); +} + +VOID +MACvIsInFullDuplexMode( + PBOOL pbFullDup, + DWORD dwIoBase + ) +{ + *pbFullDup = MACbIsRegBitsOn(dwIoBase, MAC_REG_CR1, CR1_FDX); +} + +BOOL +MACbIsRegBitsOff( + DWORD dwIoBase, + BYTE byRegOfs, + BYTE byTestBits + ) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOff(byData, byTestBits); +} + +BOOL +MACbIsRegBitsOn( + DWORD dwIoBase, + BYTE byRegOfs, + BYTE byTestBits + ) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOn(byData, byTestBits); +} + +BOOL +MACbSafeSoftwareReset( + DWORD dwIoBase, + BYTE byRevId + ) +{ + BYTE abyTmpRegData[0x100]; + BOOL bRetVal; + + /* PATCH.... */ + /* save some important register's value, then do */ + /* reset, then restore register's value */ + + /* save MAC context */ + MACvSaveContext(dwIoBase, byRevId, abyTmpRegData); + /* do reset */ + bRetVal = MACbSoftwareReset(dwIoBase, byRevId); + /* restore MAC context, except CR0 */ + MACvRestoreContext(dwIoBase, byRevId, abyTmpRegData); + + return bRetVal; +} + +BOOL +MACbStop( + DWORD dwIoBase + ) +{ + WORD ww; + BYTE byData; + + VNSvOutPortB(dwIoBase + MAC_REG_CR0, CR0_STOP); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_CR0, &byData); + if (BITbIsAllBitsOff(byData, CR0_TXON | CR0_RXON)) + break; + } + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL +MACbSafeStop( + DWORD dwIoBase, + BYTE byRevId + ) +{ + if (!MACbSafeTxOff(dwIoBase, byRevId)) + return FALSE; + if (!MACbSafeRxOff(dwIoBase, byRevId)) + return FALSE; + if (!MACbStop(dwIoBase)) + MACbSafeSoftwareReset(dwIoBase, byRevId); + + return TRUE; +} + +BOOL +MACbSafeRxOff( + DWORD dwIoBase, + BYTE byRevId + ) +{ + WORD ww; + BYTE byData; + + /* try to safe shutdown RX */ + MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL); + MACvRegBitsOff(dwIoBase, MAC_REG_CR0, CR0_RXON); + /* safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_CR0, &byData); + if (BITbIsBitOff(byData, CR0_RXON)) + break; + } + if (ww == W_MAX_TIMEOUT) { + /* enter FIFO test mode to issue RX reject */ + VNSvOutPortB(dwIoBase + MAC_REG_GFTEST, 0x01); + VNSvOutPortB(dwIoBase + MAC_REG_RFTCMD, 0x08); + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + VNSvOutPortB(dwIoBase + MAC_REG_GFTEST, 0x00); + } + + MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + return TRUE; +} + +BOOL +MACbSafeTxOff( + DWORD dwIoBase, + BYTE byRevId + ) +{ + WORD ww; + BYTE byData; + + /* try to safe shutdown TX */ + MACvRegBitsOff(dwIoBase, MAC_REG_CR0, CR0_TXON); + /* safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_CR0, &byData); + if (BITbIsBitOff(byData, CR0_TXON)) + break; + } + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL +MACbSoftwareReset( + DWORD dwIoBase, + BYTE byRevId + ) +{ + WORD ww; + BYTE byData; + + /* turn on CR1_SFRST */ + MACvRegBitsOn(dwIoBase, MAC_REG_CR1, CR1_SFRST); + + /* polling till software reset complete */ + /* W_MAX_TIMEOUT is the timeout period */ + printf("\n"); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_CR1, &byData); + if (BITbIsBitOff(byData, CR1_SFRST)) + break; + } + if (ww == W_MAX_TIMEOUT) { + /* turn on force reset */ + MACvRegBitsOn(dwIoBase, MAC_REG_MISC_CR1, MISC_CR1_FORSRST); + /* delay 2ms */ + MACvTimer0MiniSDelay(dwIoBase, byRevId, 2); + } + + return TRUE; +} + +BYTE +MACbyReadEECSR( + DWORD dwIoBase + ) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_EECSR, &byData); + return byData; +} + +BYTE +MACbyReadMIICR( + DWORD dwIoBase + ) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_MIICR, &byData); + return byData; +} + +BYTE +MACbyReadMultiAddr( + DWORD dwIoBase, + UINT uByteIdx + ) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_MAR + uByteIdx, &byData); + return byData; +} + +VOID +MACvWriteMultiAddr( + DWORD dwIoBase, + UINT uByteIdx, + BYTE byData + ) +{ + VNSvOutPortB(dwIoBase + MAC_REG_MAR + uByteIdx, byData); +} + +VOID +MACvInitialize( + DWORD dwIoBase, + BYTE byRevId + ) +{ + /* Clear sticky bits */ + MACvClearStckDS(dwIoBase); + /* Disable force PME-enable */ + VNSvOutPortB(dwIoBase + MAC_REG_WOLCG_CLR, WOLCFG_PME_OVR); + /* Disable power-event config bit */ + MACvPwrEvntDisable(dwIoBase); + /* Clear power status */ + VNSvOutPortB(dwIoBase + MAC_REG_PWRCSR_CLR, 0xFF); + VNSvOutPortB(dwIoBase + MAC_REG_PWRCSR1_CLR, 0x03); + + /* Do reset */ + MACbSoftwareReset(dwIoBase, byRevId); + /* For AUTOLD be effect in VT3043, safe delay time */ + PCAvDelayByIO(CB_DELAY_SOFT_RESET); + + /* + // Issue AUTOLD in EECSR to reload eeprom + MACvRegBitsOn(dwIoBase, MAC_REG_EECSR, EECSR_AUTOLD); + + // Wait until EEPROM loading complete + while (TRUE) { + BYTE byData; + + VNSvInPortB(dwIoBase + MAC_REG_EECSR, &byData); + if (BITbIsBitOff(byData, EECSR_AUTOLD)) + break; + } + */ + + /* For 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA turned on. */ + /* It makes MAC receive magic packet automatically. So, driver turn it off. */ + MACvRegBitsOff(dwIoBase, MAC_REG_CFGA, CFGA_LED0S0); + + /* Set rx-FIFO/tx-FIFO/DMA threshold */ + /* Set rx threshold, 64 bytes */ + MACvSetRxThreshold(dwIoBase, 0); + /* Set tx threshold, 128 bytes */ + MACvSetTxThreshold(dwIoBase, 0); + /* Set DMA length, 16 DWORDs = 64 bytes */ + MACvSetDmaLength(dwIoBase, 0); + + /* kevin wonder:Enable queue packet? or disable? */ + MACvRegBitsOff(dwIoBase, MAC_REG_CFGB, CFGB_QPKTDIS); + /* kevin wonder:Suspend-well accept broadcast, multicast */ + VNSvOutPortB(dwIoBase + MAC_REG_WOLCG_SET, WOLCFG_SAM | WOLCFG_SAB); + + /* kevin wonder :Back off algorithm use original IEEE standard */ + MACvRegBitsOff(dwIoBase, MAC_REG_CFGD, CFGD_CRADOM | CFGD_CAP | CFGD_MBA | CFGD_BAKOPT); + + /* Set packet filter */ + /* Receive directed and broadcast address */ + MACvSetPacketFilter(dwIoBase, PKT_TYPE_DIRECTED | PKT_TYPE_BROADCAST); + + /* enable MIICR_MAUTO */ + MACvEnableMiiAutoPoll(dwIoBase); + /* macinit */ + + /* printf("mac init ok!\n"); */ +} + +VOID +MACvIntDisable( + DWORD dwIoBase, + BYTE byRevId + ) +{ + VNSvOutPortW(dwIoBase + MAC_REG_IMR, 0x0000); + VNSvOutPortB(dwIoBase + MAC_REG_MIMR, 0x00); +} + +VOID +MACvIntEnable( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwMask + ) +{ + VNSvOutPortW(dwIoBase + MAC_REG_IMR, LOWORD(dwMask)); + VNSvOutPortB(dwIoBase + MAC_REG_MIMR, (BYTE)(HIWORD(dwMask))); +} + +VOID +MACvEnableMiiAutoPoll( + DWORD dwIoBase + ) +{ + WORD ww; + BYTE byData; + + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, 0); + VNSvOutPortB(dwIoBase + MAC_REG_MIIAD, 0x01); + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, MIICR_MAUTO); + + /* as soon as MDONE is on, MAUTO is really started */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_MIIAD, &byData); + if (BITbIsBitOn(byData, MIIAD_MDONE)) + break; + } + + MACvRegBitsOn(dwIoBase, MAC_REG_MIIAD, MIIAD_MSRCEN); +} + +VOID +MACvSafeDisableMiiAutoPoll( + DWORD dwIoBase, + BYTE byRevId + ) +{ + WORD ww; + BYTE byData; + + /* turn off MAUTO */ + VNSvOutPortB(dwIoBase + MAC_REG_MIICR, 0); + + /* as soon as MIDLE is on, MAUTO is really stoped */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_MIIAD, &byData); + if (BITbIsBitOn(byData, MIIAD_MIDLE)) + break; + } +} + +VOID +MACvReadISR( + DWORD dwIoBase, + BYTE byRevId, + PDWORD pdwValue + ) +{ + WORD wData; + BYTE byData; + + VNSvInPortW(dwIoBase + MAC_REG_ISR, &wData); + VNSvInPortB(dwIoBase + MAC_REG_MISR, &byData); + *pdwValue = MAKEDWORD(wData, MAKEWORD(byData, 0x00)); +} + +VOID +MACvWriteISR( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwValue + ) +{ + /* NOTE.... must write MISR before ISR, otherwise GENI will not */ + /* be cleared */ + VNSvOutPortB(dwIoBase + MAC_REG_MISR, (BYTE)(HIWORD(dwValue))); + VNSvOutPortW(dwIoBase + MAC_REG_ISR, LOWORD(dwValue)); +} + +VOID +MACvRestoreContext( + DWORD dwIoBase, + BYTE byRevId, + PBYTE pbyCxtBuf + ) +{ + int ii; + + /* restore RCR,TCR,CR,ISR,IMR... */ + for (ii = MAC_REG_PAR; ii < MAC_REG_CUR_RD_ADDR; ii++) { + /* except CR0, because we don't want to start chip now */ + if (ii != MAC_REG_CR0) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + } + + /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */ + for (ii = MAC_REG_CUR_RD_ADDR; ii < MAC_REG_CUR_TD_ADDR + 4; ii += 4) + VNSvOutPortD(dwIoBase + ii, *(PDWORD)(pbyCxtBuf + ii)); + + /* restore MIIAD... */ + for (ii = MAC_REG_MPHY; ii < MAC_REG_CNTR_MPA; ii++) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + + /* restore WOLCR, PWCFG, TestReg, WOLCG */ + for (ii = MAC_REG_WOLCR_SET; ii < MAC_REG_WOLCR_CLR; ii++) + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + /* restore pattern, mask */ + for (ii = MAC_REG_PATRN_CRC0; ii < MAC_REG_BYTEMSK3_3 + 4; ii += 4) + VNSvOutPortD(dwIoBase + ii, *((PDWORD)(pbyCxtBuf + ii))); +} + +VOID +MACvSaveContext( + DWORD dwIoBase, + BYTE byRevId, + PBYTE pbyCxtBuf + ) +{ + int ii; + + /* save RCR,TCR,CR,ISR,IMR... */ + for (ii = MAC_REG_PAR; ii < MAC_REG_CUR_RD_ADDR; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + + /* save CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */ + for (ii = MAC_REG_CUR_RD_ADDR; ii < MAC_REG_CUR_TD_ADDR + 4; ii += 4) + VNSvInPortD(dwIoBase + ii, (PDWORD)(pbyCxtBuf + ii)); + + /* save MIIAD... */ + for (ii = MAC_REG_MPHY; ii < MAC_REG_CNTR_MPA; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + + /* save WOLCR, PWCFG, TestReg, WOLCG */ + for (ii = MAC_REG_WOLCR_SET; ii < MAC_REG_WOLCR_CLR; ii++) + VNSvInPortB(dwIoBase + ii, (PBYTE)(pbyCxtBuf + ii)); + /* save pattern, mask */ + for (ii = MAC_REG_PATRN_CRC0; ii < MAC_REG_BYTEMSK3_3 + 4; ii += 4) + VNSvInPortD(dwIoBase + ii, (PDWORD)(pbyCxtBuf + ii)); +} + +VOID +MACvSetDmaLength( + DWORD dwIoBase, + BYTE byDmaLength + ) +{ + BYTE byOrgValue; + + /* set BCR0 */ + VNSvInPortB(dwIoBase + MAC_REG_BCR0, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xF8) | byDmaLength); + VNSvOutPortB(dwIoBase + MAC_REG_BCR0, byOrgValue); +} + +VOID +MACvSetDuplexMode( + DWORD dwIoBase, + BYTE byRevId, + BOOL bFullDuplexOn + ) +{ + if (bFullDuplexOn) { + MACvRegBitsOn(dwIoBase, MAC_REG_CR1, CR1_FDX); + } + else { + MACvRegBitsOff(dwIoBase, MAC_REG_CR1, CR1_FDX); + } + + if (bFullDuplexOn) { + VNSvOutPortB(dwIoBase + MAC_REG_WOLCG_SET, WOLCFG_SFDX); + } + else { + VNSvOutPortB(dwIoBase + MAC_REG_WOLCG_CLR, WOLCFG_SFDX); + } +} + + +VOID +MACvSetLoopbackMode( + DWORD dwIoBase, + BYTE byLoopbackMode + ) +{ + BYTE byOrgValue; + + /* set TCR */ + VNSvInPortB(dwIoBase + MAC_REG_TCR, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xF9) | (byLoopbackMode << 1)); + VNSvOutPortB(dwIoBase + MAC_REG_TCR, byOrgValue); +} + +VOID +MACvSetPacketFilter( + DWORD dwIoBase, + WORD wFilterType + ) +{ + BYTE byOldRCR; + BYTE byNewRCR = 0; + + /* if only in DIRECTED mode, multicast-address will set to zero, */ + /* but if other mode exist (e.g. PROMISCUOUS), multicast-address */ + /* will be open */ + if (BITbIsBitOn(wFilterType, PKT_TYPE_DIRECTED)) { + /* set multicast address to accept none */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR, 0L); + VNSvOutPortD(dwIoBase + MAC_REG_MAR + sizeof(DWORD), 0L); + } + + if (BITbIsAnyBitsOn(wFilterType, PKT_TYPE_PROMISCUOUS | PKT_TYPE_ALL_MULTICAST)) { + /* set multicast address to accept all */ + VNSvOutPortD(dwIoBase + MAC_REG_MAR, 0xFFFFFFFFL); + VNSvOutPortD(dwIoBase + MAC_REG_MAR + sizeof(DWORD), 0xFFFFFFFFL); + } + + if (BITbIsBitOn(wFilterType, PKT_TYPE_PROMISCUOUS)) + byNewRCR |= (RCR_PROM | RCR_AM | RCR_AB); + + if (BITbIsAnyBitsOn(wFilterType, PKT_TYPE_MULTICAST | PKT_TYPE_ALL_MULTICAST)) + byNewRCR |= RCR_AM; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_BROADCAST)) + byNewRCR |= RCR_AB; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_RUNT)) + byNewRCR |= RCR_AR; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_ERROR)) + byNewRCR |= RCR_SEP; + + VNSvInPortB(dwIoBase + MAC_REG_RCR, &byOldRCR); + if (byNewRCR != (byOldRCR & 0x1F)) { + /* Modify the Receive Command Register */ + byNewRCR |= (BYTE)(byOldRCR & 0xE0); + VNSvOutPortB(dwIoBase + MAC_REG_RCR, byNewRCR); + } +} + +VOID +MACvSetRxThreshold( + DWORD dwIoBase, + BYTE byThreshold + ) +{ + BYTE byOrgValue; + + /* set BCR0 */ + VNSvInPortB(dwIoBase + MAC_REG_BCR0, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xC7) | (byThreshold << 3)); + VNSvOutPortB(dwIoBase + MAC_REG_BCR0, byOrgValue); + /* set RCR */ + VNSvInPortB(dwIoBase + MAC_REG_RCR, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0x1F) | (byThreshold << 5)); + VNSvOutPortB(dwIoBase + MAC_REG_RCR, byOrgValue); +} + +VOID +MACvGetTxThreshold( + DWORD dwIoBase, + PBYTE pbyThreshold + ) +{ + /* first, get BCR1 */ + VNSvInPortB(dwIoBase + MAC_REG_BCR1, pbyThreshold); + *pbyThreshold = (BYTE)((*pbyThreshold >> 3) & 0x07); + + /* second, if BCR1 is zero, we get TCR */ + if (*pbyThreshold == 0) { + VNSvInPortB(dwIoBase + MAC_REG_TCR, pbyThreshold); + *pbyThreshold >>= 5; + } +} + +VOID +MACvSetTxThreshold( + DWORD dwIoBase, + BYTE byThreshold + ) +{ + BYTE byOrgValue; + + /* set BCR1 */ + VNSvInPortB(dwIoBase + MAC_REG_BCR1, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0xC7) | (byThreshold << 3)); + VNSvOutPortB(dwIoBase + MAC_REG_BCR1, byOrgValue); + /* set TCR */ + VNSvInPortB(dwIoBase + MAC_REG_TCR, &byOrgValue); + byOrgValue = (BYTE)((byOrgValue & 0x1F) | (byThreshold << 5)); + VNSvOutPortB(dwIoBase + MAC_REG_TCR, byOrgValue); +} + +VOID +MACvTimer0MicroSDelay( + DWORD dwIoBase, + BYTE byRevId, + UINT udelay + ) +{ + BYTE byData; + + MACvRegBitsOn(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TM0US); + + /* set delay time to udelay, unit is micro-second */ + VNSvOutPortW(dwIoBase + MAC_REG_SOFT_TIMER0, (WORD)udelay); + /* delay time */ + MACvRegBitsOn(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TIMER0_EN); + MACvRegBitsOff(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TIMER0_SUSPEND); + + while (TRUE) { + VNSvInPortB(dwIoBase + MAC_REG_MISC_CR0, &byData); + if (BITbIsBitOn(byData, MISC_CR0_TIMER0_SUSPEND)) + break; + } +} + +VOID +MACvTimer0MiniSDelay( + DWORD dwIoBase, + BYTE byRevId, + UINT udelay + ) +{ + BYTE byData; + + MACvRegBitsOff(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TM0US); + + /* set delay time to udelay, unit is mini-second */ + VNSvOutPortW(dwIoBase + MAC_REG_SOFT_TIMER0, (WORD)udelay); + + /* delay time */ + MACvRegBitsOn(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TIMER0_EN); + MACvRegBitsOff(dwIoBase, MAC_REG_MISC_CR0, MISC_CR0_TIMER0_SUSPEND); + + while (TRUE) { + VNSvInPortB(dwIoBase + MAC_REG_MISC_CR0, &byData); + if (BITbIsBitOn(byData, MISC_CR0_TIMER0_SUSPEND)) + break; + } +} + +VOID +MACvWriteEECSR( + DWORD dwIoBase, + BYTE byValue, + BYTE byRevId + ) +{ + VNSvOutPortB(dwIoBase + MAC_REG_EECSR, byValue); + + /* delay 10 micro-seconds using MAC hardware timer */ + MACvTimer0MicroSDelay(dwIoBase, byRevId, 10); +} + +BYTE +MACbyGetPhyId( + DWORD dwIoBase + ) +{ + BYTE byOrgValue; + + VNSvInPortB(dwIoBase + MAC_REG_MPHY, &byOrgValue); + return (BYTE)(byOrgValue & 0x1F); +} diff --git a/cpu/arm920t/wmt/mac.h b/cpu/arm920t/wmt/mac.h new file mode 100755 index 0000000..04dffdb --- /dev/null +++ b/cpu/arm920t/wmt/mac.h @@ -0,0 +1,844 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __MAC_H__ +#define __MAC_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__UPC_H__) +#include "upc.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +// +// Registers in the MAC +// +#define MAC_REG_PAR 0x00 // physical address +#define MAC_REG_RCR 0x06 // +#define MAC_REG_TCR 0x07 // +#define MAC_REG_CR0 0x08 // +#define MAC_REG_CR1 0x09 // +#define MAC_REG_TQWK 0x0A +#define MAC_REG_ISR 0x0C // +#define MAC_REG_IMR 0x0E // +#define MAC_REG_MAR 0x10 // +#define MAC_REG_MCAM 0x10 // +#define MAC_REG_VCAM 0x16 // +#define MAC_REG_CUR_RD_ADDR 0x18 // +#define MAC_REG_CUR_TD_ADDR 0x1C // +#define MAC_REG_RX_DMA_PTR 0x60 // +#define MAC_REG_MPHY 0x6C // +#define MAC_REG_MIISR 0x6D // +#define MAC_REG_BCR0 0x6E // +#define MAC_REG_BCR1 0x6F // +#define MAC_REG_MIICR 0x70 // +#define MAC_REG_MIIAD 0x71 // +#define MAC_REG_MIIDATA 0x72 // +#define MAC_REG_EECSR 0x74 // +#define MAC_REG_TEST 0x75 // +#define MAC_REG_CFGA 0x78 // +#define MAC_REG_CFGB 0x79 // +#define MAC_REG_CFGC 0x7A // +#define MAC_REG_CFGD 0x7B // +#define MAC_REG_CNTR_MPA 0x7C // +#define MAC_REG_CNTR_CRC 0x7E // + +// Registers only in integrated LAN +#define MAC_REG_BISTCSR0 0x50 // +#define MAC_REG_BISTCSR1 0x51 // +#define MAC_REG_BISTCSR2 0x52 // +#define MAC_REG_BISTCSR3 0x53 // + +// Registers for 3065 +#define MAC_REG_GFTEST 0x54 // +#define MAC_REG_RFTCMD 0x55 // +#define MAC_REG_TFTCMD 0x56 // +#define MAC_REG_GFSTATUS 0x57 // +#define MAC_REG_BNRY 0x58 // +#define MAC_REG_CURR 0x5A // +#define MAC_REG_FIFO_DATA 0x5C // +#define MAC_REG_CUR_RXDMA 0x60 // +#define MAC_REG_CUR_TXDMA 0x64 // + +// Registers for 3359 Ethernet MAC module +#define MAC_REG_EEADR 0x7C // +#define MAC_REG_EECMD 0x7D // +#define MAC_REG_EESD_CKSUM 0x7E // +#define MAC_REG_DPMSR 0x7F // + +#define MAC_REG_MISC_CR0 0x80 // +#define MAC_REG_MISC_CR1 0x81 // +#define MAC_REG_PMCPORT 0x82 // +#define MAC_REG_STICKHW 0x83 // +#define MAC_REG_MISR 0x84 // +#define MAC_REG_MIMR 0x86 // +#define MAC_REG_CAMMSK 0x88 // +#define MAC_REG_BPMA 0x8C // +#define MAC_REG_BPMD 0x8F // +#define MAC_REG_BPCMD 0x90 // +#define MAC_REG_BPIN_DATA 0x91 // +#define MAC_REG_CAMC 0x92 // +#define MAC_REG_CAMADD 0x93 // +#define MAC_REG_EECHKSUM 0x93 // +#define MAC_REG_SUS_MII_AD 0x94 // +#define MAC_REG_MIBCR 0x94 +#define MAC_REG_MIBDATA 0x96 // +#define MAC_REG_SUS_PHY_ID 0x96 // +#define MAC_REG_MIBPORT 0x96 // +#define MAC_REG_MIBDAT 0x97 // +#define MAC_REG_PAUSE_TIMER 0x98 // +#define MAC_REG_FLOWCR0 0x98 +#define MAC_REG_SOFT_TIMER0 0x9C // +#define MAC_REG_SOFT_TIMER1 0x9E // +#define MAC_REG_WOLCR_SET 0xA0 // +#define MAC_REG_PWCFG_SET 0xA1 // +#define MAC_REG_TSTREG_SET 0xA2 // +#define MAC_REG_WOLCR1_SET 0xA2 // +#define MAC_REG_WOLCG_SET 0xA3 // +#define MAC_REG_WOLCR_CLR 0xA4 // +#define MAC_REG_PWCFG_CLR 0xA5 // +#define MAC_REG_TSTREG_CLR 0xA6 // +#define MAC_REG_WOLCR1_CLR 0xA6 // +#define MAC_REG_WOLCG_CLR 0xA7 // +#define MAC_REG_PWRCSR_SET 0xA8 // +#define MAC_REG_PWRCSR1_SET 0xA9 // +#define MAC_REG_PWRCSR_CLR 0xAC // +#define MAC_REG_PWRCSR1_CLR 0xAD // +#define MAC_REG_PATRN_CRC0 0xB0 // +#define MAC_REG_PATRN_CRC1 0xB4 // +#define MAC_REG_PATRN_CRC2 0xB8 // +#define MAC_REG_PATRN_CRC3 0xBC // +#define MAC_REG_BYTEMSK0_0 0xC0 // +#define MAC_REG_BYTEMSK0_1 0xC4 // +#define MAC_REG_BYTEMSK0_2 0xC8 // +#define MAC_REG_BYTEMSK0_3 0xCC // +#define MAC_REG_BYTEMSK1_0 0xD0 // +#define MAC_REG_BYTEMSK1_1 0xD4 // +#define MAC_REG_BYTEMSK1_2 0xD8 // +#define MAC_REG_BYTEMSK1_3 0xDC // +#define MAC_REG_BYTEMSK2_0 0xE0 // +#define MAC_REG_BYTEMSK2_1 0xE4 // +#define MAC_REG_BYTEMSK2_2 0xE8 // +#define MAC_REG_BYTEMSK2_3 0xEC // +#define MAC_REG_BYTEMSK3_0 0xF0 // +#define MAC_REG_BYTEMSK3_1 0xF4 // +#define MAC_REG_BYTEMSK3_2 0xF8 // +#define MAC_REG_BYTEMSK3_3 0xFC // + + +// +// Bits in the RCR register +// +#define RCR_RRFT2 0x80 // +#define RCR_RRFT1 0x40 // +#define RCR_RRFT0 0x20 // +#define RCR_PROM 0x10 // +#define RCR_AB 0x08 // +#define RCR_AM 0x04 // +#define RCR_AR 0x02 // +#define RCR_SEP 0x01 // + +// +// Bits in the TCR register +// +#define TCR_RTSF 0x80 // +#define TCR_RTFT1 0x40 // +#define TCR_RTFT0 0x20 // +#define TCR_OFSET 0x08 // +#define TCR_LB1 0x04 // loopback[1] +#define TCR_LB0 0x02 // loopback[0] +#define TCR_PQEN 0x01 + +// +// Bits in the CR0 register +// +#define CR0_RDMD 0x40 // rx descriptor polling demand +#define CR0_TDMD 0x20 // tx descriptor polling demand +#define CR0_TXON 0x10 // +#define CR0_RXON 0x08 // +#define CR0_STOP 0x04 // stop MAC, default = 1 +#define CR0_STRT 0x02 // start MAC +#define CR0_INIT 0x01 // start init process + +// +// Bits in the CR1 register +// +#define CR1_SFRST 0x80 // software reset +#define CR1_RDMD1 0x40 // +#define CR1_TDMD1 0x20 // +#define CR1_KEYPAG 0x10 // +#define CR1_DPOLL 0x08 // disable rx/tx auto polling +#define CR1_FDX 0x04 // full duplex mode +#define CR1_ETEN 0x02 // early tx mode +#define CR1_EREN 0x01 // early rx mode + +// +// Bits in the IMR register +// +#define IMR_KEYM 0x8000 // +#define IMR_SRCM 0x4000 // +#define IMR_ABTM 0x2000 // +#define IMR_NORBFM 0x1000 // +#define IMR_PKTRAM 0x0800 // +#define IMR_OVFM 0x0400 // +#define IMR_ETM 0x0200 // +#define IMR_ERM 0x0100 // +#define IMR_CNTM 0x0080 // +#define IMR_BEM 0x0040 // +#define IMR_RUM 0x0020 // +#define IMR_TUM 0x0010 // +#define IMR_TXEM 0x0008 // +#define IMR_RXEM 0x0004 // +#define IMR_PTXM 0x0002 // +#define IMR_PRXM 0x0001 // + +// +// Bits in the ISR (MISR) register +// +#define ISR_GENI 0x00008000UL // for 3065 +#define ISR_SRCI 0x00004000UL // +#define ISR_ABTI 0x00002000UL // +#define ISR_NORBF 0x00001000UL // +#define ISR_PKTRA 0x00000800UL // +#define ISR_OVFI 0x00000400UL // +#define ISR_UDFI 0x00000200UL // for 3065 +#define ISR_ERI 0x00000100UL // +#define ISR_CNT 0x00000080UL // +#define ISR_BE 0x00000040UL // +#define ISR_RU 0x00000020UL // +#define ISR_TU 0x00000010UL // +#define ISR_TXE 0x00000008UL // +#define ISR_RXE 0x00000004UL // +#define ISR_PTX 0x00000002UL // +#define ISR_PRX 0x00000001UL // +// Bits in MISR +#define ISR_PWEINT 0x00800000UL // power event report in test mode +#define ISR_UDPINT_CLR 0x00400000UL // userdefined, host driven interrupt.clear +#define ISR_UDPINT_SET 0x00200000UL // userdefined, host driven interrupt.Set +#define ISR_SSRCI 0x00100000UL // suspend well mii polling status change interrupt +#define ISR_TDWBRAI 0x00080000UL // TD WB queue race +#define ISR_PHYINT 0x00040000UL // PHY state change interrupt, active by + // PHYINTEN (misc.cr[9]) in normal mode +#define ISR_TM1_INT 0x00020000UL // +#define ISR_TM0_INT 0x00010000UL // + + +// +// Bits in the MIISR register +// +#define MIISR_N_FDX 0x04 +#define MIISR_LNKFL 0x02 // +#define MIISR_SPEED 0x01 // + +// +// Bits in the MIICR register +// +#define MIICR_MAUTO 0x80 // +#define MIICR_RCMD 0x40 // +#define MIICR_WCMD 0x20 // +#define MIICR_MDPM 0x10 // +#define MIICR_MOUT 0x08 // +#define MIICR_MDO 0x04 // +#define MIICR_MDI 0x02 // +#define MIICR_MDC 0x01 // + +// +// Bits in the MIIAD register +// +#define MIIAD_MIDLE 0x80 // +#define MIIAD_MSRCEN 0x40 // +#define MIIAD_MDONE 0x20 // +// +// Bits in the MIBCR register +// +#define MIBCR_MIBEN 0x10 +#define MIBCR_MIBHALF 0x20 +#define MIBCR_MIBINC 0x40 +#define MIBCR_MIBRTN 0x80 +// +// Bits in the EECSR register +// +#define EECSR_EEPR 0x80 // eeprom programed status, 73h means programed +#define EECSR_EMBP 0x40 // eeprom embeded programming +#define EECSR_AUTOLD 0x20 // eeprom content reload +#define EECSR_DPM 0x10 // eeprom direct programming +#define EECSR_CS 0x08 // eeprom CS pin +#define EECSR_SK 0x04 // eeprom SK pin +#define EECSR_DI 0x02 // eeprom DI pin +#define EECSR_DO 0x01 // eeprom DO pin + +// +// Bits in the BCR0 register +// +#define BCR0_BOOT_MASK ((BYTE) 0xC0) +#define BCR0_BOOT_INT19 ((BYTE) 0x00) +#define BCR0_BOOT_INT18 ((BYTE) 0x40) +#define BCR0_BOOT_LOCAL ((BYTE) 0x80) +#define BCR0_BOOT_BEV ((BYTE) 0xC0) + +#define BCR0_MED2 0x80 // +#define BCR0_LED100M 0x40 // +#define BCR0_CRFT2 0x20 // +#define BCR0_CRFT1 0x10 // +#define BCR0_CRFT0 0x08 // +#define BCR0_DMAL2 0x04 // +#define BCR0_DMAL1 0x02 // +#define BCR0_DMAL0 0x01 // + +// +// Bits in the BCR1 register +// +#define BCR1_MED1 0x80 // +#define BCR1_MED0 0x40 // +#define BCR1_CTSF 0x20 // +#define BCR1_CTFT1 0x10 // +#define BCR1_CTFT0 0x08 // +#define BCR1_POT2 0x04 // +#define BCR1_POT1 0x02 // +#define BCR1_POT0 0x01 // + +// +// Bits in the CFGA register +// +#define CFGA_EELOAD 0x80 // enable eeprom embeded and direct programming +#define CFGA_MMIOEN 0x20 // memory mapped I/O enable (3043) +#define CFGA_LED0S0 0x01 // + +// VT3106 +#define CFGA_PMHCTG 0x20 // pattern match crc calculation TAG info inclusion + +// +// Bits in the CFGB register +// +#define CFGB_QPKTDIS 0x80 // +#define CFGB_MRLDIS 0x20 // + +// +// Bits in the CFGC register +// +#define CFGC_BOOT_RPL ((BYTE) 0x80) //Boot method selection for VT3106S +#define CFGC_MEDEN 0x80 // +#define CFGC_BROPT 0x40 // +#define CFGC_DLYEN 0x20 // +#define CFGC_DTSEL 0x10 // +#define CFGC_BTSEL 0x08 // +#define CFGC_BPS2 0x04 // bootrom select[2] +#define CFGC_BPS1 0x02 // bootrom select[1] +#define CFGC_BPS0 0x01 // bootrom select[0] +// +// Bits in the CAMCR register +// +#define CAMC_CAMRD 0x08 +#define CAMC_CAMWR 0x04 +#define CAMC_VCAMSL 0x02 +#define CAMC_CAMEN 0x01 + +// +// Bits in the CFGD register +// +#define CFGD_GPIOEN 0x80 // +#define CFGD_DIAG 0x40 // +#define CFGD_BOOT_RPL ((BYTE) 0x20) //Boot method selection for VT3106J, VT3206 +#define CFGD_MAGIC 0x10 // +#define CFGD_CRADOM 0x08 // +#define CFGD_CAP 0x04 // +#define CFGD_MBA 0x02 // +#define CFGD_BAKOPT 0x01 // + +#define CFGD_MMIOEN 0x80 // memory mapped I/O enable (3065/3106) + +// for VT3065 + +// Bits in STICKHW +#define STICKHW_LEGWOLEN 0x0080 // status for software reference +#define STICKHW_LEGACY_WOLSR 0x0008 +#define STICKHW_LEGACY_WOLEN 0x0004 +#define STICKHW_DS1_SHADOW 0x0002 // R/W by software/cfg cycle +#define STICKHW_DS0_SHADOW 0x0001 // suspend well DS write port + +// Bits in MISC.CR0 +#define MISC_CR0_TM0US 0x20 +#define MISC_CR0_FDXTFEN 0x10 // Full-duplex flow control TX enable +#define MISC_CR0_FDXRFEN 0x08 // Full-duplex flow control RX enable +#define MISC_CR0_HDXFEN 0x04 // Half-duplex flow control enable +#define MISC_CR0_TIMER0_SUSPEND 0x02 +#define MISC_CR0_TIMER0_EN 0x01 + +// Bits in MISC.CR1 +#define MISC_CR1_FORSRST 0x40 +#define MISC_CR1_VAUXJMP 0x20 +#define MISC_CR1_PHYINT 0x02 +#define MISC_CR1_TIMER1_EN 0x01 + +// Bits in BPCMD +#define BPCMD_BPDNE 0x80 +#define BPCMD_EBPWR 0x02 +#define BPCMD_EBPRD 0x01 + +// Bits in MISR +#define MISR_PWEINT 0x80 // power event report in test mode +#define MISR_UDPINT_CLR 0x40 // userdefined, host driven interrupt.clear +#define MISR_UDPINT_SET 0x20 // userdefined, host driven interrupt.Set +#define MISR_SSRCI 0x10 // suspend well mii polling status change interrupt +#define MISR_TDWBRAI 0x08 // TD WB queue race +#define MISR_PHYINT 0x04 // PHY state change interrupt, active by + // PHYINTEN (misc.cr[9]) in normal mode +#define MISR_TM1_INT 0x02 +#define MISR_TM0_INT 0x01 + +// Bits in WOLCR +#define WOLCR_LNKOFF_EN 0x80 // link off detected enable +#define WOLCR_LNKON_EN 0x40 // link on detected enable +#define WOLCR_MAGPKT_EN 0x20 // magic packet filter enable +#define WOLCR_UNICAST_EN 0x10 // unicast filter enable +#define WOLCR_MSWOLEN3 0x08 // enable pattern match filtering +#define WOLCR_MSWOLEN2 0x04 +#define WOLCR_MSWOLEN1 0x02 +#define WOLCR_MSWOLEN0 0x01 + + +// Bits in PWCFG +#define PWCFG_SMIITIME 0x80 // internal MII I/F timing +#define PWCFG_PCISTICK 0x40 // PCI sticky R/W enable +#define PWCFG_WOLTYPE 0x20 // pulse(1) or button (0) +#define PWCFG_LEGCY_WOL 0x10 +#define PWCFG_PMCSR_PME_SR 0x08 +#define PWCFG_PMCSR_PME_EN 0x04 // control by PCISTICK +#define PWCFG_LEGACY_WOLSR 0x02 // Legacy WOL_SR shadow +#define PWCFG_LEGACY_WOLEN 0x01 // Legacy WOL_EN shadow + +// Bits in TestReg +#define TSTREG_SGENWATCH 0x08 +#define TSTREG_SMCSNOOP 0x04 +#define TSTREG_SMACTEST 0x02 +#define TSTREG_SNORMAL 0x01 + +// Bits in WOLCFG +#define WOLCFG_PME_OVR 0x80 // for legacy use, force PMEEN always +#define WOLCFG_SFDX 0x40 // full duplex while in WOL mode +#define WOLCFG_SAM 0x20 // accept multicast case reset, default=0 +#define WOLCFG_SAB 0x10 // accept broadcast case reset, default=0 +#define WOLCFG_SMIIACC 0x08 // ?? +#define WOLCFG_SMIIOPT 0x04 // MIIOPT to extend clock in suspendwell +#define WOLCFG_SSRCEN 0x02 // suspend well mii status change enable +#define WOLCFG_PHYINTEN 0x01 // 0:PHYINT trigger enable, 1:use internal MII + // to report status change + +// Bits in DPMSR +#define DPMSR_PDPM 0x04 // Direct Programming Request + +// Bits in RAMBIST CSRs +#define BISTCSR0_TSTPAT0 0x01 // +#define BISTCSR0_TSTPAT1 0x02 // +#define BISTCSR0_TSTMODE 0x04 // +#define BISTCSR0_TX0RX1 0x08 // +#define BISTCSR1_BISTGO 0x01 // +#define BISTCSR2_TSTSR 0x01 // +#define BISTCSR3_CMDPRTEN 0x02 // +#define BISTCSR3_RAMTSTEN 0x01 // + + +// Ethernet address filter type +#define PKT_TYPE_NONE 0x0000 // turn off receiver +#define PKT_TYPE_DIRECTED 0x0001 // obselete, directed address is always accepted +#define PKT_TYPE_MULTICAST 0x0002 +#define PKT_TYPE_ALL_MULTICAST 0x0004 +#define PKT_TYPE_BROADCAST 0x0008 +#define PKT_TYPE_PROMISCUOUS 0x0020 +#define PKT_TYPE_LONG 0x2000 // NOTE.... the definition of LONG is >2048 bytes in our chip +#define PKT_TYPE_RUNT 0x4000 +#define PKT_TYPE_ERROR 0x8000 // accept error packets, e.g. CRC error + + +// Loopback mode +#define MAC_LB_NONE 0x00 // +#define MAC_LB_INTERNAL 0x01 // +#define MAC_LB_PHY 0x02 // MII or Internal-10BaseT loopback + + +// Forced media type +#define FORCED_MEDIA_NONE 0x00 // +#define FORCED_MEDIA_AUTO 0x01 // +#define FORCED_MEDIA_100M_HALF 0x02 // hub card +#define FORCED_MEDIA_100M_FULL 0x03 // fiber channel +#define FORCED_MEDIA_10M_HALF 0x04 // +#define FORCED_MEDIA_10M_FULL 0x05 // + + +// enabled mask value of irq +#if defined(_SIM) +#define IMR_MASK_VALUE 0x000BFFFFUL // initial value of IMR +#else +#define IMR_MASK_VALUE 0x000BD77FUL // initial value of IMR + // ignore ABTI,PKTRACE,CNT to + // reduce intr. frequency + // NOTE.... do not enable NoBuf int mask at NDIS driver + // when (1) NoBuf -> RxThreshold = SF + // (2) OK -> RxThreshold = original value +#endif + + +// wait time within loop +#define CB_DELAY_LOOP_WAIT 10 // 10ms +#define CB_DELAY_MII_STABLE 660 // + +// max time out delay time +#define W_MAX_TIMEOUT 0x0FFFU // + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ +#define MACvRegBitsOn(dwIoBase, byRegOfs, byBits) \ +{ \ + BYTE byData; \ + VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + VNSvOutPortB(dwIoBase + byRegOfs, byData | (BYTE)(byBits)); \ +} + + +#define MACvRegBitsOff(dwIoBase, byRegOfs, byBits) \ +{ \ + BYTE byData; \ + VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + VNSvOutPortB(dwIoBase + byRegOfs, byData & (BYTE)~(byBits)); \ +} + + +// set the chip with current rx descriptor address +#define MACvSetCurrRxDescAddr(dwIoBase, dwCurrDescAddr) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_CUR_RD_ADDR, \ + dwCurrDescAddr); \ +} + +#define MACvGetCurrRxDescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_CUR_RD_ADDR, \ + (PDWORD)pdwCurrDescAddr); \ +} + + +// set the chip with current tx descriptor address +#define MACvSetCurrTxDescAddr(dwIoBase, dwCurrDescAddr) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_CUR_TD_ADDR, \ + dwCurrDescAddr); \ +} + +// set the chip with current tx descriptor address for 3106 + +#define MACvGetCurrTxDescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_CUR_TD_ADDR, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvReadTallyCounter(dwIoBase, pwRegMPA, \ + pwRegCRC) \ +{ \ + VNSvInPortW(dwIoBase + MAC_REG_CNTR_MPA, pwRegMPA); \ + VNSvInPortW(dwIoBase + MAC_REG_CNTR_CRC, pwRegCRC); \ +} + + +#define MACvStart(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_CR0, \ + CR0_TXON | CR0_RXON | CR0_STRT); \ +} + + +#define MACvRxOn(dwIoBase) \ +{ \ + BYTE byOrgValue; \ + VNSvInPortB(dwIoBase + MAC_REG_CR0, &byOrgValue); \ + byOrgValue = (BYTE)((byOrgValue & ~CR0_STOP) | CR0_RXON | CR0_STRT); \ + VNSvOutPortB(dwIoBase + MAC_REG_CR0, byOrgValue); \ +} + + +#define MACvTxOn(dwIoBase) \ +{ \ + BYTE byOrgValue; \ + VNSvInPortB(dwIoBase + MAC_REG_CR0, &byOrgValue); \ + byOrgValue = (BYTE)((byOrgValue & ~CR0_STOP) | CR0_TXON | CR0_STRT); \ + VNSvOutPortB(dwIoBase + MAC_REG_CR0, byOrgValue); \ +} + + +#define MACvTransmit(dwIoBase) \ +{ \ + BYTE byOrgValue; \ + VNSvInPortB(dwIoBase + MAC_REG_CR1, &byOrgValue); \ + byOrgValue = (BYTE)(byOrgValue | CR1_TDMD1); \ + VNSvOutPortB(dwIoBase + MAC_REG_CR1, byOrgValue); \ +} + + +#define MACvClearStckDS(dwIoBase) \ +{ \ + BYTE byOrgValue; \ + VNSvInPortB(dwIoBase + MAC_REG_STICKHW, &byOrgValue); \ + byOrgValue = byOrgValue & (BYTE)0xFC; \ + VNSvOutPortB(dwIoBase + MAC_REG_STICKHW, byOrgValue); \ +} + + +#define MACvPwrEvntDisable(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_WOLCR_CLR, 0xFF); \ + VNSvOutPortB(dwIoBase + MAC_REG_WOLCR1_CLR, 0x03); \ +} + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL +MACbIsCableLinkOk( + DWORD dwIoBase + ); + +BOOL +MACbIsIn100MMode( + DWORD dwIoBase, + BYTE byRevId + ); + +VOID +MACvIsInFullDuplexMode( + PBOOL pbFullDup, + DWORD dwIoBase + ); + +BOOL +MACbIsRegBitsOff( + DWORD dwIoBase, + BYTE byRegOfs, + BYTE byTestBits + ); + +BOOL +MACbIsRegBitsOn( + DWORD dwIoBase, + BYTE byRegOfs, + BYTE byTestBits + ); + +BOOL +MACbSafeSoftwareReset( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MACbStop( + DWORD dwIoBase + ); + +BOOL +MACbSafeStop( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MACbSafeRxOff( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MACbSafeTxOff( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MACbSoftwareReset( + DWORD dwIoBase, + BYTE byRevId + ); + +BYTE +MACbyReadEECSR( + DWORD dwIoBase + ); + +BYTE +MACbyReadMIICR( + DWORD dwIoBase + ); + +BYTE +MACbyReadMultiAddr( + DWORD dwIoBase, + UINT uByteIdx + ); + +VOID +MACvWriteMultiAddr( + DWORD dwIoBase, + UINT uByteIdx, + BYTE byData + ); + +VOID +MACvEnableMiiAutoPoll( + DWORD dwIoBase + ); + +VOID +MACvInitialize( + DWORD dwIoBase, + BYTE byRevId + ); + +VOID +MACvIntDisable( + DWORD dwIoBase, + BYTE byRevId + ); + +VOID +MACvIntEnable( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwMask + ); + +VOID +MACvSafeDisableMiiAutoPoll( + DWORD dwIoBase, + BYTE byRevId + ); + +VOID +MACvRestoreContext( + DWORD dwIoBase, + BYTE byRevId, + PBYTE pbyCxtBuf + ); + +VOID +MACvReadISR( + DWORD dwIoBase, + BYTE byRevId, + PDWORD pdwValue + ); + +VOID +MACvWriteISR( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwValue + ); + +VOID +MACvSaveContext( + DWORD dwIoBase, + BYTE byRevId, + PBYTE pbyCxtBuf + ); + +VOID +MACvSetDmaLength( + DWORD dwIoBase, + BYTE byDmaLength + ); + +VOID +MACvSetDuplexMode( + DWORD dwIoBase, + BYTE byRevId, + BOOL bFullDuplexOn + ); + +VOID +MACvSetLoopbackMode( + DWORD dwIoBase, + BYTE byLoopbackMode + ); + +VOID +MACvSetPacketFilter( + DWORD dwIoBase, + WORD wFilterType + ); + +VOID +MACvSetRxThreshold( + DWORD dwIoBase, + BYTE byThreshold + ); + +VOID +MACvGetTxThreshold( + DWORD dwIoBase, + PBYTE pbyThreshold + ); + +VOID +MACvSetTxThreshold( + DWORD dwIoBase, + BYTE byThreshold + ); + +VOID +MACvTimer0MicroSDelay( + DWORD dwIoBase, + BYTE byRevId, + UINT udelay + ); + +VOID +MACvTimer0MiniSDelay( + DWORD dwIoBase, + BYTE byRevId, + UINT udelay + ); + +VOID +MACvWriteEECSR( + DWORD dwIoBase, + BYTE byValue, + BYTE byRevId + ); + +BYTE +MACbyGetPhyId( + DWORD dwIoBase + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __MAC_H__ + diff --git a/cpu/arm920t/wmt/macif.c b/cpu/arm920t/wmt/macif.c new file mode 100755 index 0000000..8c85932 --- /dev/null +++ b/cpu/arm920t/wmt/macif.c @@ -0,0 +1,336 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +/*#ifndef _GLOBAL_H_ +#include "global.h" +#endif +#ifndef _EXTVARS_H_ +#include "extvars.h" +#endif*/ + +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif +#if !defined(__DIAG_H__) +/* #include "diag.h" */ +#endif +#include "macif.h" +#if !defined(__DBG_H__) +#include "dbg.h" +#endif + +/* #include "emacisr.h" */ +#include <net.h> +#if MACDBG +ULONG MacDebugLevel = MACDBG_INFO | MACDBG_ISR; +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +/* static BOOL s_bDiagnoseTest(PSAdapterInfo pAdapter, int idxItem, unsigned long *pcbPass, */ +/* unsigned long *pcbFail, WORD wTestCond, BOOL bShowMsg); */ + + +/*--------------------- Export Variables --------------------------*/ +/* PVOID g_pvBufferIndex = (PVOID)MEMORY_BUFFER_START; */ + +/*--------------------- Export Functions --------------------------*/ +/* for inform allocation 0f TD RD & BUFFER have done!! */ +BOOL g_bInit = FALSE; +#if MACDBG +static void register_dump(void) +{ + int i; + DWORD state; + printf("resister dump-------------------------------------------\n"); + for (i = 0; i < 32; i++) { + VNSvInPortD(sg_aAdapter->dwIoBase+4*i, &state); + printf("%08X\n", state); + } + printf("--------------------------------------------------------\n"); + return; +} + +static void TD_RD_dump(void) +{ + int i; + printf("TD dump-------------------------------------------------\n"); + for (i = 0; i < sg_aAdapter->cbTD; i++) { + printf("TSR0:%02X ", sg_aAdapter->apTD[i]->m_td0TD0.byTSR0); + printf("TSR1:%02X ", sg_aAdapter->apTD[i]->m_td0TD0.byTSR1); + printf("OWNER:%02X\n", sg_aAdapter->apTD[i]->m_td0TD0.f1Owner); + printf("Buffer length:%d ", sg_aAdapter->apTD[i]->m_td1TD1.f15TxBufLen); + printf("Chain:%02X ", sg_aAdapter->apTD[i]->m_td1TD1.f1Chain); + printf("TCR:%02X\n", sg_aAdapter->apTD[i]->m_td1TD1.byTCR); + printf("Bufferaddress:%08X\n", sg_aAdapter->apTD[i]->m_dwTxBufferAddr); + printf("NextTD:%08X\n", sg_aAdapter->apTD[i]->m_dwTxNextDescAddr); + } + printf("RD dump-------------------------------------------------\n"); + for (i = 0; i < sg_aAdapter->cbTD; i++) { + printf("RSR0:%02X ", sg_aAdapter->apRD[i]->m_rd0RD0.byRSR0); + printf("RSR1:%02X ", sg_aAdapter->apRD[i]->m_rd0RD0.byRSR1); + printf("receive length:%d ", sg_aAdapter->apRD[i]->m_rd0RD0.f15FrameLen); + printf("OWNER:%02X\n", sg_aAdapter->apRD[i]->m_rd0RD0.f1Owner); + printf("Buffer length:%d\n", sg_aAdapter->apRD[i]->m_rd1RD1.f15RxBufLen); + printf("Bufferaddress:%08X\n", sg_aAdapter->apRD[i]->m_dwRxBufferAddr); + printf("NextRD:%08X\n", sg_aAdapter->apRD[i]->m_dwRxNextDescAddr); + } + printf("--------------------------------------------------------\n"); + return; +} +#endif +int mac_startio(bd_t *bd) +{ + int ii, jj; + UINT uTotalAdapterNum = 0; + UINT uAdapterInWork = 0; + + PSAdapterInfo apAdapter[CB_MAX_NET_DEVICE]; + + /* INIT ADAPTER: */ + /* 1.allocate adapter structure */ + /* 2.Get info from NIC and store to adapter structure */ + uTotalAdapterNum = ADPuInitAll(); +#if MACDBG + printf("mac_startio - TotalAdapterNum=%d\n", uTotalAdapterNum); +#endif + if (uTotalAdapterNum == 0) { + printf("Cannot find the adapter \n"); + return 1; + } + + uTotalAdapterNum = 0; + + for (ii = 0; ii < CB_MAX_NET_DEVICE; ii++) { + if ((&sg_aAdapter[ii])->wDevId == W_DEVICE_ID_3106A || + (&sg_aAdapter[ii])->wDevId == W_DEVICE_ID_3053A) { + /* Start driver: */ + /* 1.allocte TD/RD & buffer then init them */ + /* 2.MAC init */ + /* 3.enable INT */ + /* 4.Get status from NIC and store to adapter structure */ + if (!ADPbBind(&sg_aAdapter[ii])) { + printf("Initialization of adapter[%d]'s TD RD or Init of MAC%d fail.\n", + ii, ii); + continue; + } + apAdapter[uAdapterInWork] = &sg_aAdapter[ii]; + uAdapterInWork++; + uTotalAdapterNum++; +#if MACDBG + printf("| %d) 10/100 Ethernet MAC%d |\n", ii, ii); + printf("| DevID:%04X RevID:%02X |\n", + (&sg_aAdapter[ii])->wDevId, (&sg_aAdapter[ii])->byRevId); +#endif + } + } + + if (uTotalAdapterNum == 0) { + printf("initialization is failed.\n"); + return 1; + } + + for (ii = 0; ii < CB_MAX_NET_DEVICE; ii++) { + /* init mac address from bd */ + if (ii == 0) { + for (jj = 0; jj < U_ETHER_ADDR_LEN; jj++) + VNSvOutPortB(apAdapter[ii]->dwIoBase + MAC_REG_PAR + jj, bd->bi_enetaddr[jj]); + } + /* Start mac TX/RX */ + MACvStart(apAdapter[ii]->dwIoBase); + } +#if MACDBG + printf("Initialization done..\n"); + register_dump(); + TD_RD_dump(); +#endif + g_bInit = TRUE; + return 0; +} + +static VOID s_vSetupData_TD( + PSAdapterInfo pAdapter, int entry, int length, volatile void *packet + ) +{ + int jj; + PBYTE pbyBuf; + + pbyBuf = (PBYTE)pAdapter->apTD[entry]->m_dwTxBufferAddr; + jj = 0; + while (jj < length) { + *(PBYTE)(pbyBuf+jj) = *((PBYTE)(packet+jj)); + jj++; + } + /* fill TD */ + pAdapter->apTD[entry]->m_td1TD1.f15TxBufLen = length >= 60 ? length : 60; + pAdapter->apTD[entry]->m_td1TD1.f1Chain = 1; + pAdapter->apTD[entry]->m_td1TD1.byTCR |= TCR_EDP|TCR_STP|TCR_IC; + pAdapter->apTD[entry]->m_td0TD0.f1Owner = B_OWNED_BY_CHIP; + return; +} + +int mac_send(volatile void *packet, int length) +{ + int entry, dirty, tmp; + /* use mac0 to send */ + entry = sg_aAdapter->idxTxCurDesc; + dirty = sg_aAdapter->idxTxdirtyDesc; + + #if MACDBG + printf("enter mac_send\n"); + #endif + + /* because of no interrupt, check TD status when sending begins */ + /* 1.check TD's ownership */ + if (sg_aAdapter->apTD[entry]->m_td0TD0.f1Owner == B_OWNED_BY_CHIP) { + MACvRegBitsOn(sg_aAdapter->dwIoBase, (1 << 7), MAC_REG_TQWK); + MACvTransmit(sg_aAdapter->dwIoBase); + printf("TD overflow and let DMA send first\n"); + + #if MACDBG + TD_RD_dump(); + #endif + return 1; + } + + /* 2.clear current descriptor */ + sg_aAdapter->apTD[entry]->m_td0TD0.byTSR0 = 0; + sg_aAdapter->apTD[entry]->m_td0TD0.byTSR1 = 0; + sg_aAdapter->apTD[entry]->m_td0TD0.f12VID = 0; + sg_aAdapter->apTD[entry]->m_td0TD0.f4Prioity = 0; + + /* 3.prepare data:memcopy */ + s_vSetupData_TD(sg_aAdapter, entry, length, packet); + /* printf("init TD and data\n"); */ + + /* 4.jump to next TD */ + tmp = (++sg_aAdapter->idxTxCurDesc); + sg_aAdapter->idxTxCurDesc = tmp % sg_aAdapter->cbTD; + + #if MACDBG + printf("jump to next TD=%d\n", sg_aAdapter->idxTxCurDesc); + #endif + + /* 5.trigger TDMD1& enable queue */ + MACvRegBitsOn(sg_aAdapter->dwIoBase, (1 << 7), MAC_REG_TQWK); + MACvTransmit(sg_aAdapter->dwIoBase); + + #if MACDBG + printf("data sent!\n", sg_aAdapter->idxTxCurDesc); + #endif + /* 6.error handling :checking TD if ABT, UND */ + + return 0; +} + +int mac_receive(void) +{ + PSRxDesc pRD; + int length = 0, tmp; + DWORD isr_status; + /* 1.store ISR */ + MACvReadISR(sg_aAdapter->dwIoBase, sg_aAdapter->byRevId, &isr_status); + /* 2.disable IMR */ + MACvIntDisable(sg_aAdapter->dwIoBase, sg_aAdapter->byRevId); + /* 3clear ISR */ + MACvWriteISR(sg_aAdapter->dwIoBase, sg_aAdapter->byRevId, isr_status); + + /* 4.handle ISR */ + /* 5.handle received packets until owner==chip */ + /* printf("enter mac_receive\n"); */ + while (TRUE) { + pRD = sg_aAdapter->apRD[sg_aAdapter->idxRxCurDesc]; + /* a.check RD status */ + /* if owner==chip break; */ + if (pRD->m_rd0RD0.f1Owner == B_OWNED_BY_CHIP) { + /* printf("receive done \n"); */ + break; + } + /* if ok, net_receive() */ + if (pRD->m_rd0RD0.byRSR1&RSR1_RXOK) { + NetReceive((volatile uchar *)pRD->m_dwRxBufferAddr, pRD->m_rd0RD0.f15FrameLen-4); + length += (pRD->m_rd0RD0.f15FrameLen-4); + +#if MACDBG + printf("receive ok\n"); +#endif + } else{ + /* else, error handling */ + printf("receive error status:%02X %02X%\n", + pRD->m_rd0RD0.byRSR1, + pRD->m_rd0RD0.byRSR0); + /* handler will do later */ + } + + /* b.set own==chip */ + pRD->m_rd0RD0.f1Owner = B_OWNED_BY_CHIP; + + /* c.increase to next RD */ + tmp = (++sg_aAdapter->idxRxCurDesc); + sg_aAdapter->idxRxCurDesc = tmp % sg_aAdapter->cbRD; + + #if MACDBG + printf("jump to next RD =%d\n", sg_aAdapter->idxRxCurDesc); + #endif + } + /* 6.enable IMR */ + MACvIntEnable(sg_aAdapter->dwIoBase, sg_aAdapter->byRevId, IMR_MASK_VALUE); + return length; +} + +void mac_halt(void) +{ +#if MACDBG + printf("mac halt\n"); +#endif + //if (g_bInit) + // ADPbShutdown(sg_aAdapter); + return; +} + +void mii_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + SAdapterInfo Adapter; + Adapter.dwIoBase = BA_MAC0; + Adapter.byPhyId = MACbyGetPhyId(Adapter.dwIoBase); + MIIbReadEmbedded(Adapter.dwIoBase, Adapter.byPhyId, addr, value); + #if MACDBG + printf("%02X %02X %04X\n", addr, reg, *value); + #endif +} + +void mii_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + SAdapterInfo Adapter; + Adapter.dwIoBase = BA_MAC0; + Adapter.byPhyId = MACbyGetPhyId(Adapter.dwIoBase); + MIIbWriteEmbedded(Adapter.dwIoBase, Adapter.byPhyId, addr, value); + #if MACDBG + printf("%02X %02X %04X\n", addr, reg, value); + #endif +} diff --git a/cpu/arm920t/wmt/macif.h b/cpu/arm920t/wmt/macif.h new file mode 100755 index 0000000..44455af --- /dev/null +++ b/cpu/arm920t/wmt/macif.h @@ -0,0 +1,71 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef _MACIF_H_ +#define _MACIF_H_ + +#include "ttype.h" +/*--------------------- Export Definitions -------------------------*/ +#define BA_MAC0 0xd8004000 /* MAC0 Base Address */ +#define BA_MAC1 0xd8005000 /* MAC1 Base Address */ +#define MEMORY_BUFFER_START 0x01000000 /* Start address of allocated memory buffer */ +#define CB_MAX_NET_DEVICE 1 /* max. # of the devices */ +#define W_MAX_TIMEOUT 0x0FFFU +#define MACDBG 0 /* Switch to control debug message (0/1 = Disable/Enable) */ +#define IRQ_ETH0 10 +#define IRQ_ETH1 17 +/* Definition for diagnose test condition */ +#define DIAG_AUTO_TEST 0x0001 +#define DIAG_NO_WAIT 0x0002 +#define DIAG_REPORT 0x0004 +#define DIAG_NO_CABLE_TEST 0x0008 +#define DIAG_EXT_LOOPBACK 0x0010 + +#define PCI_Configuration_Space_Offset 0x100 +#define VEE 0x5c +#define VMSTS 0x7c +#define MaxTimeOut 1000 + +extern BOOL g_bInit; + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +#include <asm/u-boot.h> + +int mac_startio(bd_t* bd ); +int mac_send(volatile void *packet, int length); +int mac_receive(void); +void mac_halt(void); +void mii_read(char *devname, unsigned char addr,unsigned char reg, unsigned short * value); +void mii_write(char *devname, unsigned char addr,unsigned char reg, unsigned short value) ; +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* _MACIF_H_ */ diff --git a/cpu/arm920t/wmt/mem.c b/cpu/arm920t/wmt/mem.c new file mode 100755 index 0000000..dbeadad --- /dev/null +++ b/cpu/arm920t/wmt/mem.c @@ -0,0 +1,113 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +/*#ifndef _GLOBAL_H_ +#include "global.h" +#endif +#ifndef _EXTVARS_H_ +#include "extvars.h" +#endif*/ + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__MEM_H__) +#include "mem.h" +#endif +#include <malloc.h> +#include "macif.h" + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +extern PVOID g_pvBufferIndex; + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +VOID +MEMvAlign( + PSAllocMap pamMem, + UINT uBoundary + ) +{ + ULONG ulAlignmentOffset = 0; + + if ((pamMem->dwRawVAddr % uBoundary) != 0) + ulAlignmentOffset = uBoundary - (pamMem->dwRawVAddr % uBoundary); + pamMem->dwVAddr = pamMem->dwRawVAddr + ulAlignmentOffset; + pamMem->dwPAddr = LODWORD(pamMem->qwRawPAddr) + ulAlignmentOffset; +} + +/*PVOID +MEMvAllocate( + UINT uCount + ) +{ + PVOID pvMemAddr; + + pvMemAddr = g_pvBufferIndex; + g_pvBufferIndex += uCount; + + return pvMemAddr; +}*/ + +VOID +MEMvAllocateShared( + PSAllocMap pamMem + ) +{ + if (!g_bInit) + pamMem->dwRawVAddr = (DWORD)mALLOc((size_t)pamMem->dwRawSize * (size_t)sizeof(BYTE)); + + /* If allocation failed, virtual/phisical address == NULL */ + if ((PVOID)pamMem->dwRawVAddr == NULL) { + LODWORD(pamMem->qwRawPAddr) = 0; + HIDWORD(pamMem->qwRawPAddr) = 0; + return; + } else + memset((PVOID)pamMem->dwRawVAddr, 0, (size_t)pamMem->dwRawSize * (size_t)sizeof(BYTE)); + + LODWORD(pamMem->qwRawPAddr) = pamMem->dwRawVAddr; + HIDWORD(pamMem->qwRawPAddr) = 0; +} + +VOID +MEMvCopy( + PVOID pvDst, + PVOID pvSrc, + UINT uCount + ) +{ + memcpy(pvDst, pvSrc, uCount); +} + +VOID +MEMvSet( + PVOID pvDst, + BYTE byPattern, + UINT uCount + ) +{ + memset(pvDst, byPattern, uCount); +} diff --git a/cpu/arm920t/wmt/mem.h b/cpu/arm920t/wmt/mem.h new file mode 100755 index 0000000..209c7fa --- /dev/null +++ b/cpu/arm920t/wmt/mem.h @@ -0,0 +1,90 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __MEM_H__ +#define __MEM_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +/* memory allocation map from RAW(allocated) memory -> ALIGNED memory */ +typedef struct tagSAllocMap { + /* this dwRawSize value must assign */ + DWORD dwRawSize; /* allocated size of the memory block */ + DWORD dwRawVAddr; /* allocated virtual address of the memory block */ + QWORD qwRawPAddr; /* allocated physical address of the memory block */ + DWORD dwSize; /* aligned size (exactly) */ + DWORD dwVAddr; /* aligned virtual address */ + DWORD dwPAddr; /* aligned physical address */ + + PVOID pvHandle; /* handle to do system-call */ + +} SAllocMap, *PSAllocMap; + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +MEMvAlign( + PSAllocMap pamMem, + UINT uBoundary + ); + +PVOID +MEMvAllocate( + UINT uCount + ); + +VOID +MEMvAllocateShared( + PSAllocMap pamMem + ); + +VOID +MEMvCopy( + PVOID pvDst, + PVOID pvSrc, + UINT uCount + ); + +VOID +MEMvSet( + PVOID pvDst, + BYTE byPattern, + UINT uCount + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __MEM_H__ */ diff --git a/cpu/arm920t/wmt/mib.h b/cpu/arm920t/wmt/mib.h new file mode 100755 index 0000000..9224965 --- /dev/null +++ b/cpu/arm920t/wmt/mib.h @@ -0,0 +1,228 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __MIB_H__ +#define __MIB_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +// +// statistic counter +// +typedef struct tagSStatCounter { + // ISR0,1 status count + // + DWORD dwIsrRxOK; + DWORD dwIsrTxOK; + DWORD dwIsrRxErr; // FOV | BUFF | CRC | FAE + DWORD dwIsrTxErr; // FUD | BUFF | ABT | BE + DWORD dwIsrRxDescUdfl; + DWORD dwIsrTxDescUdfl; + DWORD dwIsrBusErr; + DWORD dwIsrTlyCntOvfl; + + DWORD dwIsrRxErly; + + union { + DWORD dwIsrTxErly; + DWORD dwIsrTxFifoUdfl; + } u1; + + DWORD dwIsrRxFifoOvfl; + DWORD dwIsrRxPktRace; + DWORD dwIsrRxNoBuf; + DWORD dwIsrTxAbort; + DWORD dwIsrLinkStatusChg; + + // IsrKey for RevId < 3065 , GenInt for RevId >= 3065 + union { + DWORD dwIsrKey; + DWORD dwGenInt; + } u2; + + DWORD dwIsrUnknown; // unknown interrupt count + DWORD dwIsrTllyMPA; // tally counter for Miss Packet Abort + DWORD dwIsrTllyCRC; // tally counter for CRC err + + // MISR for 3065 + DWORD dwMisrSoftTimer0; + DWORD dwMisrSoftTimer1; + DWORD dwMisrPhyStatChg; + DWORD dwMisrTDWBRace; + DWORD dwMisrSSRC; + DWORD dwMisrUserDef; + DWORD dwMisrPWE; + + DWORD dwIntLinkUp; + DWORD dwIntLinkDown; + + // RSR0,1 status count + // + DWORD dwRsrCRCErr; + DWORD dwRsrFrmAlgnErr; + DWORD dwRsrFifoOvfl; + DWORD dwRsrLong; + DWORD dwRsrRunt; + DWORD dwRsrBusErr; + DWORD dwRsrBufUdfl; + DWORD dwRsrErr; // FOV | BUFF | CRC | FAE | SERR + DWORD dwRsrOK; + + DWORD dwRsrRxPacket; + DWORD dwRsrRxOctet; + DWORD dwRsrBroadcast; + DWORD dwRsrMulticast; + DWORD dwRsrDirected; + + DWORD dwRsrRxFragment; + DWORD dwRsrRxFrmLen64; + DWORD dwRsrRxFrmLen65_127; + DWORD dwRsrRxFrmLen128_255; + DWORD dwRsrRxFrmLen256_511; + DWORD dwRsrRxFrmLen512_1023; + DWORD dwRsrRxFrmLen1024_1518; + // for VT3106 + DWORD dwRsrRxVIDHit; + DWORD dwRsrRxTagFrame; + + // TSR0,1 status count + // + DWORD dwTsrTotalColRetry; // total collision retry count + DWORD dwTsrOnceCollision; // this packet only occur one collision + DWORD dwTsrMoreThanOnceCollision; // this packet occur more than one collision + + DWORD dwTsrCollision; // this packet has ever occur collision, + // that is (dwTsrOnceCollision + dwTsrMoreThanOnceCollision) + DWORD dwTsrHeartBeat; + + DWORD dwTsrAbort; + DWORD dwTsrLateCollision; + DWORD dwTsrCarrierLost; + DWORD dwTsrFifoUdfl; + DWORD dwTsrBufUdfl; + DWORD dwTsrBusErr; + DWORD dwTsrJab; + DWORD dwTsrErr; // FUD | BUFF | ABT + DWORD dwTsrOK; + + DWORD dwTsrTxPacket; + DWORD dwTsrTxOctet; + DWORD dwTsrBroadcast; + DWORD dwTsrMulticast; + DWORD dwTsrDirected; + + // RD/TD count + DWORD dwCntRxFrmLength; + DWORD dwCntTxBufLength; + + BYTE abyCntRxPattern[16]; + BYTE abyCntTxPattern[16]; + + // for pingpong + DWORD dwCntNoResponse; + DWORD dwCntSerialNumErr; + DWORD dwCntPPTDataErr; + + // PATCH.... + DWORD dwCntRxDataErr; // rx buffer data software compare CRC err count + DWORD dwIsrContinuePktRace; // if continueous packet-race happen, should reset + DWORD dwIsrContinueNoBuf; // if continueous no-buffer + + // for multi Tx descriptor + DWORD dwTDSizePerPacket[CB_MAX_DESC_PER_PKT]; + +} SStatCounter, *PSStatCounter; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +STAvClearAllCounter( + PSStatCounter pStatistic + ); + +VOID +STAvUpdateIsrStatCounter( + PSStatCounter pStatistic, + DWORD dwIsr, + BYTE byMISR + ); + +VOID +STAvUpdateRDStatCounter( + PVOID pvAdapter, + PSRxDesc prdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength + ); + +VOID +STAvUpdateRDStatCounterEx( + PVOID pvAdapter, + PSRxDesc prdCurr, + PBYTE pbyBuffer, + UINT cbFrameLength + ); + +VOID +STAvUpdateTDStatCounter( + PVOID pvAdapter, + PSStatCounter pStatistic, + BYTE byTSR0, + BYTE byTSR1, + PBYTE pbyBuffer, + UINT cbFrameLength + ); + +VOID +STAvUpdateTDStatCounterEx( + PVOID pvAdapter, + PSStatCounter pStatistic, + BYTE byTSR0, + BYTE byTSR1, + PBYTE pbyBuffer, + DWORD cbFrameLength + ); + +VOID +STAvUpdateTallyCounter( + PSStatCounter pStatistic, + WORD wMPACount, + WORD wCRCCount + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __MIB_H__ + diff --git a/cpu/arm920t/wmt/mii.c b/cpu/arm920t/wmt/mii.c new file mode 100755 index 0000000..9d0b661 --- /dev/null +++ b/cpu/arm920t/wmt/mii.c @@ -0,0 +1,352 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__MII_H__) +#include "mii.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +BOOL +MIIbIsAutoNegotiationOn( + DWORD dwIoBase, + BYTE byRevId + ) +{ + return MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_AUTO); +} + +BOOL +MIIbIsIn100MMode( + DWORD dwIoBase, + BYTE byRevId + ) +{ + if (MIIbIsAutoNegotiationOn(dwIoBase, byRevId)) { + /* If my TX_FD on, check both TX_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TXFD)) { + /* partner's TX_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TXFD)) + return TRUE; + } + + /* If my T4 on, check both T4 */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_T4)) { + /* partner's T4 */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_T4)) + return TRUE; + } + + /* If my TX_HD on, check both TX_HD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TX)) { + /* partner's TX_HD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TX)) + return TRUE; + } + + /* If my 10_FD on, check both 10_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_10FD)) { + /* partner's 10_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_10FD)) + return FALSE; + } + + /* If all above is not, then it would be 10_HD or no link */ + /* both case will be 10 Mb */ + return FALSE; + } else { + /* If in force mode */ + if (MIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED)) + return FALSE; + } + + return TRUE; +} + +BOOL +MIIbIsInFullDuplexMode( + DWORD dwIoBase, + BYTE byRevId + ) +{ + if (MIIbIsAutoNegotiationOn(dwIoBase, byRevId)) { + /* if my TX_FD on, check both TX_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TXFD)) { + /* partner's TX_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TXFD)) + return TRUE; + } + + /* if my T4 on, check both T4 */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_T4)) { + /* partner's T4 */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_T4)) + return FALSE; + } + + /* if my TX_HD on, check both TX_HD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_TX)) { + /* partner's TX_HD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_TX)) + return FALSE; + } + + /* if my 10_FD on, check both 10_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANAR, ANAR_10FD)) { + /* partner's 10_FD */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_ANLPAR, ANLPAR_10FD)) + return TRUE; + } + + /* if all above is not, then it would be 10_HD or no link */ + /* both case will be half duplex */ + return FALSE; + } else { + /* if in force mode */ + if (MIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_FDX)) + return FALSE; + } + + return TRUE; +} + +BOOL +MIIbIsRegBitsOff( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wTestBits + ) +{ + static WORD wOrgData; + + MIIbReadEmbedded(dwIoBase, byRevId, byMiiAddr, &wOrgData); + return BITbIsAllBitsOff(wOrgData, wTestBits); +} + +BOOL +MIIbIsRegBitsOn( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wTestBits + ) +{ + static WORD wOrgData; + + MIIbReadEmbedded(dwIoBase, byRevId, byMiiAddr, &wOrgData); + return BITbIsAllBitsOn(wOrgData, wTestBits); +} + + +BOOL +MIIbReadEmbedded( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + PWORD pwData + ) +{ + WORD ww; + + /* Disable MIICR_MAUTO, so that mii addr can be set normally */ + MACvSafeDisableMiiAutoPoll(dwIoBase, byRevId); + + /* MII reg offset */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIAD, byMiiAddr); + + /* Turn on MIICR_RCMD */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIICR, MIICR_RCMD); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (BITbIsBitOff(MACbyReadMIICR(dwIoBase), MIICR_RCMD)) + break; + } + + /* get MII data */ + VNSvInPortW(dwIoBase + MAC_REG_MIIDATA, pwData); + + MACvEnableMiiAutoPoll(dwIoBase); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL +MIIbWriteEmbedded( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wData + ) +{ + WORD ww; + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + MACvSafeDisableMiiAutoPoll(dwIoBase, byRevId); + + /* MII reg offset */ + VNSvOutPortB(dwIoBase + MAC_REG_MIIAD, byMiiAddr); + /* set MII data */ + VNSvOutPortW(dwIoBase + MAC_REG_MIIDATA, wData); + + /* turn on MIICR_WCMD */ + MACvRegBitsOn(dwIoBase, MAC_REG_MIICR, MIICR_WCMD); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (BITbIsBitOff(MACbyReadMIICR(dwIoBase), MIICR_WCMD)) + break; + } + + MACvEnableMiiAutoPoll(dwIoBase); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +VOID +MIIvInitialize( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwPhyCmrId + ) +{ + WORD wOrgData; + + /* PHY company/module, don't care revision id */ + dwPhyCmrId &= CID_REV_ID_MASK_OFF; + + switch (dwPhyCmrId) { + case CID_NS: + case CID_MYSON: + /* for MYSON turn on LED to indicate full-duplex in 10M mode */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_PCR, PCR_LED4MODE); + break; + + case CID_ESI: + /* for ESI, set TX/ACT LED option to ACT */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_PCSR, PCSR_LEDON4ACT); + break; + + default: + break; + } + + /* if ISO is on, turn it off */ + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_BMCR, &wOrgData); + if (BITbIsBitOn(wOrgData, BMCR_ISO)) { + wOrgData &= ~BMCR_ISO; + MIIbWriteEmbedded(dwIoBase, byRevId, MII_REG_BMCR, wOrgData); + } +} + +VOID +MIIvSetLoopbackMode( + DWORD dwIoBase, + BYTE byRevId, + BYTE byLoopbackMode + ) +{ + /* handle AUTO-NEGO */ + switch (byLoopbackMode) { + case MII_LB_NONE: + //check MII loopback status + if(MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK)){ + /* turn off MII loopback */ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* must turn on AUTO-NEGO after turn off BMCR_LBK, otherwise */ + /* the AUTO-NEGO process will never end in some PHY (e.g. ESI...) */ + MIIvSetAutoNegotiationOn(dwIoBase, byRevId); + } + break; + + case MII_LB_INTERNAL: + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* select 100M */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED); + break; + + case MII_LB_ISO: + /* we achieve isolation by do loopback in MII not in Transceiver */ + MIIvSetAutoNegotiationOff(dwIoBase, byRevId); + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_LBK); + /* select 100M */ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_SPEED); + break; + + default: + break; + } + + /* wait for MII loopback to stable */ + PCAvDelayByIO(CB_DELAY_MII_LB_STABLE); +} + +VOID +MIIvWaitForNwayCompleted( + DWORD dwIoBase, + BYTE byRevId + ) +{ + UINT uu; + + /* delay about 8 sec. */ + /* wait for AUTO-NEGO to complete (may never complete if */ + /* no link), after that then, we can get correct link status */ + /* NOTE: because I have no timer, so looping is used, */ + /* if timer is available in your OS, use timer */ + /* in stead of looping */ + + /* wait for BMSR_AUTOCM to off */ + for (uu = 0; uu < CB_MAX_COUNT_AUTO_COMPLETE; uu++) { + if (MIIbIsRegBitsOff(dwIoBase, byRevId, MII_REG_BMSR, BMSR_AUTOCM)) + break; + } + /* wait for BMSR_AUTOCM to on */ + /* NOTE.... read BMSR_AUTOCM bit will also clear BMSR_LNK bit */ + for (uu = 0; uu < CB_MAX_COUNT_AUTO_COMPLETE; uu++) { + /* if AUTO-NEGO completed, then go out this loop */ + /* otherwise, count down to time out */ + if (MIIbIsRegBitsOn(dwIoBase, byRevId, MII_REG_BMSR, BMSR_AUTOCM)) + break; + } +} diff --git a/cpu/arm920t/wmt/mii.h b/cpu/arm920t/wmt/mii.h new file mode 100755 index 0000000..06e4228 --- /dev/null +++ b/cpu/arm920t/wmt/mii.h @@ -0,0 +1,270 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __MII_H__ +#define __MII_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +#define CB_DELAY_MII_LB_STABLE (1000) +#define MAX_PHY_DEVICE 32 // max. # of PHY in a MII bus + +// +// Registers in the MII (offset unit is WORD) +// +#define MII_REG_BMCR 0x00 // physical address +#define MII_REG_BMSR 0x01 // +#define MII_REG_PHYID1 0x02 // OUI +#define MII_REG_PHYID2 0x03 // OUI + Module ID + REV ID +#define MII_REG_ANAR 0x04 // +#define MII_REG_ANLPAR 0x05 // +#define MII_REG_MODCFG 0x10 +// NS, MYSON only +#define MII_REG_PCR 0x17 // +// ESI only +#define MII_REG_PCSR 0x17 // + +// +// Bits in the BMCR register +// +#define BMCR_RESET 0x8000 // +#define BMCR_LBK 0x4000 // +#define BMCR_SPEED 0x2000 // +#define BMCR_AUTO 0x1000 // +#define BMCR_PD 0x0800 // +#define BMCR_ISO 0x0400 // +#define BMCR_REAUTO 0x0200 // +#define BMCR_FDX 0x0100 // + +// +// Bits in the BMSR register +// +#define BMSR_AUTOCM 0x0020 // +#define BMSR_LNK 0x0004 // + +// +// Bits in the ANAR register +// +#define ANAR_ASMDIR 0x0800 // Asymmetric PAUSE support +#define ANAR_PAUSE 0x0400 // Symmetric PAUSE Support +#define ANAR_T4 0x0200 // +#define ANAR_TXFD 0x0100 // +#define ANAR_TX 0x0080 // +#define ANAR_10FD 0x0040 // +#define ANAR_10 0x0020 // + +// +// Bits in the ANLPAR register +// +#define ANLPAR_ASMDIR 0x0800 // Asymmetric PAUSE support +#define ANLPAR_PAUSE 0x0400 // Symmetric PAUSE Support +#define ANLPAR_T4 0x0200 // +#define ANLPAR_TXFD 0x0100 // +#define ANLPAR_TX 0x0080 // +#define ANLPAR_10FD 0x0040 // +#define ANLPAR_10 0x0020 // + + +// NS, MYSON only + +// +// Bits in the PCR register +// +#define PCR_LED4MODE 0x0002 // + + +// ESI only + +// +// Bits in the PCR register +// +#define PCSR_LEDON4ACT 0x0080 // + + +// Loopback mode +#define MII_LB_NONE 0x00 // +#define MII_LB_INTERNAL 0x01 // +#define MII_LB_ISO 0x02 // isolate endec/twister + + +// +// Company ID +// +#define CID_REV_ID_MASK_OFF 0xFFFFFFF0UL // the last 4-bit is revision id, + // we don't care it + +#define CID_NS 0x20005C00UL // OUI = 08-00-17 , 0x2000 5C01 +#define CID_ESI 0x00437400UL // , 0x0043 7412 +#define CID_DAVICOM 0x0181B800UL // OUI = 00-60-6E , 0x0181 B800 +#define CID_DAVICOM_B 0x0181B802UL // +#define CID_MYSON 0x0302D000UL // , 0x0302 D000 +#define CID_SEEQ 0x0016F880UL // OUI = 00-A0-7D , 0x0016 F880 +#define CID_BROADCOM 0x00406000UL // , 0x0040 61B1 +#define CID_KENDIN 0x00221720UL // OUI = 00-10-A1 , 0x0022 1720 +#define CID_ADHOC 0x00225610UL // OUI = 00-10-A9 , 0x0022 5610 +#define CID_AMD_AM79C901_T 0x00006B70UL // , 0x0000 6B70 +#define CID_VIA_VT3072 0x01018F20UL +//#define CID_VIA_VT3082 0x01018F20UL + +#define CB_MAX_COUNT_AUTO_COMPLETE (0x1244) + // AUTO-NEGO complete, polling time out count + // about 6 sec. + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +#define MIIvRegBitsOn(dwIoBase, byRevId, byMiiAddr, wBits) \ +{ \ + WORD wOrgData; \ + MIIbReadEmbedded(dwIoBase, byRevId, byMiiAddr, &wOrgData); \ + MIIbWriteEmbedded(dwIoBase, byRevId, byMiiAddr, \ + (WORD)(wOrgData | wBits)); \ +} + + +#define MIIvRegBitsOff(dwIoBase, byRevId, byMiiAddr, wBits) \ +{ \ + WORD wOrgData; \ + MIIbReadEmbedded(dwIoBase, byRevId, byMiiAddr, &wOrgData); \ + MIIbWriteEmbedded(dwIoBase, byRevId, byMiiAddr, \ + (WORD)(wOrgData & (~wBits))); \ +} + + +#define MIIvReadPhyCmrId(dwIoBase, byRevId, pdwPhyCmrId) \ +{ \ + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_PHYID2, \ + (PWORD)pdwPhyCmrId); \ + MIIbReadEmbedded(dwIoBase, byRevId, MII_REG_PHYID1, \ + ((PWORD)pdwPhyCmrId) + 1); \ +} + + +#define MIIvSetAutoNegotiationOn(dwIoBase, byRevId) \ +{ \ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, (BMCR_AUTO|BMCR_REAUTO)); \ +} + + +#define MIIvSetAutoNegotiationOff(dwIoBase, byRevId) \ +{ \ + MIIvRegBitsOff(dwIoBase, byRevId, MII_REG_BMCR, BMCR_AUTO); \ +} + + +#define MIIvSetResetOn(dwIoBase, byRevId) \ +{ \ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_RESET); \ +} + + +#define MIIvSetReAuto(dwIoBase, byRevId) \ +{ \ + MIIvRegBitsOn(dwIoBase, byRevId, MII_REG_BMCR, BMCR_REAUTO);\ +} + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL +MIIbIsAutoNegotiationOn( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MIIbIsIn100MMode( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MIIbIsInFullDuplexMode( + DWORD dwIoBase, + BYTE byRevId + ); + +BOOL +MIIbIsRegBitsOff( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wTestBits + ); + +BOOL +MIIbIsRegBitsOn( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wTestBits + ); + +BOOL +MIIbReadEmbedded( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + PWORD pwData + ); + +BOOL +MIIbWriteEmbedded( + DWORD dwIoBase, + BYTE byRevId, + BYTE byMiiAddr, + WORD wData + ); + +VOID +MIIvInitialize( + DWORD dwIoBase, + BYTE byRevId, + DWORD dwPhyCmrId + ); + +VOID +MIIvSetLoopbackMode( + DWORD dwIoBase, + BYTE byRevId, + BYTE byLoopbackMode + ); + +VOID +MIIvWaitForNwayCompleted( + DWORD dwIoBase, + BYTE byRevId + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __MII_H__ + diff --git a/cpu/arm920t/wmt/mmc.c b/cpu/arm920t/wmt/mmc.c new file mode 100755 index 0000000..9782a57 --- /dev/null +++ b/cpu/arm920t/wmt/mmc.c @@ -0,0 +1,2854 @@ +/*++ +Copyright (c) 2013 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531-1, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ +/* + * (C) Copyright 2003 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <malloc.h> +#include <mmc.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> +#include <part.h> +#include "ttype.h" +#include "./sdc.h" +#include <asm-arm/arch-wmt/common_def.h> +#include "../../../board/wmt/include/wmt_clk.h" +/*#define CONFIG_MMC*/ + +#ifdef CONFIG_MMC +/***********************************************************************************/ +#define BA_SDC_1 0xD800A400 /* SD Controller Base Address */ +#define BA_SDCDMA_1 0xD800A500 /* SD Controller DMA Base Address */ +#define BA_SDC 0xD800A000 /* SD Controller Base Address */ +#define BA_SDCDMA 0xD800A100 /* SD Controller DMA Base Address */ +#define BA_SDC_2 0xD800A800 /* SD Controller Base Address */ +#define BA_SDCDMA_2 0xD800A900 /* SD Controller DMA Base Address */ + + +#define SDMMC_SET_BLKSIZE(pHC, b) {pHC->blklen &= 0xF800; pHC->blklen |= ((b) & 0x7FF); } + +/* PMC module reg */ +#define PMC_BASE_ADDR 0XD8130000 +#define PMC_SD1_CLK REG32_PTR(PMC_BASE_ADDR + 0x324) +#define PMC_SD_CLK REG32_PTR(PMC_BASE_ADDR + 0x328) +#define PMC_Enable_SD_CLK REG32_PTR(PMC_BASE_ADDR + 0x254) +#define PMC_PLLB_MULTIPLIER REG32_PTR(PMC_BASE_ADDR + 0x204) +#define PMC_SD_CLOCK_EN 0x40000 + +/* GPIO module reg */ +#define GPIO_BASE_ADDR 0xD8110000 +#define GPIO_SD_ENABLE REG32_PTR(GPIO_BASE_ADDR + 0x40) + + +PWMT_SDMMC_REG pSd_Reg = (PWMT_SDMMC_REG) BA_SDC; +struct _SD_PDMA_REG_ *pSd_PDma_Reg = (struct _SD_PDMA_REG_ *) BA_SDCDMA; +PGPIO_REG GpioReg = (PGPIO_REG) GPIO_BASE_ADDR; +/*static unsigned long RCA;*/ +sd_info_t *SDDevInfo; +sd_info_t SD0DevInfo; +sd_info_t SD1DevInfo; +sd_info_t SD2DevInfo; + +static unsigned int Bitmode ; +static unsigned short chip_id; +static block_dev_desc_t *mmc_dev; +static block_dev_desc_t mmc0_dev; +static block_dev_desc_t mmc1_dev; +static block_dev_desc_t mmc2_dev; + +static int mmc_ready; +static int mmc0_ready; +static int mmc1_ready; +static int mmc2_ready; + +#define SDPRINTK(x...) do { } while (0)/*printf(x)*/ +extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd, int unit, int freq); + +/**********************************************************************************/ +int sd_command(unsigned char command, unsigned char cmdtype, unsigned int arg, unsigned char rsptype); +int sd_config_pdma(unsigned long *DescAddr, char dir); +unsigned int get_chip_version(void); + +void Change_SD_host(int host_num) +{ + switch (host_num) { + case 0: + pSd_Reg = (PWMT_SDMMC_REG) BA_SDC; + pSd_PDma_Reg = (struct _SD_PDMA_REG_ *) BA_SDCDMA; + SDDevInfo = &SD0DevInfo; + mmc_dev = &mmc0_dev; + mmc_ready = mmc0_ready; + break; + case 1: + if (chip_id == 0x3437 || + chip_id == 0x3429 || + chip_id == 0x3451 || + chip_id == 0x3445 || + chip_id == 0x3481 || + chip_id == 0x3498) { + + pSd_Reg = (PWMT_SDMMC_REG) BA_SDC_1; + pSd_PDma_Reg = (struct _SD_PDMA_REG_ *) BA_SDCDMA_1; + SDDevInfo = &SD1DevInfo; + mmc_dev = &mmc1_dev; + mmc_ready = mmc1_ready; + } + break; + case 2: + if (chip_id == 0x3445 || + chip_id == 0x3481 || + chip_id == 0x3498) { + + pSd_Reg = (PWMT_SDMMC_REG) BA_SDC_2; + pSd_PDma_Reg = (struct _SD_PDMA_REG_ *) BA_SDCDMA_2; + SDDevInfo = &SD2DevInfo; + mmc_dev = &mmc2_dev; + mmc_ready = mmc2_ready; + } + break; + default: + break; + } +} +int SD_Init_PDMA(void) +{ + pSd_PDma_Reg->DMA_GCR = SD_PDMA_GCR_SOFTRESET; + pSd_PDma_Reg->DMA_GCR = SD_PDMA_GCR_DMA_EN; + if (pSd_PDma_Reg->DMA_GCR & SD_PDMA_GCR_DMA_EN) + return 0; + else + return 1; +} + +int PrintPDMAReg(void) +{ + printf("0x00 =%x\n", pSd_PDma_Reg->DMA_GCR); + printf("0x04 =%x\n", pSd_PDma_Reg->DMA_IER); + printf("0x08 =%x\n", pSd_PDma_Reg->DMA_ISR); + printf("0x0C =%x\n", pSd_PDma_Reg->DMA_DESPR); + printf("0x10 =%x\n", pSd_PDma_Reg->DMA_RBR); + printf("0x14 =%x\n", pSd_PDma_Reg->DMA_DAR); + printf("0x18 =%x\n", pSd_PDma_Reg->DMA_BAR); + printf("0x1C =%x\n", pSd_PDma_Reg->DMA_CPR); + printf("0x20 =%x\n", pSd_PDma_Reg->DMA_CCR); +} + +/* Check Align problem. if brffer size have no align, break up a descript + into two descripts for Align problem using AXI bus.*/ +int sd_check_long_desc(unsigned long *DescAddr, int Desc_num, unsigned int ReqCount, + unsigned long *BufferAddr, unsigned long *BranchAddr, int End) +{ + unsigned long first_size, second_size; + SDPRINTK("\nDescAddr=0x%x, Desc_num=%d, ReqCount=%d,\ + BufferAddr=0x%x, BranchAddr=0x%x, End=%d\n", + DescAddr, Desc_num, ReqCount, BufferAddr, BranchAddr, End); + + first_size = (unsigned long)BufferAddr % 0x1000; + first_size = 0x1000 - first_size; + + SDPRINTK("firstsize=%d, buf+first 0x%x, sizeof=0x%x\n", + first_size, + (unsigned int)BufferAddr + first_size, + sizeof(struct _SD_PDMA_DESC_L)); + + if ((ReqCount > first_size) && (Desc_num > 1)) { + sd_init_long_desc(DescAddr, first_size, BufferAddr, BranchAddr, 0); + second_size = ReqCount - first_size; + sd_init_long_desc(BranchAddr, second_size, ((unsigned int)BufferAddr + first_size), + (unsigned int)BranchAddr + sizeof(struct _SD_PDMA_DESC_L), 1); + } else { + sd_init_long_desc(DescAddr, ReqCount, BufferAddr, BranchAddr, 1); + } + + return 0; +} + +int sd_init_long_desc(unsigned long *DescAddr, unsigned int ReqCount, + unsigned long *BufferAddr, unsigned long *BranchAddr, int End) +{ + struct _SD_PDMA_DESC_L *CurDes_L; + CurDes_L = (struct _SD_PDMA_DESC_L *) DescAddr; + /*Bug, Fix by leoli @2009.4 */ + CurDes_L->ReqCount = (u16) ReqCount; + CurDes_L->i = 0; + CurDes_L->format = 1; + CurDes_L->end = 0; + CurDes_L->DataBufferAddr = BufferAddr; + CurDes_L->BranchAddr = BranchAddr; + SDPRINTK("DescAddr=0x%x, ReqCount=%d\ + BufferAddr=0x%x, BranchAddr=0x%x,End=%d\n", + DescAddr, ReqCount, BufferAddr, BranchAddr, End); + if (End) { + CurDes_L->end = 1; + CurDes_L->i = 1; + } + SDPRINTK("ReqCount=0x%x, i=0x%x, end=0x%x, format=0x%d,\ + DataBufferAddr=0x%x,BranchAddr=0x%x\n", + CurDes_L->ReqCount, CurDes_L->i, CurDes_L->end, CurDes_L->format, + CurDes_L->DataBufferAddr, CurDes_L->BranchAddr); + return 0; +} + +int sd_pdma_handler(void) +{ + unsigned long status = SD_PDMA_CCR_Evt_no_status; + long count = 0; +/* SDPRINTK("Before polling DMA status:\nSTS[0-3]: 0x%x 0x%x 0x%x 0x%x \n",pSd_Reg->str0, + pSd_Reg->str1, pSd_Reg->str2, pSd_Reg->str3);*/ + count = 0x10000000; + /* polling CSR TC status */ + + do { + count--; + if (pSd_PDma_Reg->DMA_ISR & SD_PDMA_IER_INT_STS) { + SDPRINTK("pSd_PDma_Reg->DMA_CCR = 0x%lx!\n", pSd_PDma_Reg->DMA_CCR); + status = pSd_PDma_Reg->DMA_CCR & SD_PDMA_CCR_EvtCode; + pSd_PDma_Reg->DMA_ISR |= SD_PDMA_IER_INT_STS; + break ; + } + if (count == 0) { + SDPRINTK("SDPDMA Time Out!\n"); + break; + } + } while (1); + + /* SDPRINTK("\nPolling CSR TC status: 0x%lx!\n",status); */ + if (status == SD_PDMA_CCR_Evt_ff_underrun) + SDPRINTK("PDMA Buffer under run!\n"); + + if (status == SD_PDMA_CCR_Evt_ff_overrun) + SDPRINTK("PDMA Buffer over run!\n"); + + if (status == SD_PDMA_CCR_Evt_desp_read) + SDPRINTK("PDMA read Descriptor error!\n"); + + if (status == SD_PDMA_CCR_Evt_data_rw) + SDPRINTK("PDMA read/write memory error!\n"); + + if (status == SD_PDMA_CCR_Evt_early_end) + SDPRINTK("PDMA read early end!\n"); + + if (count == 0) { + SDPRINTK("SDPDMA TimeOut!\n"); + return -1; + } + + count = 0x10000000; + /* check write direction */ + /* Leo fix bug here, never go into the branch. */ + if ((pSd_PDma_Reg->DMA_CCR & SD_PDMA_CCR_peripheral_to_IF) == SD_PDMA_CCR_IF_to_peripheral) { + if (pSd_Reg->cmdi == WRITE_MULTIPLE_BLOCK) { + while (!(pSd_Reg->str0 & 0x10)) { + count--; + if (count == 0) { + printf("SD Control Data TimeOut!\n"); + return -1; + } + } + } + while (!(pSd_Reg->str0 & 0x30)) { + count--; + if (count == 0) { + printf("SD Control Data TimeOut!\n"); + return -1; + } + } + } + /* printf("SD handler count = %x\n",count); */ + return 0 ; +} + +void sdmmcSendExCSD(unsigned long *ahb_mem_data_in) +{ + unsigned char Resp1[4], tmp; + struct _SD_PDMA_DESC_L ReadDesc; + /* bzero(ahb_mem_data_in, 512); */ + memset(ahb_mem_data_in, 0x0, 512); + pSd_Reg->blkcnt = 0x01; + + /* set normal speed bus mode */ + pSd_Reg->extctl &= 0x7F; + + /* set time-out value */ + pSd_Reg->rtor = 0x1F; + pSd_Reg->ctlr |= 0x08; /* response FIFO reset */ + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + SD_Init_PDMA(); + sd_init_long_desc( + (unsigned long*)(&ReadDesc), + 512, + ahb_mem_data_in, + (unsigned long *)(&ReadDesc + sizeof(struct _SD_PDMA_DESC_L)), + 1 + ); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + + if (sd_command(SEND_EXT_CSD, 2, 0x0, R1) != 0) { + SDPRINTK("\nErr : send extend csd! \n"); + return; + } + + tmp = pSd_Reg->resr[0]; + Resp1[0] = pSd_Reg->resr[1]; + Resp1[1] = pSd_Reg->resr[2]; + Resp1[2] = pSd_Reg->resr[3]; + Resp1[3] = pSd_Reg->resr[4]; + /* + SDPRINTK("SWT response[31:24] =%x \n\r",Resp1[0]); + SDPRINTK("SWT response[23:16] =%x \n\r",Resp1[1]); + SDPRINTK("SWT response[15:8] =%x \n\r", Resp1[2]); + SDPRINTK("SWT response[7:0] =%x \n\r", Resp1[3]); + */ + /* while (ost_delay_ms(200) != OST_NO_ERROR); */ + + sd_pdma_handler(); + + /* *IMR0_REG = 0x08; / Clark - RX buffer half full intr enable */ + + return; + +} + +int sd_free_pdma(void) +{ + pSd_PDma_Reg->DMA_DESPR = 0; + pSd_PDma_Reg->DMA_GCR = 0; + /*SDPRINTK("sd_free_pdma okay!\n");*/ + return 0; +} + +int sdmmcSwitch(void) +{ + unsigned char *SCR ; + unsigned char tmp ; + unsigned long *ahb_mem_data_in = (unsigned long *)malloc(64); + struct _SD_PDMA_DESC_L ReadDesc; + memset(ahb_mem_data_in, 0x0, 64); + /*bzero(ahb_mem_data_in, 64);*/ + + SDDevInfo->HighSpeedSupport = SD_FALSE; + SDDevInfo->MMCMaxClockRate = SD_Clk_25MHz; + + pSd_Reg->blklen = 0x003F; + pSd_Reg->blkcnt = 0x00; + pSd_Reg->ctlr |= 0x08 ; + + + /* set normal speed bus mode */ + pSd_Reg->extctl &= 0x7F ; + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + /* Config Read DMA */ + SD_Init_PDMA(); + sd_init_long_desc( + (unsigned long *)(&ReadDesc), + 64, + ahb_mem_data_in, + (unsigned long *)(&ReadDesc + sizeof(struct _SD_PDMA_DESC_L)), + 1 + ); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + + /* (1)SD_SWITCH:Check function + * check Card support High speed mode + */ + if (sd_command(0x6, 2, 0x00FFFF01, R1) != 0) { + SDPRINTK("\nErr : send switch cmd! \n"); + return -1; + } + + sd_pdma_handler(); + + SCR = (unsigned char *)(ahb_mem_data_in); + tmp = *(SCR+16) ; + if ((tmp & 0x0F) == 0x01) { + SDDevInfo->HighSpeedSupport = SD_TRUE; + SDDevInfo->MMCMaxClockRate = SD_Clk_44MHz; + } + + /* while (ost_delay_ms(100) != OST_NO_ERROR); */ + + if (SDDevInfo->HighSpeedSupport == SD_TRUE) { + pSd_Reg->ctlr |= 0x08 ; + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + sd_init_long_desc( + (unsigned long *)(&ReadDesc), + 64, + ahb_mem_data_in, + (unsigned long *)(&ReadDesc + sizeof(struct _SD_PDMA_DESC_L)), + 1 + ); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + + /* (1)SD_SWITCH:SET function + * switch card to High speend mode + */ + if (sd_command(0x6, 2, 0x80FFFF01, R1) != 0) { + SDPRINTK("\nErr : send switch cmd! \n"); + return -1; + } + + sd_pdma_handler(); + + /* free dma */ + sd_free_pdma(); + + SCR = (unsigned char *)(ahb_mem_data_in) ; + tmp = *(SCR+16) ; + + if ((tmp & 0x0F) == 0x0F) { + SDDevInfo->HighSpeedSupport = SD_FALSE; + SDDevInfo->MMCMaxClockRate = SD_Clk_25MHz; + SDPRINTK("SD Card NormSpeed!\n") ; + return 0 ; + } else{ + SDPRINTK("SD Card High Speed!\n") ; + } + + } + + return 0 ; +} + +int sd_send_scr(void) +{ + + unsigned long sd_status; + unsigned char rb_data ; + + sd_status = sd_command(SD_SEND_SCR , 2, 0, R1); + if (sd_status != 0) + return -1; + + while ((pSd_Reg->str0 & BLK_DONE) != BLK_DONE) { + if (pSd_Reg->str1 & DATA_TIMEOUT) { + rb_data = pSd_Reg->str1 ; + rb_data = pSd_Reg->str1 ; + rb_data = pSd_Reg->str1 ; + return -1 ; + } + } + + rb_data = pSd_Reg->str0 ; + rb_data = pSd_Reg->str0 ; + rb_data = pSd_Reg->str0 ; + + return 0 ; +} + +void card_nop(void) +{ + int i = 2000 ; + do { + i--; + } while (i != 0); +} + +/*------------------------------------------------------ +*send SD command (non-data related command) to SD card +* +*arg depends on command type +* +*----------------------------------------------------- +*/ +int sd_command( + unsigned char command, + unsigned char cmdtype, + unsigned int arg, + unsigned char rsptype + ) +{ + + unsigned char rb_data ; + + + /* set command*/ + pSd_Reg->cmdi = command ; + /* set command argument*/ + pSd_Reg->cmdarg0 = (BYTE)arg; + pSd_Reg->cmdarg1 = (BYTE)(arg >> 8);/*move 8 bits*/ + pSd_Reg->cmdarg2 = (BYTE)(arg >> 16);/*move 16 bits*/ + pSd_Reg->cmdarg3 = (BYTE)(arg >> 24);/*move 24 bits*/ + pSd_Reg->respt = rsptype; + + /*clear all status registers*/ + pSd_Reg->str0 &= 0xff; + pSd_Reg->str1 &= 0xff; + pSd_Reg->str2 &= 0xff; + pSd_Reg->str3 &= 0xff; + + /*Choose SD mode*/ + if (chip_id == 0x3426) + pSd_Reg->busm &= 0xEF; + else + pSd_Reg->busm |= 0x10; + + pSd_Reg->ctlr &= 0x0F; + pSd_Reg->ctlr |= (cmdtype << 4); + + + /*send out the command*/ + pSd_Reg->ctlr |= CMD_START; + rb_data = pSd_Reg->ctlr ; + + /*wait for Ctrl[busy] clear*/ + while ((pSd_Reg->ctlr & 0x1) != 0) + ; + /*wait for command completion, STS1[cmd-rsp-done]*/ + while ((pSd_Reg->str1 & 0x4) != 0x4) { + if ((pSd_Reg->str1 & 0x2) == 0x2) { + rb_data = pSd_Reg->str1; + rb_data = pSd_Reg->str1; + rb_data = pSd_Reg->ctlr; + break; + } + } + + /*SD status : command-response time-out*/ + if ((pSd_Reg->str1 & 0x4) == 0x4) { + rb_data = pSd_Reg->str1; + rb_data = pSd_Reg->str1; + rb_data = pSd_Reg->ctlr; + return -1; + } + + return 0; +} + +int sd_app_command( + unsigned char command, + unsigned char cmdtype, + unsigned int arg, + unsigned char rsptype + ) +{ + unsigned long sd_status; + + if (command == SD_SEND_SCR) { + /*change blk length to 8 (SCR register is 8byte)*/ + pSd_Reg->blklen = 0x7; + pSd_Reg->blkcnt = 0x00; + } + + sd_status = sd_command(APP_CMD, 0, SDDevInfo->RCA, R1) ; + + /*while( ost_delay_ms(200) != OST_NO_ERROR );*/ + if (sd_status != 0) /*not successfully on CMD55*/ + return -1; + /*while( ost_delay_ms(1000) != OST_NO_ERROR );*/ + + if (command == SD_SEND_SCR) { + sd_status = sd_send_scr(); + + if (sd_status != 0) + return -1; + } else { + sd_status = sd_command(command, cmdtype, arg, rsptype) ; + + if(sd_status != 0) + return -1; + } + + return 0; +} + +int sd_alloc_desc_pool(unsigned long *DescAddr) +{ + /*bzero(DescAddr, 0x1000);*/ + return 0; +} + +int sd_init_short_desc(unsigned long *DescAddr, unsigned int ReqCount, unsigned long *BufferAddr) +{ + struct _SD_PDMA_DESC_S *CurDes_S; + CurDes_S = (struct _SD_PDMA_DESC_S *) DescAddr; + CurDes_S->ReqCount = ReqCount; + CurDes_S->i = 0; + CurDes_S->format = 0; + CurDes_S->DataBufferAddr = BufferAddr; + return 0; +} + +int sd_init_short_desc_with_end(unsigned long *DescAddr, unsigned int ReqCount, + unsigned long *BufferAddr, int end) +{ + struct _SD_PDMA_DESC_S *CurDes_S = (struct _SD_PDMA_DESC_S *) DescAddr; + sd_init_short_desc(DescAddr,ReqCount,BufferAddr); + CurDes_S->end = end; + return 0; + +} + +#define MAX_LONG_DES_LEN ((1<<16) - 32) /*2^15*/ + + +void sd_config_desc(unsigned long *DescAddr, unsigned long *BufferAddr, int Blk_Cnt) +{ + struct _SD_PDMA_DESC_S *CurDes_S = (struct _SD_PDMA_DESC_S *)DescAddr; + + CurDes_S->ReqCount = 512*Blk_Cnt; + CurDes_S->i = 1; + CurDes_S->format = 0; + CurDes_S->end = 1; + CurDes_S->DataBufferAddr = BufferAddr; + +} + + +void sd_dump_memory(int where, int how_many) +{ + unsigned long *ahb_mem_data_in = (unsigned long *)(0x4600000) ; + unsigned long * CurValue = NULL; + int Blk_Cnt = how_many; + int loop = 0; + for (CurValue=ahb_mem_data_in + (where*512/4); + loop <Blk_Cnt*512/4; + loop++, CurValue++) + { + if (loop % 8 == 0) + SDPRINTK("\n0x%8x: 0x%8lx", (where*512+loop*4), *CurValue); + else + SDPRINTK(" 0x%8lx", *CurValue); + } +} +int sd_config_pdma(unsigned long *DescAddr, char dir) +{ + pSd_PDma_Reg->DMA_IER = SD_PDMA_IER_INT_EN; + pSd_PDma_Reg->DMA_DESPR = DescAddr; + if (dir == SD_PDMA_WRITE) + pSd_PDma_Reg->DMA_CCR &= SD_PDMA_CCR_IF_to_peripheral; + else + pSd_PDma_Reg->DMA_CCR |= SD_PDMA_CCR_peripheral_to_IF; + pSd_PDma_Reg->DMA_CCR |= SD_PDMA_CCR_RUN; + return 0; +} + +int SD_Init(void) +{ + struct _SD_PDMA_DESC_L ReadDesc; + unsigned long *ahb_mem_data_in = (unsigned long *)malloc(8); + unsigned char *mmc_ext_csd = (unsigned char *)malloc(512); + memset(ahb_mem_data_in, 0x0, 8); + memset(mmc_ext_csd, 0x0, 512); + unsigned char csd[16]; + unsigned int i; + unsigned char tmp, powerupOK, FourBitSupport = SD_FALSE; + unsigned int pwr_range0, pwr_range1, pwr_range2, pwr_range3, temp; + unsigned char Read_Blk_Len, C_Size_Multi; + unsigned short C_Size, blkLength; + + unsigned long Card_Capacity, retryCount, sdstatus; + + unsigned char scr[8], card_status[5], card_status_ready[5]; + unsigned int RCA_t1, RCA_t2; + + SDDevInfo->RCAHi = 0x0; + SDDevInfo->RCALo = 0x0; + SDDevInfo->RCA = 0; + udelay(1000); + + /* get Strapping option status register */ + SDDevInfo->strapping &= 0xE; + /* if strapping is emmc+sf, SD1 need boot software reset. */ + if (SDDevInfo->CtrlID == 1 && SDDevInfo->strapping == 0x2) { + pSd_Reg->Reserved2[0] &= ~0x1; + pSd_Reg->busm &= ~0x10; + pSd_Reg->busm |= 0x10; + } + + /* (1)send CMD0 to set all sd cards into Idle state */ + sdstatus = sd_command(GO_IDLE_STATE, 0, 0, R0); + if (sdstatus != 0) + goto err; + + + /* (2)check card type and its voltage range */ + powerupOK = SD_FALSE; + retryCount = 0; + SDDevInfo->SDVersion = SD1_1; + + sdstatus = sd_command(SEND_IF_COND, 0, 0x000001AA, R1); + retryCount = 0; + while ((sdstatus != 0) && (retryCount < 5)) { /* retry 5 times */ + sdstatus = sd_command(SEND_IF_COND, 0, 0x000001AA, R1); + retryCount++; + } + + if (sdstatus == 0) { + SDDevInfo->MMC_Card = SD_FALSE; + SDDevInfo->SD_Card = SD_TRUE; + + tmp = pSd_Reg->resr[0]; /* 1st byte is cmd index, no use */ + pwr_range0 = pSd_Reg->resr[1]; /* 2st byte is resvert argument, no use */ + pwr_range1 = pSd_Reg->resr[2]; /* 3st byte is resvert argument, no use */ + pwr_range2 = pSd_Reg->resr[3]; /* 4st byte is VHS */ + pwr_range3 = pSd_Reg->resr[4]; /* 5st byte is Echo check pattern */ + + if ((pwr_range2 == 0x01) && (pwr_range3 == 0xAA)) { /* operation condition accepted by card */ + SDDevInfo->SDVersion = SD2_0; + SDPRINTK("\nSD2_0 : SDHC card!\n") ; + } else{ + printf("0x%x, 0x%x, 0x%x, 0x%x\n", pwr_range0, pwr_range1, pwr_range2, pwr_range3); + SDPRINTK("\nSD2_0 Err : power fail !\n") ; + goto err; + } + } else { + /* 2006/10/13 janshiue SEND_IF_COND(CMD8) retry 5 times no response + * it means SD card below ver 1.1 or MMC card + * F/W resend RESET(CMD0) to restart initial procedure. + */ + SDDevInfo->SDVersion = SD1_1; + sdstatus = sd_command(GO_IDLE_STATE, 0, 0, R0); + + if (sdstatus != 0) { + SDPRINTK("\nSD1_1 Err : idle fail !\n"); + goto err; + } + } + + /* for 1.0 and 1.1 */ + if (SDDevInfo->SDVersion != SD2_0) { + /* ACMD41 to get card's require voltage range */ + sdstatus = sd_app_command(SD_APP_OP_COND, 0, 0, R3); + retryCount = 0; + /* retry ACMD41 */ + while ((sdstatus != 0) && (retryCount < 20)) { + sdstatus = sd_app_command(SD_APP_OP_COND, 0, 0, R3); + retryCount++; + card_nop(); + card_nop(); + card_nop(); + } + + if (sdstatus == 0) { + SDDevInfo->MMC_Card = SD_FALSE; + SDDevInfo->SD_Card = SD_TRUE; + SDPRINTK("\nInit : SD Card !\n"); + } else { + SDDevInfo->MMCMaxClockRate = SD_Clk_15MHz; + SDDevInfo->MMC_Card = SD_TRUE; + SDDevInfo->SD_Card = SD_FALSE; + SDPRINTK("\nInit : MMC Card !\n"); + } + + } + + + /* (i)check MMC card or not */ + if (SDDevInfo->SD_Card == SD_FALSE) { + sdstatus = sd_command(GO_IDLE_STATE, 0, 0, R0); + if (sdstatus != 0) { + SDPRINTK("\nMMC Err : idle fail 1!\n"); + goto err; + } + /* CMD1 to get card's require voltage range */ + sdstatus = sd_command(SEND_OP_COND, 0x0, 0x40fc0000, R3); + retryCount = 0; + /* retry CMD1 */ + while ((sdstatus != 0) && (retryCount < 10)) { + sdstatus = sd_command(SEND_OP_COND, 0x0, 0x40fc0000, R3); + retryCount++; + } + if (sdstatus == 0) { + SDDevInfo->MMC_Card = SD_TRUE; + SDDevInfo->SD_Card = SD_FALSE; + } else { + SDDevInfo->MMC_Card = SD_FALSE; + SDDevInfo->SD_Card = SD_FALSE; + } + } + + /* no response to SD_APP_OP_COND and SEND_OP_COND */ + /* card type can't be judged */ + if ((SDDevInfo->MMC_Card == SD_FALSE) && (SDDevInfo->SD_Card == SD_FALSE)) { + SDPRINTK("\nErr : unknown type !\n"); + goto err; + } + + if (SDDevInfo->SDVersion == SD2_0) + sdstatus = sd_app_command(SD_APP_OP_COND, 0, 0x40ff8000, R3); /* 2.7~3.6 v */ + + + + /* get the retun OCR content */ + tmp = pSd_Reg->resr[0]; /* 1st byte is cmd index, no use */ + pwr_range0 = pSd_Reg->resr[1]; /* OCR[31:24] */ + pwr_range1 = pSd_Reg->resr[2]; /* OCR[23:16] */ + pwr_range2 = pSd_Reg->resr[3]; /* OCR[15:8] */ + pwr_range3 = pSd_Reg->resr[4]; /* OCR[7:0] */ + + if (SDDevInfo->SDVersion == SD2_0) { + /* to support SD2.0 High capacity card */ + pwr_range0 |= HostCapacitySupport; + } + + /* (3)power the card and wait for card power phase complete */ + + /* retry CMD1 or ACMD41 till powerup ok */ + retryCount = 0; + powerupOK = SD_FALSE; + /* add timeout to SD power up retry check (ACMD41 & CMD1). It is for plugin-plugout issue. */ + if (chip_id == 0x3481 && SDDevInfo->CtrlID == 1) { + udelay(1000); //for ASUS MID case. + } else { + udelay(64000); + } + /*add timeout to SD power up retry check (ACMD41 & CMD1). It is for plugin-plugout issue.*/ + + /* If this card is MMCcard, resend CMD0 to reset MMC card register, + * MMC card enter Idel mode. If SD card don't enter Idle mode. added by Eason 2012/6/22 */ + if (SDDevInfo->MMC_Card == SD_TRUE) { + sdstatus = sd_command(GO_IDLE_STATE, 0, 0, R0); + if (sdstatus != 0) { + SDPRINTK("\nMMC Err : idle fail 2!\n"); + goto err; + } + } + + while (powerupOK == SD_FALSE) { + if (SDDevInfo->MMC_Card == SD_TRUE) + sdstatus = sd_command(SEND_OP_COND, 0, 0x40fc0000, R3); + else{ + temp = (pwr_range0 << 24)|(pwr_range1 << 16)|(pwr_range2 << 8)|(pwr_range3) ; + sdstatus = sd_app_command(SD_APP_OP_COND, 0, temp, R3); + } + /* chek OCR[31] bit set or not */ + tmp = pSd_Reg->resr[0]; /* 1st byte is cmd index */ + tmp = pSd_Reg->resr[1]; /* OCR[31:24] */ + /* Save OCR Register */ + SDDevInfo->ocr[0] = pSd_Reg->resr[1]; + SDDevInfo->ocr[1] = pSd_Reg->resr[2]; + SDDevInfo->ocr[2] = pSd_Reg->resr[3]; + SDDevInfo->ocr[3] = pSd_Reg->resr[4]; + + if (tmp & 0x80) { + /* check CardCapacityStatus MMCA 4.2 must check this*/ + if (tmp & 0x40) + SDDevInfo->CardCapacityStatus = HighCapacity; + else + SDDevInfo->CardCapacityStatus = StandardCapacity; + + + powerupOK = SD_TRUE; + } else{ + for (i = 0; i < 20; i++) { + tmp = pSd_Reg->resr[i]; + card_nop(); + card_nop(); + card_nop(); + } + } + + + retryCount++; + udelay(64000); + + if (retryCount > 36) { + SDPRINTK("\nSD Err : power fail 1 !\n"); + goto err; + } + + } + + if (sdstatus != 0) { + SDPRINTK("\nSD Err : power fail 2 !\n"); + goto err; + } + SDPRINTK("\nInit : Read OCR OK !\n"); + /* (4)read card CID, RCA */ + sdstatus = sd_command(ALL_SEND_CID, 0, 0x0, R2); + if (sdstatus != 0) { + SDPRINTK("\n Err :send CID fail !\n"); + goto err; + } + /* Save CID Register*/ + SDDevInfo->cid[0] = pSd_Reg->resr[1]; + SDDevInfo->cid[1] = pSd_Reg->resr[2]; + SDDevInfo->cid[2] = pSd_Reg->resr[3]; + SDDevInfo->cid[3] = pSd_Reg->resr[4]; + SDDevInfo->cid[4] = pSd_Reg->resr[5]; + SDDevInfo->cid[5] = pSd_Reg->resr[6]; + SDDevInfo->cid[6] = pSd_Reg->resr[7]; + SDDevInfo->cid[7] = pSd_Reg->resr[8]; + SDDevInfo->cid[8] = pSd_Reg->resr[9]; + SDDevInfo->cid[9] = pSd_Reg->resr[10]; + SDDevInfo->cid[10] = pSd_Reg->resr[11]; + SDDevInfo->cid[11] = pSd_Reg->resr[12]; + SDDevInfo->cid[12] = pSd_Reg->resr[13]; + SDDevInfo->cid[13] = pSd_Reg->resr[14]; + SDDevInfo->cid[14] = pSd_Reg->resr[15]; + + + /************************************************** + *if SD Card, get RCA from card + *if MMC_Card, controller need to assign RCA (0xffc1) for card + **************************************************/ + if (SDDevInfo->SD_Card == SD_TRUE) { + sdstatus = sd_command(SEND_RELATIVE_ADDR, 0, 0x0, R6); + if (sdstatus != 0) { + SDPRINTK("\nSD Err :send RCA fail !\n"); + goto err; + } + + tmp = pSd_Reg->resr[1]; + SDDevInfo->RCAHi = tmp; + tmp = pSd_Reg->resr[2]; + SDDevInfo->RCALo = tmp; + } else { + /* PKtest 9/5 adjust the timeOut register value */ + sdstatus = sd_command(SET_RELATIVE_ADDR, 0, 0xffc10000, R1); + if (sdstatus != 0) { + SDPRINTK("\nMMC Err :send RCA fail !\n"); + goto err; + } + + SDDevInfo->RCAHi = 0xff; + SDDevInfo->RCALo = 0xc1; + } + + /* (5)read card CSD to know card size, capability */ + + RCA_t1 = 0x0; + RCA_t2 = 0x0; + RCA_t1 |= SDDevInfo->RCAHi; + RCA_t2 |= SDDevInfo->RCALo; + SDDevInfo->RCA = (RCA_t1 << 24) | (RCA_t2 << 16); + + sdstatus = sd_command(SEND_CSD, 0, SDDevInfo->RCA, R2); + if (sdstatus != 0) { + SDPRINTK("\nErr :send CSD fail !\n"); + goto err; + } + + /* Save CSD Register*/ + for (i = 0; i < 15; i++) { + csd[i]= pSd_Reg->resr[i+1]; + SDDevInfo->csd[i] = pSd_Reg->resr[i+1]; + } + + Read_Blk_Len = csd[5] & 0x0f; + + if ((SDDevInfo->SD_Card == SD_TRUE) && (csd[0] == 0x40)) { + /* CSD 2.0 */ + Card_Capacity = ((((csd[7] & 0x3F) << 8)|csd[8]) << 8) | csd[9]; + Card_Capacity++; + + /* SD2.0 SPEC : memory capacity = (C_SIZE + 1) * 512 K Byte + * Card_Capacity is base on 512 bytes, + * thus return Card_Capacity *((512 * 1024)/512) + */ + Card_Capacity = Card_Capacity * 1024; + SDDevInfo->SDCard_Size = Card_Capacity; + } + + if ((SDDevInfo->MMC_Card == SD_TRUE) || (csd[0] == 0x00)) { + /* MMC card or SD 1.1 below */ + C_Size = (((csd[6] & 0x03) << 8) | csd[7]) << 2 | (csd[8] & 0xC0) >> 6; + C_Size_Multi = (csd[9] & 0x3) << 1 | (csd[10] & 0x80) >> 7; + blkLength = ((unsigned short)1) << Read_Blk_Len; + Card_Capacity = ((((unsigned long)(C_Size + 1)) << (C_Size_Multi + 2)) * blkLength) / 512; + SDDevInfo->SDCard_Size = Card_Capacity; + } + + /* (6)select card */ + sdstatus = sd_command(SELECT_DESELECT_CARD, 0, SDDevInfo->RCA, R1); + if (sdstatus != 0) { + SDPRINTK("\nErr :deselect card fail !\n"); + goto err; + } + + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sdstatus != 0) + goto err; + + for (i = 0; i <= 4; i++) { + card_status[i] = 0 ; + card_status_ready[i] = 0; + } + card_status_ready[0] = 0x0; + card_status_ready[1] = 0x0; + card_status_ready[2] = 0x0; + card_status_ready[3] = 0x09; + card_status_ready[4] = 0x0; + + for (i = 1; i <= 4; i++) + card_status[i] = pSd_Reg->resr[i]; + + for (i = 1; i <= 4; i++) { + if (card_status[i] != card_status_ready[i]) { + if (card_status[4] == 0x40) { + /* back operation support */ + printf("\n !! Warning !! pSd_Reg->Rsp[4]=%X ! \n", pSd_Reg->resr[4]); + } else { + SDPRINTK("\n pSd_Reg->Rsp[1]=%X ! \n", pSd_Reg->resr[1]); + SDPRINTK("\n pSd_Reg->Rsp[2]=%X ! \n", pSd_Reg->resr[2]); + SDPRINTK("\n pSd_Reg->Rsp[3]=%X ! \n", pSd_Reg->resr[3]); + SDPRINTK("\n pSd_Reg->Rsp[4]=%X ! \n", pSd_Reg->resr[4]); + + SDPRINTK("\n Card Status Error ! \n"); + goto err; + } + } + } + SDPRINTK("\nInit : card selected !\n"); + /* (7)read card SCR to know card support 4bit mode or not */ + if (SDDevInfo->SD_Card == SD_TRUE) { + SDPRINTK("\nInit : SD card set mode !\n"); + FourBitSupport = SD_FALSE; + + SD_Init_PDMA(); + sd_init_long_desc( + (unsigned long *)&ReadDesc, + 8, + ahb_mem_data_in, + (unsigned long *)(&ReadDesc + sizeof(struct _SD_PDMA_DESC_L)), + 1 + ); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + + sdstatus = sd_app_command(SD_SEND_SCR, 2, 0x0, R1); + if (sdstatus != 0) + goto err; + + sdstatus = sd_pdma_handler(); + + if (sdstatus != 0) + goto err; + + /* Save SCR Register*/ + for (i = 0; i < 8; i++) { + scr[i] = *((uchar *)ahb_mem_data_in + i); + SDDevInfo->scr[i] = *((uchar *)ahb_mem_data_in + i); + } + /* free dma */ + sd_free_pdma(); + + + tmp = scr[0]; + if ((tmp & 0x0f) != 0x00) + SDDevInfo->HighSpeedSupport = SD_TRUE; + + tmp = scr[1]; + if ((tmp & 0x0f) == 0x05) + FourBitSupport = SD_TRUE; + } + + /* (8)set blklength and bus width */ + + /* set block length to be 512bytes */ + blkLength = 0; + blkLength = ((unsigned short)1) << Read_Blk_Len; + if (blkLength != 512) { + SDPRINTK("\nset blocklen fun. !\n"); + sdstatus = sd_command(SET_BLOCKLEN, 0, 0x200, R1); + if (sdstatus != 0) { + SDPRINTK("\nErr :set blocklen fail !\n"); + goto err; + } + } + + pSd_Reg->blklen |= 0x1FF; + + //if SD card support 4bit bus set to 4bit mode transfer + if (SDDevInfo->SD_Card == SD_TRUE) { + SDDevInfo->MMCMaxClockRate = SD_Clk_25MHz; + if (FourBitSupport == SD_TRUE) { + if (Bitmode == 0) { + sdstatus = sd_app_command(SET_BUS_WIDTH, 0, 0x2, R1); + if (sdstatus != 0) + goto err; + + /* set BusMode register to 4bit mode */ + pSd_Reg->busm |= FOURBIT_MODE; + SDPRINTK("\nSD:Four Bits Mode!\n"); + } else { + pSd_Reg->busm &= ONEBIT_MODE; + SDPRINTK("\nSD:One Bit Mode!\n"); + } + } + /* Check SD Card High Speend Support */ + if (SDDevInfo->HighSpeedSupport == SD_TRUE) { + /* SDPRINTK("\nsdmmcSwitch func.\n"); */ + + SDDevInfo->MMCMaxClockRate = SD_Clk_44MHz; + if ( sdmmcSwitch() != 0 ) { + SDPRINTK("\nErr: sdmmcSwitch func.\n"); + pSd_Reg->blklen = 0x01FF; + goto err; + } + + pSd_Reg->blklen = 0x01FF; + } + } + + + if (SDDevInfo->MMC_Card == SD_TRUE) { + SDPRINTK("\nInit :MMC card set mode !\n"); + /* save the MMCVersion */ + SDDevInfo->MMCVersion = (csd[0] >> 2) & 0x0f; + + /* check spec version */ + if (SDDevInfo->MMCVersion < MMC4_01) { + pSd_Reg->busm &= ONEBIT_MODE ; + SDPRINTK("\nMMC1_0 :One Bit Mode!\n"); + + } + if (SDDevInfo->MMCVersion >= MMC4_01) { + + sdmmcSendExCSD((unsigned long *)mmc_ext_csd); + /* Save MMC Extended CSD Register */ + for (i = 0; i < 512; i += 4) { + SDDevInfo->ext_csd[i] = *(mmc_ext_csd + i); + SDDevInfo->ext_csd[i + 1] = *(mmc_ext_csd + i + 1); + SDDevInfo->ext_csd[i + 2] = *(mmc_ext_csd + i + 2); + SDDevInfo->ext_csd[i + 3] = *(mmc_ext_csd + i + 3); + /*SDPRINTK("CMD %x SCR[%x] =%x \n", pSd_Reg->Cmd, i, *(mmc_ext_csd + i));*/ + } + Card_Capacity = SDDevInfo->ext_csd[212] << 0 | + SDDevInfo->ext_csd[213] << 8 | + SDDevInfo->ext_csd[214] << 16 | + SDDevInfo->ext_csd[215] << 24; + if (Card_Capacity) + SDDevInfo->SDCard_Size = Card_Capacity; + + tmp = *(mmc_ext_csd + 196); + if (tmp & BIT1) { /* high speed and max clock rate at 52Mhz*/ + /*high speed mode 52Mhz*/ + SDDevInfo->MMCMaxClockRate = SD_Clk_44MHz; + SDDevInfo->HighSpeedSupport = SD_TRUE; + SDPRINTK("\nMMC : CLK 48!\n"); + } else if (tmp == 0x01) {/* high speed and max clock rate at 26Mhz*/ + SDDevInfo->MMCMaxClockRate = SD_Clk_25MHz; + SDDevInfo->HighSpeedSupport = SD_FALSE; + SDPRINTK("\nMMC : CLK 24!\n"); + } else { + SDDevInfo->MMCMaxClockRate = SD_Clk_15MHz;/*Clk_15;*/ + SDDevInfo->HighSpeedSupport = SD_FALSE; + SDPRINTK("\nMMC : CLK 15!\n"); + } + + if (SDDevInfo->HighSpeedSupport == SD_TRUE) { + SDPRINTK("\nInit :MMC card High Speed Support !\n"); + /* Card support High Speed interface */ + sdstatus = sd_command(SWITCH_MMC, 0, 0x03B90100, R1); + + /*add delay to patch eMMC for MMCA 4.3*/ + udelay(10000); + + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + for (i = 1; i <= 4; i++) + card_status[i]=pSd_Reg->resr[i]; + + if ((card_status[3] & 0x80) == 0x00) { + /* switch command ok */ + /* check SWITCH to High speed timming SUCCESS */ + + sdmmcSendExCSD((unsigned long *)mmc_ext_csd); + tmp = *(mmc_ext_csd + 185); + + if (tmp == 0x01) {/* switch to high speed timming*/ + SDDevInfo->HighSpeedSupport = SD_TRUE; + SDPRINTK("\nMMC : High speed is true !\n"); + } else { /* switch failer*/ + SDDevInfo->HighSpeedSupport = SD_FALSE; + SDPRINTK("\nMMC : High speed is false !\n"); + } + } + } + + /* Use SWITCH command to set MMC 4.0 card to 4bit mode + * access = 0x3 write byte + * index = 183 point to BUS_WIDTH field + * value = 1 indicate 4 bit bus, 2 indicate 8 bit bus + */ + if (Bitmode == 0) + Bitmode = 4; + if (Bitmode == 0) { + sdstatus = sd_command(SWITCH_MMC, 0, 0x03B70200, R1); + + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + for (i = 1; i <= 4; i++) + card_status[i]=pSd_Reg->resr[i]; + + if ((card_status[3] & 0x80) == 0x00) { /* switch command ok */ + /* set BusMode register to 8bit mode */ + /* + //SDReg.BusMode |= FOURBIT_MODE; + //SDDevInfo->MMC40 = TRUE; + */ + pSd_Reg->extctl |= EIGHTBIT_MODE; + SDDevInfo->MMCVersion = MMC4_01; + SDPRINTK("\nMMC4_0 : Eight Bits Mode !\n"); + } else { + /* can't switch to 8bit mode, try 4bit mode */ + + /*2006/03/08 marked by janshiue, Since if card don't support + * 8 bit mode the card still MMC 4.0 card, it should + * perform at 1 or 4 bit mode. if set SDDevInfo->MMCVersion to + * MMC3_123. it will also disable the high speed support. + */ + /*//SDDevInfo->MMCVersion = MMC4_01;*/ + + sdstatus = sd_command(SWITCH_MMC, 0, 0x03B70100, R1); + + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + for (i = 1; i <= 4; i++) + card_status[i]=pSd_Reg->resr[i]; + + if ((card_status[3] & 0x80) == 0x00) { + /* switch command ok */ + /* set BusMode register to 4bit mode */ + pSd_Reg->busm |= FOURBIT_MODE; + SDPRINTK("\nMMC4_0:Four Bits Mode!\n"); + SDDevInfo->MMCVersion = MMC4_01; + } + + } + } + if (Bitmode == 4) { + /*switch to 4 bit mode*/ + + sdstatus = sd_command(SWITCH_MMC, 0, 0x03B70100, R1); + + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + for (i = 1; i <= 4; i++) + card_status[i] = pSd_Reg->resr[i] ; + + if ((card_status[3] & 0x80) == 0x00) { + /* switch command ok */ + /* set BusMode register to 4bit mode */ + pSd_Reg->busm |= FOURBIT_MODE; + SDPRINTK("\nMMC4_0:Four Bits Mode!\n") ; + SDDevInfo->MMCVersion = MMC4_01; + } + } + if (Bitmode == 1) { + sdstatus = sd_command(SWITCH_MMC, 0, 0x03B70000, R1); + sdstatus = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + for (i = 1; i <= 4; i++) + card_status[i] = pSd_Reg->resr[i]; + + if ((card_status[3] & 0x80) == 0x00) { + /* switch command ok */ + /* set BusMode register to 1bit mode */ + pSd_Reg->busm &= ONEBIT_MODE ; + SDPRINTK("\nMMC4_0 :One Bit Mode!\n"); + SDDevInfo->MMCVersion = MMC4_01; + } + } + + } + } + free(mmc_ext_csd); + free(ahb_mem_data_in); + return 0; +err: + free(mmc_ext_csd); + free(ahb_mem_data_in); + return -1; +} + + +int SD_Initialization(void) +{ + unsigned char sdstatus = 0; + + Bitmode = 0; /* eight/four bits mode */ + /* card type is unknown here */ + SDDevInfo->MMC_Card = SD_FALSE; + SDDevInfo->SD_Card = SD_FALSE; + SDDevInfo->SD_IO_Card = SD_FALSE; + + /* get SD/MMC card info */ + SDDevInfo->InitOK = SD_FALSE; + /* SDDevInfo->MMCMaxClockRate = Clk_375; */ + sdstatus = SD_Init(); + /* error handle during initialization */ + if (sdstatus != 0) { + printf("\nInitial SD/MMC Card Fail!\n"); + return -1; + } else { + SDDevInfo->InitOK = SD_TRUE; + printf("\nInitial SD/MMC Card OK!\n"); + } + + return 0; +} + + + +/**********************************************************************************/ +extern int +fat_register_device(block_dev_desc_t *dev_desc, int part_no); + +block_dev_desc_t * mmc_get_dev(int dev) +{ + if (dev == 0) + return ((block_dev_desc_t *)&mmc0_dev); + else if (dev == 1) + return ((block_dev_desc_t *)&mmc1_dev); + else if (dev == 2) + return ((block_dev_desc_t *)&mmc2_dev); + return NULL; +} + +/* + * FIXME needs to read cid and csd info to determine block size + * and other parameters + */ +//static uchar mmc_buf[MMC_BLOCK_SIZE]; +//static mmc_csd_t mmc_csd; + + +int +/****************************************************/ +mmc_block_read_singleblock(uchar *dst, ulong src) +/****************************************************/ +{ + unsigned long sd_status; + struct _SD_PDMA_DESC_S ReadDesc; + /*SDPRINTK("\n Read Single block begin \n");*/ + long count =1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1 ; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_read_singleblock Time Out!\n"); + break; + } + + } + + pSd_Reg->blkcnt = 0x01; + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&ReadDesc), (unsigned long*)dst, 1); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + + sd_status = sd_command(READ_SINGLE_BLOCK, 2, src, R1); + if (sd_status != 0) { + SDPRINTK("\nRead single Block CMD Err !\n"); + return -1 ; + } + + sd_status = sd_pdma_handler(); + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + /* SDPRINTK("pSd_Reg->Cmd = 0x%x\n", pSd_Reg->Cmd); + SDPRINTK("pSd_Reg->STS0 = 0x%x\n", pSd_Reg->ctrl); + SDPRINTK("pSd_Reg->DmaTout0 = 0x%x\n", pSd_Reg->DmaTout[0]); + SDPRINTK("pSd_Reg->DmaTout1 = 0x%x\n", pSd_Reg->DmaTout[1]); + SDPRINTK("pSd_Reg->STS1 = 0x%x\n", pSd_Reg->str1); + SDPRINTK("pSd_Reg->BlkCnt[0] = 0x%x\n", pSd_Reg->blkcnt); + SDPRINTK("pSd_Reg->Cbcr[0] = 0x%x\n", pSd_Reg->Cbcr[0]); + SDPRINTK("pSd_Reg->Cbcr[1] = 0x%x\n", pSd_Reg->Cbcr[1]); + SDPRINTK("pSd_Reg->Res3[0] = 0x%x\n", pSd_Reg->Res3[0]); + SDPRINTK("pSd_Reg->Res3[1] = 0x%x\n", pSd_Reg->Res3[1]);*/ + return -1 ; + + } + + /* free dma */ + sd_free_pdma(); + /*SDPRINTK("\n Read Single block end \n");*/ + return 0; + +} + +int +/****************************************************/ +mmc_block_read_multiblock(uchar *dst, ulong src, ulong ulBlockCount) +/****************************************************/ +{ + unsigned long sd_status; + struct _SD_PDMA_DESC_S ReadDesc; + long count =1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1 ; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_read_multiblock Time Out!\n"); + break; + } + + } + + /*SDPRINTK("\n Read Multi block begin \n");*/ + while (ulBlockCount > 127) { + pSd_Reg->blkcnt = (unsigned short)(127 & 0xFFFF); + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&ReadDesc), (unsigned long*)dst, 127); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + /* pSd_Reg->extctl |= 0x01; */ + + sd_status = sd_command(READ_MULTIPLE_BLOCK, 4, src, R1); + if (sd_status != 0) { + SDPRINTK("\nRead Multi Block CMD Err !\n"); + return -1; + } + + sd_status = sd_pdma_handler(); + + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + /* SDPRINTK("pSd_Reg->Cmd = 0x%x\n", pSd_Reg->Cmd); + SDPRINTK("pSd_Reg->STS0 = 0x%x\n", pSd_Reg->ctrl); + SDPRINTK("pSd_Reg->DmaTout0 = 0x%x\n", pSd_Reg->DmaTout[0]); + SDPRINTK("pSd_Reg->DmaTout1 = 0x%x\n", pSd_Reg->DmaTout[1]); + SDPRINTK("pSd_Reg->STS1 = 0x%x\n", pSd_Reg->str1); + SDPRINTK("pSd_Reg->BlkCnt[0] = 0x%x\n", pSd_Reg->blkcnt); + SDPRINTK("pSd_Reg->Cbcr[0] = 0x%x\n", pSd_Reg->Cbcr[0]); + SDPRINTK("pSd_Reg->Cbcr[1] = 0x%x\n", pSd_Reg->Cbcr[1]); + SDPRINTK("pSd_Reg->Res3[0] = 0x%x\n", pSd_Reg->Res3[0]); + SDPRINTK("pSd_Reg->Res3[1] = 0x%x\n", pSd_Reg->Res3[1]);*/ + return -1; + } + + /* free dma */ + sd_free_pdma(); + + /* send CMD12 : stop command */ + pSd_Reg->ctlr |= 0x08 ; /* response FIFO reset, */ + sd_status = sd_command(STOP_TRANSMISSION, 7, src, R1b); + if (sd_status != 0) + return -1 ; + ulBlockCount -= 127; + + if (SDDevInfo->CardCapacityStatus == 0) + src += 127*512; + else + src += 127; + dst += 127*512; + + count = 1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1 ; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + + } + if (ulBlockCount) { + pSd_Reg->blkcnt = (unsigned short)(ulBlockCount & 0xFFFF); + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&ReadDesc), (unsigned long*)dst, ulBlockCount); + sd_config_pdma((unsigned long *)(&ReadDesc), SD_PDMA_READ); + //pSd_Reg->extctl |= 0x01; + + sd_status = sd_command(READ_MULTIPLE_BLOCK, 4, src, R1); + if (sd_status != 0) { + SDPRINTK("\nRead Multi Block CMD Err !\n"); + return -1 ; + } + + sd_status = sd_pdma_handler(); + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + /* SDPRINTK("pSd_Reg->Cmd = 0x%x\n", pSd_Reg->Cmd); + SDPRINTK("pSd_Reg->STS0 = 0x%x\n", pSd_Reg->ctrl); + SDPRINTK("pSd_Reg->DmaTout0 = 0x%x\n", pSd_Reg->DmaTout[0]); + SDPRINTK("pSd_Reg->DmaTout1 = 0x%x\n", pSd_Reg->DmaTout[1]); + SDPRINTK("pSd_Reg->STS1 = 0x%x\n", pSd_Reg->str1); + SDPRINTK("pSd_Reg->BlkCnt[0] = 0x%x\n", pSd_Reg->blkcnt); + SDPRINTK("pSd_Reg->Cbcr[0] = 0x%x\n", pSd_Reg->Cbcr[0]); + SDPRINTK("pSd_Reg->Cbcr[1] = 0x%x\n", pSd_Reg->Cbcr[1]); + SDPRINTK("pSd_Reg->Res3[0] = 0x%x\n", pSd_Reg->Res3[0]); + SDPRINTK("pSd_Reg->Res3[1] = 0x%x\n", pSd_Reg->Res3[1]);*/ + return -1; + } + + /* free dma */ + sd_free_pdma(); + + /* send CMD12 : stop command */ + pSd_Reg->ctlr |= 0x08 ; /* response FIFO reset, */ + sd_status = sd_command(STOP_TRANSMISSION, 7, src, R1b); + if (sd_status != 0) + return -1; + + count =1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + + } + /*SDPRINTK("\nRead multi Block CMD OK !\n");*/ + return 0 ; +} + +int +/****************************************************/ +mmc_block_write_singleblock(uchar *src, ulong ulBlockStart) +/****************************************************/ +{ + unsigned long sd_status; + struct _SD_PDMA_DESC_S WriteDesc; + //SDPRINTK("\n Write Single block begin \n"); + long count =0x1000000; + + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + pSd_Reg->str0 |= 0x30; + + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1 ; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_write_singleblock Time Out!\n"); + break; + } + + } + + pSd_Reg->blkcnt = 0x01; + + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&WriteDesc), (unsigned long*)src, 1); + sd_config_pdma((unsigned long *)(&WriteDesc), SD_PDMA_WRITE); + + sd_status = sd_command(WRITE_SINGLE_BLOCK, 1, ulBlockStart, R1); + if (sd_status != 0) { + SDPRINTK("\nRead single Block CMD Err !\n"); + return -1; + } + + sd_status = sd_pdma_handler(); + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + return -1; + } + + /* free dma */ + sd_free_pdma(); + //SDPRINTK("\n Write Single block end \n"); + + count = 0x1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + return 0; + +} + +int +/****************************************************/ +mmc_block_write_multiblock(uchar *src, ulong ulBlockStart, ulong ulBlockCount) +/****************************************************/ +{ + unsigned long sd_status; + long count =0x1000000; + struct _SD_PDMA_DESC_S WriteDesc; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + SDPRINTK("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + while(ulBlockCount > 127) { + pSd_Reg->blkcnt = (unsigned short)(127 & 0xFFFF); + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&WriteDesc), (unsigned long*)src, 127); + sd_config_pdma((unsigned long *)(&WriteDesc), SD_PDMA_WRITE); + /* pSd_Reg->extctl |= 0x01; */ + + sd_status = sd_command(WRITE_MULTIPLE_BLOCK, 3, ulBlockStart, R1); + if (sd_status != 0) { + SDPRINTK("\nWrite Multi Block CMD Err !\n"); + return -1 ; + } + + /*sd_status = vt3400_sd_dma_handler() ;*/ + sd_status = sd_pdma_handler(); + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + return -1; + } + + /* free dma */ + sd_free_pdma(); + + /* send CMD12 : stop command */ + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + sd_status = sd_command(STOP_TRANSMISSION, 7, (unsigned int)src, R1b); + if (sd_status != 0) + return -1; + if (SDDevInfo->CardCapacityStatus == 0) + ulBlockStart += 127*512; + else + ulBlockStart += 127; + ulBlockCount -= 127; + src += 127*512; + + + count = 0x1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) { + printf("mmc_block_write_multiblock fail!\n"); + return -1; + } + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + printf("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + } + + if (ulBlockCount) { + pSd_Reg->blkcnt = (unsigned short)(ulBlockCount & 0xFFFF); + pSd_Reg->ctlr |= 0x08; /* response FIFO reset, */ + pSd_Reg->str0 |= 0xFF; + pSd_Reg->str1 |= 0xFF; + /* Config Read DMA */ + SD_Init_PDMA(); + sd_config_desc((unsigned long *)(&WriteDesc), (unsigned long*)src, ulBlockCount); + sd_config_pdma((unsigned long *)(&WriteDesc), SD_PDMA_WRITE); + //pSd_Reg->extctl |= 0x01; + + sd_status = sd_command(WRITE_MULTIPLE_BLOCK, 3, ulBlockStart, R1); + if (sd_status != 0) { + SDPRINTK("\nWrite Multi Block CMD last Err ! ulBlockStart %d ulBlockCount %d\n", ulBlockStart, ulBlockCount); + return -1 ; + } + + + sd_status = sd_pdma_handler(); + if (sd_status != 0) { + pSd_Reg->timeval = 0xefff; + return -1 ; + } + + /* free dma */ + sd_free_pdma(); + + /* send CMD12 : stop command */ + pSd_Reg->ctlr |= 0x08 ; /* response FIFO reset, */ + sd_status = sd_command(STOP_TRANSMISSION, 7, (unsigned int)src, R1b); + if (sd_status != 0) + return -1 ; + + count = 0x1000000; + while(1) { + sd_status = sd_command(SEND_STATUS, 0, SDDevInfo->RCA, R1); + if (sd_status != 0) + return -1; + if (pSd_Reg->resr[3] == 0x09) + break; + count--; + if (count == 0) { + printf("mmc_block_write_multiblock Time Out!\n"); + break; + } + + } + } + SDPRINTK("\n Write multi Block CMD OK !\n"); + return 0 ; +} + +int +/****************************************************/ +mmc_read(ulong src, uchar *dst, int size) +/****************************************************/ +{ + ulong end, part_start, part_end, aligned_start, aligned_end; + ulong mmc_block_size, mmc_block_address, ulBlockCount; + + if (size == 0) { + return 0; + } + + if (!mmc_ready) { + printf("Please initial the MMC first\n"); + return -1; + } + + mmc_block_size = MMC_BLOCK_SIZE; + mmc_block_address = ~(mmc_block_size - 1); + + src -= CFG_MMC_BASE; + end = src + size; + part_start = ~mmc_block_address & src; + part_end = ~mmc_block_address & end; + aligned_start = mmc_block_address & src; + aligned_end = mmc_block_address & end; + ulBlockCount = (aligned_end-src)/MMC_BLOCK_SIZE; + + if (ulBlockCount ==1) { + /*This is for single block read*/ + /*for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {*/ + if ((mmc_block_read_singleblock((uchar *)dst, (src>>9*SDDevInfo->CardCapacityStatus))) < 0) { + return -1; + } + /*}*/ + } else { + /*This is for multi block read*/ + if (mmc_block_read_multiblock((uchar*)dst, (src>>9*SDDevInfo->CardCapacityStatus), ulBlockCount) < 0) { + return -1; + } + } + return 0; +} + +int +/****************************************************/ +mmc_write(uchar *src, ulong dst, int size) +/****************************************************/ +{ + + return 0; +} + + +ulong +/****************************************************/ +mmc_bread(int dev_num, ulong blknr, ulong blkcnt, ulong *dst) +/****************************************************/ +{ + ulong src = 0; + //ulong src_size = 0; //20120105 by eason + //ulong SDCard_Size = SDDevInfo->SDCard_Size; + //printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + //printf(" dst 0x%x dev_num 0x%x, blknr 0x%x, blkcnt 0x%x \n", dst, dev_num, blknr, blkcnt); + //printf(" SDDevInfo->CardCapacityStatus %d \n", SDDevInfo->CardCapacityStatus); + if(!blkcnt) + return blkcnt; + + /*select host*/ + Change_SD_host(dev_num); + + if (!mmc_ready) { + printf("Please initial the MMC first\n"); + return -1; + } + + src = SDDevInfo->CardCapacityStatus ? blknr : (blknr*MMC_BLOCK_SIZE); + /*ount SD size by block based, a block = 512 bytes */ + //src_size = SDDevInfo->CardCapacityStatus ? src : (src/MMC_BLOCK_SIZE); + //if(src_size > SDCard_Size) { /*if reas address > SDCard size , the part_address is error */ + // printf("mmc_bwrite part_offset error\n"); + // return -1; + //} + + if (blkcnt == 1) { + /*This is for single block read*/ + if ((mmc_block_read_singleblock((uchar *)dst, src)) < 0) { + return -1; + } + } else { + /*This is for multi block read*/ + if (mmc_block_read_multiblock((uchar*)dst, src, blkcnt) < 0) { + return -1; + } + } + return blkcnt; +} + + +ulong +/****************************************************/ +mmc_bwrite(int dev_num, ulong blknr, ulong blkcnt, ulong *src) +/****************************************************/ +{ + ulong dst = 0; + //ulong dst_size = 0; + //ulong SDCard_Size = SDDevInfo->SDCard_Size; + dst = SDDevInfo->CardCapacityStatus ? blknr : (blknr*MMC_BLOCK_SIZE); + + /* count SD size by block based, a block = 512 bytes */ + //dst_size = SDDevInfo->CardCapacityStatus ? dst : (dst/MMC_BLOCK_SIZE); + //printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + //printf("[mmc_bwrite] dst 0x%x src 0x%x dev_num 0x%x, blknr 0x%x, blkcnt 0x%x \n", dst, src, dev_num, blknr, blkcnt); + if(!blkcnt) + return blkcnt; + + /*select host*/ + Change_SD_host(dev_num); + + if (!mmc_ready) { + printf("Please initial the MMC first\n"); + return -1; + } + //if(dst_size > SDCard_Size) { /*if write address > SDCard size , the part_offset is error */ + // printf("mmc_bwrite part_offset error\n"); + // return -1; + //} + if (blkcnt ==1) { + /*This is for single block read*/ + if ((mmc_block_write_singleblock((uchar *)src, dst)) < 0) { + return -1; + } + } else { + /*This is for multi block read*/ + if (mmc_block_write_multiblock((uchar*)src, dst, blkcnt) < 0) { + return -1; + } + } + return blkcnt; +} +int +/****************************************************/ +mmc_fb_write(unsigned dev_num, ulong blknr, ulong blkcnt, uchar *src) +/****************************************************/ +{ + ulong dst = 0; + //ulong dst_size = 0; + //ulong SDCard_Size = SDDevInfo->SDCard_Size; + dst = SDDevInfo->CardCapacityStatus ? blknr : (blknr*MMC_BLOCK_SIZE); + + /* count SD size by block based, a block = 512 bytes */ + //dst_size = SDDevInfo->CardCapacityStatus ? dst : (dst/MMC_BLOCK_SIZE); + //printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + //printf("[mmc_bwrite] dst 0x%x src 0x%x dev_num 0x%x, blknr 0x%x, blkcnt 0x%x \n", dst, src, dev_num, blknr, blkcnt); + if(!blkcnt) + return blkcnt; + + /*select host*/ + Change_SD_host(dev_num); + + if (!mmc_ready) { + printf("Please initial the MMC first\n"); + return -1; + } + //if(dst_size > SDCard_Size) { /*if write address > SDCard size , the part_offset is error */ + // printf("mmc_bwrite part_offset error\n"); + // return -1; + //} + if (blkcnt ==1) { + /*This is for single block read*/ + if ((mmc_block_write_singleblock((uchar *)src, dst)) < 0) { + return -1; + } + } else { + /*This is for multi block read*/ + if (mmc_block_write_multiblock((uchar*)src, dst, blkcnt) < 0) { + return -1; + } + } + return blkcnt; +} +int sd_set_clock(int Frequence) +{ + + if (Frequence == SD_Clk_Auto) { + /* Check SD Card */ + if (SDDevInfo->SD_Card == SD_TRUE) { + if (SDDevInfo->HighSpeedSupport == SD_TRUE) + Frequence = 6; /* 50Mhz */ + else + Frequence = 3; /* 25Mhz */ + } + + /* Check MMC Card */ + if (SDDevInfo->MMC_Card == SD_TRUE) { + if (SDDevInfo->MMCMaxClockRate == Clk_48) + Frequence = 6; /* 50Mhz */ + else if (SDDevInfo->MMCMaxClockRate == Clk_24) + Frequence = 3; /* 25Mhz */ + else if (SDDevInfo->MMCMaxClockRate == Clk_15) + Frequence = 1; /* 15Mhz */ + } + } + + switch (Frequence) { + case SD_Clk_Auto: + break; + case SD_Clk_15MHz: + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 15); + SDPRINTK("ATSMB Host0 15MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 15); + SDPRINTK("ATSMB Host1 15MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 15); + SDPRINTK("ATSMB Host2 15MHz \n"); + } + break; + case SD_Clk_20MHz: + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 20); + SDPRINTK("ATSMB Host0 20MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 20); + SDPRINTK("ATSMB Host1 20MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 20); + SDPRINTK("ATSMB Host2 20MHz \n"); + } + break; + case SD_Clk_25MHz: + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 24); + SDPRINTK("ATSMB Host0 25MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 24); + SDPRINTK("ATSMB Host1 25MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 24); + SDPRINTK("ATSMB Host2 25MHz \n"); + } + break; + case SD_Clk_33MHz: + if (SDDevInfo->SD_Card == SD_TRUE) { + pSd_Reg->extctl |= 0x80; /* Enable High Speed timing */ + } + if (SDDevInfo->MMC_Card == SD_TRUE) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + } + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 33); + SDPRINTK("ATSMB Host0 33MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing for WM3498 */ + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 33); + SDPRINTK("ATSMB Host1 33MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 33); + SDPRINTK("ATSMB Host2 33MHz \n"); + } + break; + case SD_Clk_40MHz: + if (SDDevInfo->SD_Card == SD_TRUE) { + pSd_Reg->extctl |= 0x80; /* Enable High Speed timing */ + } + if (SDDevInfo->MMC_Card == SD_TRUE) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + } + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 40); + SDPRINTK("ATSMB Host0 40MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing for WM3498 */ + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 40); + SDPRINTK("ATSMB Host1 40MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 40); + SDPRINTK("ATSMB Host2 40MHz \n"); + } + break; + case SD_Clk_44MHz: + if (SDDevInfo->SD_Card == SD_TRUE) { + pSd_Reg->extctl |= 0x80; /* Enable High Speed timing */ + } + if (SDDevInfo->MMC_Card == SD_TRUE) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + } + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 44); + SDPRINTK("ATSMB Host0 44MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing for WM3498 */ + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 44); + SDPRINTK("ATSMB Host1 44MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 44); + SDPRINTK("ATSMB Host2 44MHz \n"); + } + break; +/* case SD_Clk_50MHz: + if (SDDevInfo->SD_Card == SD_TRUE) { + pSd_Reg->extctl |= 0x80; + } + if (SDDevInfo->MMC_Card == SD_TRUE) { + pSd_Reg->extctl &= ~0x80; + } + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 2, 50); + SDPRINTK("ATSMB Host0 50MHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 2, 50); + SDPRINTK("ATSMB Host1 50MHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 2, 50); + SDPRINTK("ATSMB Host2 50MHz \n"); + } + if (SDDevInfo->CtrlID == 3) { + auto_pll_divisor(DEV_SDMMC3, SET_DIV, 2, 50); + SDPRINTK("ATSMB Host3 50MHz \n"); + } + break;*/ + case SD_Clk_400KHz: + pSd_Reg->extctl &= ~0x80; /* Disable High Speed timing */ + if (SDDevInfo->CtrlID == 0) { + auto_pll_divisor(DEV_SDMMC0, SET_DIV, 1, 400); + SDPRINTK("ATSMB Host0 400KHz \n"); + } + if (SDDevInfo->CtrlID == 1) { + auto_pll_divisor(DEV_SDMMC1, SET_DIV, 1, 400); + SDPRINTK("ATSMB Host1 400KHz \n"); + } + if (SDDevInfo->CtrlID == 2) { + auto_pll_divisor(DEV_SDMMC2, SET_DIV, 1, 400); + SDPRINTK("ATSMB Host2 400KHz \n"); + } + break; + default: + break; + } + + return 0; +} + +int +mmc_init(int verbose, int device_num) +/****************************************************/ +{ + unsigned long sd_status; + + + int Fre = 3;/*3*/ + + get_chip_version(); + if (chip_id == 0x3437 || + chip_id == 0x3429 || + chip_id == 0x3451) { + if (device_num > 1) + device_num = 1; + if (device_num < 0) + device_num = 0; + } else if (chip_id == 0x3445 || chip_id == 0x3498) { + if (device_num > 2) + device_num = 2; + if (device_num < 0) + device_num = 0; + } else if (chip_id == 0x3481) { + if (device_num > 3) + device_num = 3; + if (device_num < 0) + device_num = 0; + } else { + device_num = 0; + } + + if (device_num == 0) + auto_pll_divisor(DEV_SDMMC0, CLK_ENABLE, 0, 0); + if (device_num == 1) + auto_pll_divisor(DEV_SDMMC1, CLK_ENABLE, 0, 0); + if (device_num == 2) + auto_pll_divisor(DEV_SDMMC2, CLK_ENABLE, 0, 0); + + Change_SD_host(device_num); + memset(SDDevInfo, 0x0, sizeof(sd_info_t)); + SDDevInfo->CtrlID = (char)device_num; + + SD_Controller_Powerup(); + + sd_status = SD_Initialization(); /* for Emul. */ + if (sd_status != 0 ) + return -1 ; + Fre = SDDevInfo->MMCMaxClockRate; + switch (Fre) { + case SD_Clk_400KHz: + sd_set_clock(SD_Clk_400KHz); /* 400Khz */ + printf("SD/MMC clock is 400Khz\n"); + break; + case SD_Clk_15MHz: + sd_set_clock(SD_Clk_15MHz); /* 15Mhz */ + printf("SD/MMC clock is 15Mhz\n"); + break; + case SD_Clk_25MHz: + sd_set_clock(SD_Clk_25MHz); /* 25Mhz */ + printf("SD/MMC clock is 22.36Mhz\n"); + break; + case SD_Clk_44MHz: + sd_set_clock(SD_Clk_44MHz); /* 44Mhz */ + printf("SD/MMC clock is 41Mhz\n"); + break; + /*case SD_Clk_50MHz: + sd_set_clock(SD_Clk_50MHz); /* 48Mhz + printf( "SD/MMC clock is 50Mhz\n"); + break;*/ + default: + break; + + } + + /* set normal speed bus mode */ + /* pSd_Reg->extctl &= 0x7F; */ + + pSd_Reg->blkcnt = 0x01 ; + pSd_Reg->ctlr |= 0x08 ; // response FIFO reset, + + + mmc_dev->if_type = IF_TYPE_MMC; + mmc_dev->part_type = PART_TYPE_DOS; + mmc_dev->dev = device_num; + mmc_dev->lun = 0; + mmc_dev->type = 0; + /* FIXME fill in the correct size (is set to 32MByte) */ + mmc_dev->blksz = 512; + mmc_dev->lba = SDDevInfo->SDCard_Size; + mmc_dev->removable = 0; + mmc_dev->block_read = mmc_bread; + mmc_dev->block_write = mmc_bwrite; + + if (device_num == 0) + mmc0_ready = 1; + if (device_num == 1) + mmc1_ready = 1; + if (device_num == 2) + mmc2_ready = 1; + mmc_ready = 1; + + + printf("register mmc device\n"); + SDPRINTK("SDCard_Size = %ld MB\n",SDDevInfo->SDCard_Size / (2*1024)); + fat_register_device(mmc_dev, 1); /* partitions start counting with 1 */ + + return 0; +} + +int +mmc_ident(block_dev_desc_t *dev) +{ + return 0; +} + +int +mmc2info(ulong addr) +{ + /* FIXME hard codes to 32 MB device */ + if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000) { + return 1; + } + return 0; +} + +unsigned int get_chip_version(void) +{ + static unsigned int chip_version = 0; + unsigned int val; + + if (chip_version) + return chip_version; + + chip_id = *(unsigned short *) 0xD8120002; + switch (chip_id) { + case 0x3357: + val = *(unsigned int *)(0xd8120700); + *(unsigned int *)(0xd8120700) = val; + + val = *(unsigned int *)(0xd8120700); + chip_version = ((0xA + ((val & 0x0F) - 0x02)) << 4) + ((val & 0xF0) >> 4); + break; + case 0x3400: + val = *(unsigned int *) 0xD8120000; + chip_version = ((val & 0xF00) >> 4) + 0x90 + ((val & 0xFF) - 1); + break; + case 0x3426: + pSd_Reg = (PWMT_SDMMC_REG) BA_SDC; + pSd_PDma_Reg = (struct _SD_PDMA_REG_ *) BA_SDCDMA; + val = *(unsigned int *) 0xD8120000; + chip_version = ((val & 0xF00) >> 4) + 0x90 + ((val & 0xFF) - 1); + break; + default: + val = *(unsigned int *) 0xD8120000; + chip_version = ((val & 0xF00) >> 4) + 0x90 + ((val & 0xFF) - 1); + break; + } + chip_version = (chip_id << 16) | chip_version; + SDPRINTK( "debug chip_id = %x, chip_version = %x\n", chip_id, chip_version); + return chip_version; +} + + + +void SD_Controller_Powerup(void) +{ + +#define GPIO_PIN_Sharing REG32_PTR(GPIO_BASE_ADDR + 0x200) +#define GPIO_Strapping REG32_PTR(GPIO_BASE_ADDR + 0x100) + +/*SD0*/ +#define GPIO_INPUT_DATA_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x00C) +#define GPIO_INPUT_DATA_SD REG8_PTR(GPIO_BASE_ADDR + 0x00D) +#define GPIO_INPUT_DATA_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x03F) + +#define GPIO_Enable_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x04C) +#define GPIO_Enable_SD REG8_PTR(GPIO_BASE_ADDR + 0x04D) +#define GPIO_Enable_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x07F) + +#define GPIO_OUTPUT_Enable_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x08C) +#define GPIO_OUTPUT_Enable_SD REG8_PTR(GPIO_BASE_ADDR + 0x08D) +#define GPIO_OUTPUT_Enable_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x0BF) + +#define GPIO_OUTPUT_DATA_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x0CC) +#define GPIO_OUTPUT_DATA_SD REG8_PTR(GPIO_BASE_ADDR + 0x0CD) +#define GPIO_OUTPUT_DATA_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x0FF) + +#define GPIO_PULL_Enable_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x48C) +#define GPIO_PULL_Enable_SD REG8_PTR(GPIO_BASE_ADDR + 0x48D) +#define GPIO_PULL_Enable_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x4BF) + +#define GPIO_PULL_Control_SD018SEL REG8_PTR(GPIO_BASE_ADDR + 0x4CC) +#define GPIO_PULL_Control_SD REG8_PTR(GPIO_BASE_ADDR + 0x4CD) +#define GPIO_PULL_Control2_SD REG8_PTR(GPIO_BASE_ADDR + 0x4DB) +#define GPIO_PULL_Control_SDCardDetect REG8_PTR(GPIO_BASE_ADDR + 0x4FF) + +/*SD1*/ +#define GPIO_INPUT_DATA_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x00E) +#define GPIO_INPUT_DATA_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x010) + +#define GPIO_Enable_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x04E) +#define GPIO_Enable_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x050) + +#define GPIO_OUTPUT_Enable_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x08E) +#define GPIO_OUTPUT_Enable_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x090) + +#define GPIO_OUTPUT_DATA_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x0CE) +#define GPIO_OUTPUT_DATA_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x0D0) + +#define GPIO_PULL_Enable_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x48E) +#define GPIO_PULL_Enable_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x490) + +#define GPIO_PULL_Control_SD1 REG8_PTR(GPIO_BASE_ADDR + 0x4CE) +#define GPIO_PULL_Control_SD1Data REG8_PTR(GPIO_BASE_ADDR + 0x4D0) + +/*SD2*/ +#define GPIO_INPUT_DATA_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x013) +#define GPIO_INPUT_DATA_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x03F) + +#define GPIO_Enable_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x053) +#define GPIO_Enable_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x07F) + +#define GPIO_OUTPUT_Enable_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x093) +#define GPIO_OUTPUT_Enable_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x0BF) + +#define GPIO_OUTPUT_DATA_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x0D3) +#define GPIO_OUTPUT_DATA_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x0FF) + +#define GPIO_PULL_Enable_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x493) +#define GPIO_PULL_Enable_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x4BF) + +#define GPIO_PULL_Control_SD2 REG8_PTR(GPIO_BASE_ADDR + 0x4D3) +#define GPIO_PULL_Control_SD2CardDetect REG8_PTR(GPIO_BASE_ADDR + 0x4FF) + +/* SD pin */ +#define GPIO_SD0_CD BIT4 +#define GPIO_SD0_Data (BIT6 | BIT5 | BIT4 | BIT3) +#define GPIO_SD0_WriteProtect BIT2 +#define GPIO_SD0_Command BIT1 +#define GPIO_SD0_Clock BIT0 +#define GPIO_SD0_POWER BIT7 +#define GPIO_SD0_18SEL BIT4 + +#define GPIO_SD1_Data (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) +#define GPIO_SD1_Command BIT1 +#define GPIO_SD1_Clock BIT0 +#define GPIO_SD1_CD BIT6 +#define GPIO_SD1_WriteProtect BIT5 +#define GPIO_SD1_POWER BIT4 +#define GPIO_SD1_RSTN BIT3 + +#define GPIO_SD2_Data (BIT3 | BIT2 | BIT1 | BIT0) +#define GPIO_SD2_Command BIT4 +#define GPIO_SD2_Clock BIT5 +#define GPIO_SD2_CD BIT2 +#define GPIO_SD2_WriteProtect BIT7 +#define GPIO_SD2_POWER BIT6 + +/* PIN share switch */ +#define GPIO_SD1_PinShare BIT11 +#define GPIO_SD2_PinShare BIT28 + +#define SD0_CARD_PWR BIT1 +#define SD1_CARD_PWR BIT2 +#define SD2_CARD_PWR BIT3 + + /* unsigned long SD0_PIN,SD1_PIN,SD2_PIN; */ + /* SD0_PIN = ( GPIO_SD0_Clock | GPIO_SD0_Command | GPIO_SD0_WriteProtect | GPIO_SD0_Data); */ + /* SD1_PIN = ( GPIO_SD1_Clock | GPIO_SD1_Command | GPIO_SD1_WriteProtect | GPIO_SD1_RSTN | GPIO_SD1_CD); */ + /* SD2_PIN = ( GPIO_SD2_Clock | GPIO_SD2_Command | GPIO_SD2_WriteProtect | GPIO_SD2_Data); */ + /* Get Strapping option status register */ + SDDevInfo->strapping = *GPIO_Strapping; + + /* set normal speed bus mode */ + pSd_Reg->extctl = 0x0; + pSd_Reg->busm = 0x0; /* response FIFO reset, */ + + /* disable SD Card power */ + if (SDDevInfo->CtrlID == 0) { + /*set SD0 power pin as GPO pin*/ + *GPIO_Enable_SD |= GPIO_SD0_POWER; /*Set power pin as GPIO pin*/ + *GPIO_OUTPUT_Enable_SD |= GPIO_SD0_POWER; /*Set output pin*/ + + /*set internal pull up*/ + *GPIO_PULL_Control_SD |= GPIO_SD0_POWER; + + /*set internal pull enable*/ + *GPIO_PULL_Enable_SD |= GPIO_SD0_POWER; + + /*disable SD0 power*/ + *GPIO_OUTPUT_DATA_SD |= GPIO_SD0_POWER; + } else if (SDDevInfo->CtrlID == 1) { + /*set SD1 power pin as GPO pin*/ + *GPIO_Enable_SD1 |= GPIO_SD1_POWER; /*Set power pin as GPIO pin*/ + *GPIO_OUTPUT_Enable_SD1 |= GPIO_SD1_POWER; /*Set output pin*/ + + /*set internal pull up*/ + *GPIO_PULL_Control_SD1 |= GPIO_SD1_POWER; + + /*set internal pull enable*/ + *GPIO_PULL_Enable_SD1 |= GPIO_SD1_POWER; + + /*disable SD1 power*/ + *GPIO_OUTPUT_DATA_SD1 |= GPIO_SD1_POWER; + } else if (SDDevInfo->CtrlID == 2) { + /*set SD2 power pin as GPO pin*/ + *GPIO_Enable_SD2 |= GPIO_SD2_POWER; /*Set power pin as GPIO pin*/ + *GPIO_OUTPUT_Enable_SD2 |= GPIO_SD2_POWER; /*Set output pin*/ + + /*set internal pull up*/ + *GPIO_PULL_Control_SD2 |= GPIO_SD2_POWER; + + /*set internal pull enable*/ + *GPIO_PULL_Enable_SD2 |= GPIO_SD2_POWER; + + /*disable SD2 power*/ + *GPIO_OUTPUT_DATA_SD2 |= GPIO_SD2_POWER; + } + + /* Config SD PIN share */ + if (SDDevInfo->CtrlID == 1) + *GPIO_PIN_Sharing |= GPIO_SD1_PinShare; + else if (SDDevInfo->CtrlID == 2) + *GPIO_PIN_Sharing |= GPIO_SD2_PinShare; + + /* do not config GPIO_SD1_CD because ISR has already rum, + * config card detect will issue ISR storm. + */ + + /* Config SD to GPIO */ + if (SDDevInfo->CtrlID == 0) { + *GPIO_Enable_SD |= (GPIO_SD0_Clock | GPIO_SD0_Command | GPIO_SD0_WriteProtect | GPIO_SD0_Data); + *GPIO_Enable_SDCardDetect |= GPIO_SD0_CD; + *GPIO_Enable_SD018SEL |= GPIO_SD0_18SEL; + } else if (SDDevInfo->CtrlID == 1) { + *GPIO_Enable_SD1 |= (GPIO_SD1_Clock | GPIO_SD1_Command | GPIO_SD1_WriteProtect | GPIO_SD1_RSTN | GPIO_SD1_CD); + *GPIO_Enable_SD1Data |= GPIO_SD1_Data; + } else if (SDDevInfo->CtrlID == 2) { + *GPIO_Enable_SD2 |= (GPIO_SD2_Clock | GPIO_SD2_Command | GPIO_SD1_WriteProtect | GPIO_SD2_Data); + *GPIO_Enable_SD2CardDetect |= GPIO_SD2_CD; + } + + /* SD all pins output low */ + if (SDDevInfo->CtrlID == 0) { + *GPIO_OUTPUT_DATA_SD &= ~(GPIO_SD0_Clock | GPIO_SD0_Command | GPIO_SD0_WriteProtect | GPIO_SD0_Data); + *GPIO_OUTPUT_DATA_SDCardDetect &= ~GPIO_SD0_CD; + *GPIO_OUTPUT_DATA_SD018SEL |= GPIO_SD0_18SEL; + } else if (SDDevInfo->CtrlID == 1) { + *GPIO_OUTPUT_DATA_SD1 &= ~(GPIO_SD1_Clock | GPIO_SD1_Command | GPIO_SD1_WriteProtect | GPIO_SD1_RSTN | GPIO_SD1_CD); + *GPIO_OUTPUT_DATA_SD1Data &= ~GPIO_SD1_Data; + } else if (SDDevInfo->CtrlID == 2) { + *GPIO_OUTPUT_DATA_SD2 &= ~(GPIO_SD2_Clock | GPIO_SD2_Command | GPIO_SD1_WriteProtect | GPIO_SD2_Data); + *GPIO_OUTPUT_DATA_SD2CardDetect &= ~GPIO_SD2_CD; + } + + /* Config SD to GPO */ + if (SDDevInfo->CtrlID == 0) { + *GPIO_OUTPUT_Enable_SD |= (GPIO_SD0_Clock | GPIO_SD0_Command | GPIO_SD0_WriteProtect | GPIO_SD0_Data); + *GPIO_OUTPUT_Enable_SDCardDetect |= GPIO_SD0_CD; + *GPIO_OUTPUT_Enable_SD018SEL = GPIO_SD0_18SEL; + } else if (SDDevInfo->CtrlID == 1) { + *GPIO_OUTPUT_Enable_SD1 |= (GPIO_SD1_Clock | GPIO_SD1_Command | GPIO_SD1_WriteProtect | GPIO_SD1_RSTN | GPIO_SD1_CD); + *GPIO_OUTPUT_Enable_SD1Data |= GPIO_SD1_Data; + } else if (SDDevInfo->CtrlID == 2) { + *GPIO_OUTPUT_Enable_SD2 |= (GPIO_SD2_Clock | GPIO_SD2_Command | GPIO_SD1_WriteProtect | GPIO_SD2_Data); + *GPIO_OUTPUT_Enable_SD2CardDetect |= GPIO_SD2_CD; + } + + /* stop SD output clock */ + pSd_Reg->busm &= ~BIT4; + udelay(100000); /* for SD card, need to delay 100 ms. */ + + /* Pull up/down resister of SD Bus */ + if (SDDevInfo->CtrlID == 0) { + /*Disable Clock & CMD Pull enable*/ + *GPIO_PULL_Enable_SD &= ~(GPIO_SD0_Clock | GPIO_SD0_Command); + + /*Set CD ,WP ,DATA pin pull up*/ + *GPIO_PULL_Control_SDCardDetect |= GPIO_SD0_CD; + *GPIO_PULL_Control_SD |= (GPIO_SD0_Data | GPIO_SD0_WriteProtect); + *GPIO_PULL_Control_SD018SEL |= GPIO_SD0_18SEL; + + /*Enable CD ,WP ,DATA internal pull*/ + *GPIO_PULL_Enable_SDCardDetect |= GPIO_SD0_CD; + *GPIO_PULL_Enable_SD |= (GPIO_SD0_Data | GPIO_SD0_WriteProtect); + *GPIO_PULL_Enable_SD018SEL |= GPIO_SD0_18SEL; + + } else if (SDDevInfo->CtrlID == 1) { + /*Disable Clock & CMD Pull enable*/ + *GPIO_PULL_Enable_SD1 &= ~(GPIO_SD1_Clock | GPIO_SD1_Command); + + /*Set CD ,WP ,DATA pin pull up*/ + /* SD1 no card detect feature Bow */ + /**GPIO_PULL_Control_SD1 |= GPIO_SD1_CD;*/ + *GPIO_PULL_Control_SD1 |= GPIO_SD1_WriteProtect; + *GPIO_PULL_Control_SD1Data |= GPIO_SD1_Data; + + /*Enable CD ,WP ,DATA internal pull*/ + /* SD1 no card detect feature Bow */ + /**GPIO_PULL_Enable_SD1 |= GPIO_SD1_CD;*/ + *GPIO_PULL_Enable_SD1 |= GPIO_SD1_WriteProtect; + *GPIO_PULL_Enable_SD1Data |= GPIO_SD1_Data; + + } else if (SDDevInfo->CtrlID == 2) { + /*Disable Clock & CMD Pull enable*/ + *GPIO_PULL_Enable_SD2 &= ~(GPIO_SD2_Clock | GPIO_SD2_Command); + + /*Set CD ,WP ,DATA pin pull up*/ + *GPIO_PULL_Control_SD2CardDetect |= GPIO_SD2_CD; + *GPIO_PULL_Control_SD2 |= (GPIO_SD2_Data | GPIO_SD2_WriteProtect); + + /*Enable CD ,WP ,DATA internal pull*/ + *GPIO_PULL_Enable_SD2CardDetect |= GPIO_SD2_CD; + *GPIO_PULL_Enable_SD2 |= (GPIO_SD2_Data | GPIO_SD2_WriteProtect); + + } + + udelay(10000); + /*enable SD power*/ + if (SDDevInfo->CtrlID == 0) { + /*Enable SD0 power*/ + *GPIO_OUTPUT_DATA_SD &= ~GPIO_SD0_POWER; + } else if (SDDevInfo->CtrlID == 1) { + /*Ensable SD1 power*/ + *GPIO_OUTPUT_DATA_SD1 &= ~GPIO_SD1_POWER; + } else if (SDDevInfo->CtrlID == 2) { + /*Ensable SD2 power*/ + *GPIO_OUTPUT_DATA_SD2 &= ~GPIO_SD2_POWER; + } + + /* issue softReset to SD controller */ + pSd_Reg->busm = SOFT_RESET; + + /* automatic clock freezing enable */ + pSd_Reg->str2 = DIS_FORCECLK; + + pSd_Reg->timeval = 0xefff; + SD_Init_PDMA(); + + /* clear card_insert in STS0[7] */ + pSd_Reg->str0 = DEVICE_INS; + + /* SD clock = 400Khz */ + sd_set_clock(SD_Clk_400KHz); + + /* enable SD output clock */ + pSd_Reg->busm |= 0x10; + udelay(10000); + + + /* Config SD back to function */ + if (SDDevInfo->CtrlID == 0) { + *GPIO_Enable_SD &= ~(GPIO_SD0_Clock | GPIO_SD0_Command | GPIO_SD0_WriteProtect | GPIO_SD0_Data); + *GPIO_Enable_SDCardDetect &= ~GPIO_SD0_CD; + *GPIO_Enable_SD018SEL &= ~GPIO_SD0_18SEL; + } else if (SDDevInfo->CtrlID == 1) { + *GPIO_Enable_SD1 &= ~(GPIO_SD1_Clock | GPIO_SD1_Command | GPIO_SD1_WriteProtect | GPIO_SD1_RSTN); + /* SD1 no card detect feature Bow */ + /**GPIO_Enable_SD1CardDetect &= ~GPIO_SD1_CD;*/ + *GPIO_Enable_SD1Data &= ~GPIO_SD1_Data; + } else if (SDDevInfo->CtrlID == 2) { + *GPIO_Enable_SD2 &= ~(GPIO_SD2_Clock | GPIO_SD2_Command | GPIO_SD2_WriteProtect | GPIO_SD2_Data); + *GPIO_Enable_SD2CardDetect &= ~GPIO_SD2_CD; + } + + /* issue softReset to SD controller */ + //pSd_Reg->busm= SOFT_RESET; + card_nop(); +} + + +int SD_card_inserted(void) +{ + int ret; + SD_Controller_Powerup(); + + sd_command(GO_IDLE_STATE, 0, 0x0, R0); /*reset SD Card*/ + ret = sd_command(APP_CMD, 0, 0x0, R1); + if (!ret) + ret = sd_command(SD_APP_OP_COND, 0, 0x0, R3); /*send ACMD41 to get card's require voltage range*/ + if (!ret) + return 1; /*inserted*/ + else + return 0; /*not inserted*/ +} + + +int mmc_wfs_read(unsigned long dev, unsigned long addr, char *filename, unsigned long bytes) { + + + disk_partition_t pt; + char buffer[512]; + root_dir *RootDir = buffer; + unsigned long blkcnt = 0; + unsigned long blk_addr = 0; + unsigned long status = 0; + + Change_SD_host(dev); + + if (!mmc_ready) { + printf("Please initial the SD/MMC first\n"); + return -1; + } +#if 0 + printf("mmc_wfs_read\n"); + printf("<dev> : 0x%x\n",dev); + printf("<addr> : 0x%x\n",addr); + printf("<filename> : %s\n",filename); + printf("<bytes> : 0x%x\n",bytes); +#endif + get_partition_info(mmc_dev, 1, &pt); +#if 0 + printf("\nPartition info\n"); + printf("offset = 0x%x\n", pt.offset); + printf("start = 0x%x\n", pt.start); + printf("size = 0x%x 0x%xMB\n", pt.size, pt.size/2048); + printf("blksz = 0x%x\n", pt.blksz); + printf("name = %s\n", &pt.name); + printf("type = %s\n", &pt.type); +#endif + /*Read Root Dir*/ + mmc_bread(dev, pt.start, 1, RootDir); + + if (strcmp(RootDir->MagicHeader, "WMTBLS!") != 0) { + printf("The MagicHeader is not correct '%s'\n",RootDir->MagicHeader); + return -1; + } +#if 0 + printf("RootDir->MagicHeader = %s\n",RootDir->MagicHeader); + printf("RootDir->filename1 = %s\n",RootDir->filename1); + printf("RootDir->filesize1 = 0x%x\n",RootDir->filesize1); + printf("RootDir->filename2 = %s\n",RootDir->filename2); + printf("RootDir->filesize2 = 0x%x\n",RootDir->filesize2); + printf("RootDir->filename3 = %s\n",RootDir->filename3); + printf("RootDir->filesize3 = 0x%x\n",RootDir->filesize3); +#endif + if (strcmp(filename, "wx-load.bin") == 0) { + if (bytes > 0) { + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + } else { + blkcnt = RootDir->filesize1/MMC_BLOCK_SIZE; + + if (RootDir->filesize1 % MMC_BLOCK_SIZE) + blkcnt++; + } + + blk_addr = pt.start + (0x10000 / MMC_BLOCK_SIZE); + + status = mmc_bread(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + } else if (strcmp(filename, "wmt-env.bin") == 0){ + if (bytes > 0) { + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + } else { + blkcnt = RootDir->filesize2/MMC_BLOCK_SIZE; + + if (RootDir->filesize2 % MMC_BLOCK_SIZE) + blkcnt++; + } + + blk_addr = pt.start + (0x20000 / MMC_BLOCK_SIZE); + + status = mmc_bread(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + } else if (strcmp(filename, "u-boot.bin") == 0) { + if (bytes > 0) { + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + } else { + blkcnt = RootDir->filesize3/MMC_BLOCK_SIZE; + + if (RootDir->filesize3 % MMC_BLOCK_SIZE) + blkcnt++; + } + + blk_addr = pt.start + (0x30000 / MMC_BLOCK_SIZE); + + status = mmc_bread(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + } else + return -1; + + + return 0; + +} + +int mmc_wfs_write(unsigned long dev, unsigned long addr, char *filename, unsigned long bytes) { + + disk_partition_t pt; + char buffer[512]; + root_dir *RootDir = buffer; + unsigned long blkcnt = 0; + unsigned long blk_addr = 0; + unsigned long status = 0; + int i = 0; + + + Change_SD_host(dev); + + if (!mmc_ready) { + printf("Please initial the SD/MMC first\n"); + return -1; + } + +#if 0 + printf("mmc_wfs_read\n"); + printf("<dev> : 0x%x\n",dev); + printf("<addr> : 0x%x\n",addr); + printf("<filename> : %s\n",filename); + printf("<bytes> : 0x%x\n",bytes); +#endif + get_partition_info(mmc_dev, 1, &pt); +#if 0 + printf("\nPartition info\n"); + printf("offset = 0x%x\n", pt.offset); + printf("start = 0x%x\n", pt.start); + printf("size = 0x%x 0x%xMB\n", pt.size, pt.size/2048); + printf("blksz = 0x%x\n", pt.blksz); + printf("name = %s\n", &pt.name); + printf("type = %s\n", &pt.type); +#endif + + /*Read Root Dir*/ + mmc_bread(dev, pt.start, 1, (unsigned long *)RootDir); + + strcpy(RootDir->MagicHeader, "WMTBLS!"); + + + if (strcmp(filename, "wx-load.bin") == 0) { + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + + RootDir->filesize1 = bytes; + + strcpy(RootDir->filename1, "wx-load.bin"); + + blk_addr = pt.start + (0x10000 / MMC_BLOCK_SIZE); + + status = mmc_bwrite(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + + /*Write RootDir*/ + status = mmc_bwrite(dev, pt.start, 1, RootDir); + if (status == -1) + return -1; + + + } else if (strcmp(filename, "wmt-env.bin") == 0){ + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + + RootDir->filesize2 = bytes; + + strcpy(RootDir->filename2, "wmt-env.bin"); + + blk_addr = pt.start + (0x20000 / MMC_BLOCK_SIZE); + + status = mmc_bwrite(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + + /*Write RootDir*/ + status = mmc_bwrite(dev, pt.start, 1, RootDir); + if (status == -1) + return -1; + } else if (strcmp(filename, "u-boot.bin") == 0) { + blkcnt = bytes/MMC_BLOCK_SIZE; + + if (bytes % MMC_BLOCK_SIZE) + blkcnt++; + + RootDir->filesize3 = bytes; + + strcpy(RootDir->filename3, "u-boot.bin"); + + blk_addr = pt.start + (0x30000 / MMC_BLOCK_SIZE); + + status = mmc_bwrite(dev, blk_addr, blkcnt, addr); + + if (status == -1) + return -1; + + /*Write RootDir*/ + status = mmc_bwrite(dev, pt.start, 1, RootDir); + if (status == -1) + return -1; + } else + return -1; + + + +#if 0 + printf("RootDir = 0x%x\n",RootDir); + printf("RootDir->MagicHeader = %s\n",RootDir->MagicHeader); + printf("RootDir->filename1 = %s\n",RootDir->filename1); + printf("RootDir->filesize1 = 0x%x\n",RootDir->filesize1); + printf("RootDir->filename2 = %s\n",RootDir->filename2); + printf("RootDir->filesize2 = 0x%x\n",RootDir->filesize2); + printf("RootDir->filename3 = %s\n",RootDir->filename3); + printf("RootDir->filesize3 = 0x%x\n",RootDir->filesize3); +#endif + + return 0; +} + +#endif /* CONFIG_MMC */ diff --git a/cpu/arm920t/wmt/pcinet.c b/cpu/arm920t/wmt/pcinet.c new file mode 100755 index 0000000..2bbe52f --- /dev/null +++ b/cpu/arm920t/wmt/pcinet.c @@ -0,0 +1,263 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__UPCI_H__) +#include "upci.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__PCINET_H__) +#include "pcinet.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ +int g_IO_point = PCI_base_addr; +int g_Mem_point = PCI_base_addr + PCI_io_range; + +BOOL NPCIbIsRegBitsOn(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits) +{ + BYTE byOrgData; + + PCIvReadConfigB(hHandle, wBusDevFunId, byRegOffset, &byOrgData); + return BITbIsAllBitsOn(byOrgData, byBits); +} + +BOOL NPCIbIsRegBitsOff(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits) +{ + BYTE byOrgData; + + PCIvReadConfigB(hHandle, wBusDevFunId, byRegOffset, &byOrgData); + return BITbIsAllBitsOff(byOrgData, byBits); +} + +void NPCIvRegBitsOn(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits) +{ + BYTE byOrgData; + + PCIvReadConfigB(hHandle, wBusDevFunId, byRegOffset, &byOrgData); + PCIvWriteConfigB(hHandle, wBusDevFunId, byRegOffset, (BYTE)(byOrgData | byBits)); +} + +void NPCIvRegBitsOff(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits) +{ + BYTE byOrgData; + + PCIvReadConfigB(hHandle, wBusDevFunId, byRegOffset, &byOrgData); + PCIvWriteConfigB(hHandle, wBusDevFunId, byRegOffset, (BYTE)(byOrgData & ~byBits)); +} + +void NPCIvReadManyConfigSpace(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, + PBYTE pbyBuffer, WORD wCount) +{ + PCIvReadConfigManyBytes(hHandle, wBusDevFunId, byRegOffset, pbyBuffer, wCount); +} + +void NPCIvReadRevisionId(HANDLE hHandle, WORD wBusDevFunId, PBYTE pbyRevId) +{ + PCIvReadConfigB(hHandle, wBusDevFunId, PCI_REG_REV_ID, pbyRevId); +} + +/* + * Description: Read PCI information by Vendor's id and Device's id + * + * Parameters: + * + * Return Value: + * + */ +BOOL NPCIbReadDeviceInfo(HANDLE hHandle, WORD wVendorID, WORD wDeviceID, PSPciDevice pPciDevs) +{ + BYTE byBusNum; + BYTE bySlotNum; + BYTE byFuncNum; + BYTE byRevId; + DWORD dwIoBase; + DWORD dwIoSpaceRange; + BYTE byIrqNo; + DWORD dwDevVenID = MAKEDWORD(wVendorID, wDeviceID); + + /* init device number to 0 */ + pPciDevs->wDeviceNum = 0; + byBusNum = 0; + bySlotNum = 0; + byFuncNum = 0; + /* get each Bus/Device/Function no. by vendor & device id */ + while (PCIbFindConfigDeviceInfo(dwDevVenID, &byBusNum, &bySlotNum, &byFuncNum, &byRevId, + &dwIoBase, &dwIoSpaceRange, &byIrqNo)) { + pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum] = + MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum); + (pPciDevs->wDeviceNum)++; + + /* increase bySlotNum or byFuncNum to do the next search */ + /* by checking PCI header type bit 7 */ + if (NPCIbIsRegBitsOn( + hHandle, + MAKE_BDF_TO_WORD(byBusNum, bySlotNum, 0), + PCI_REG_HDR_TYPE, + 0x80) + ) + byFuncNum++; + else + bySlotNum++; + } + + return TRUE; +} + +void NPCIvInitialize(HANDLE hHandle, WORD wBusDevFunId, BYTE byRevId) +{ + /* PATCH.... turn this on to avoid retry forever */ + NPCIvRegBitsOn(hHandle, wBusDevFunId, PCI_REG_MODE2, MODE2_PCEROPT); + /* PATCH.... */ + /* for some legacy BIOS and OS don't open BusM */ + /* bit in PCI configuration space. So, turn it on. */ + NPCIvRegBitsOn(hHandle, wBusDevFunId, PCI_REG_COMMAND, COMMAND_BUSM); + /* PATCH.... turn this on to detect MII coding error */ + /* NPCIvRegBitsOn(hHandle, wBusDevFunId, PCI_REG_MODE3, MODE3_MIION); */ +} + +/* add by kevin */ +/* search all pci devices matched vender & device ID */ +BOOL NPCIbPCIAlloc(HANDLE hHandle, WORD wVendorID, WORD wDeviceID, PSPciDevice pPciDevs) +{ + BYTE byBusNum; + BYTE bySlotNum; + BYTE byFuncNum; + BYTE byRevId; + DWORD dwIoBase; + DWORD dwIoSpaceRange; + BYTE byIrqNo; + DWORD dwDevVenID = MAKEDWORD(wVendorID, wDeviceID); + int i; + WORD command; + DWORD space_size; + + /* init device number to 0 */ + pPciDevs->wDeviceNum = 0; + byBusNum = 0; + bySlotNum = 0; + byFuncNum = 0; + /* get each Bus/Device/Function no. by vendor & device id */ + while (PCIbFindConfigDeviceInfo(dwDevVenID, &byBusNum, &bySlotNum, &byFuncNum, &byRevId, + &dwIoBase, &dwIoSpaceRange, &byIrqNo)) { + pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum] = + MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum); + /* disable IO/Mem accesss */ + PCIXvReadW(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_COMMAND, &command); + command = (~0x3)&command; + PCIXvWriteW(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_COMMAND, command); + + /* allocate IO or Memory space */ + for (i = 0; i < 6; i++) { + /* judge whether size equals to 0 */ + PCIXvWriteD( + pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], + PCI_REG_BAR0+i*4, + PCI_invalid + ); + PCIXvReadD(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], + PCI_REG_BAR0+i*4, + &space_size + ); + + if (space_size != 0) { + if (space_size & PCI_IO_ENABLE) { + /* assign IO space */ + /* assume io space doesn't exceed 256 bytes */ + PCIXvWriteD( + pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], + PCI_REG_BAR0+i*4, + g_IO_point + ); + g_IO_point += PCI_io_page; + } else { + /* assign memory space */ + /* assume mem space doesn't exceed 4k bytes */ + PCIXvWriteD( + pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], + PCI_REG_BAR0+i*4, + g_Mem_point + ); + g_Mem_point += PCI_memory_page; + } + } + } + /* 2.assign PCI slot interrupt */ + /* slot 8-a:44 */ + /* slot 9-a:45 */ + /* slot 10-a:46 */ + /* slot 11-a:47 */ + if (bySlotNum == 8) + PCIXvWriteB(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_INT_LINE, 44); + else if (bySlotNum == 9) + PCIXvWriteB(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_INT_LINE, 45); + else if (bySlotNum == 0xa) + PCIXvWriteB(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_INT_LINE, 46); + else if (bySlotNum == 0xb) + PCIXvWriteB(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_INT_LINE, 47); + else + PCIXvWriteB(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_INT_LINE, 44); + + /* enable IO/Mem accesss and PCI master */ + PCIXvReadW(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_COMMAND, &command); + command |= (0x7); + PCIXvWriteW(pPciDevs->awBusDevFunID[pPciDevs->wDeviceNum], PCI_REG_COMMAND, command); + + pPciDevs->wDeviceNum++; + /* increase bySlotNum or byFuncNum to do the next search */ + /* by checking PCI header type bit 7 */ + if (NPCIbIsRegBitsOn( + hHandle, + MAKE_BDF_TO_WORD(byBusNum, bySlotNum, 0), + PCI_REG_HDR_TYPE, + 0x80) + ) + byFuncNum++; + else + bySlotNum++; + } + /* printf("Richard DBG3\n"); */ + return TRUE; +} + +void pciconfigurationdump(WORD wBusDevFunId) +{ + unsigned long s_c; + + PCIXvReadD(wBusDevFunId, 0, &s_c); + printf("pci ID:%8x\n", s_c); + PCIXvReadD(wBusDevFunId, 4, &s_c); + printf("pci status and command:%8x\n", s_c); + PCIXvReadD(wBusDevFunId, 16, &s_c); + printf("pci io space:%8x\n", s_c); + PCIXvReadD(wBusDevFunId, 20, &s_c); + printf("pci mem spae:%8x\n", s_c); + return; +} diff --git a/cpu/arm920t/wmt/pcinet.h b/cpu/arm920t/wmt/pcinet.h new file mode 100755 index 0000000..fabeabe --- /dev/null +++ b/cpu/arm920t/wmt/pcinet.h @@ -0,0 +1,139 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __PCINET_H__ +#define __PCINET_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TPCI_H__) +#include "tpci.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +/* #define CB_MAX_NET_DEVICE 6 // max. # of the devices */ + +/* + * PCI total devices with the same Vendor id and Device id + */ +typedef struct tagSPciDevice { + WORD wDeviceNum; + WORD awBusDevFunID[MAX_NET_DEVICE]; +} SPciDevice, DEF * PSPciDevice; + + +/* + * Registers in the PCI configuration space + */ +#define PCI_REG_MODE0 0x60 +#define PCI_REG_MODE1 0x61 +#define PCI_REG_MODE2 0x62 +#define PCI_REG_MODE3 0x63 +#define PCI_REG_DELAY_TIMER 0x64 + + +/* + * Registers for power management (offset) + */ +#define PCI_REG_PM_BASE 0x50 + +#define PM_CAP_ID 0x00 +#define PM_NEXT_ITEM_PTR 0x01 +#define PM_PMC0 0x02 +#define PM_PMC1 0x03 +#define PM_PMCSR0 0x04 +#define PM_PMCSR1 0x05 +#define PM_CSR_BSE 0x06 +#define PM_DATA 0x07 + + +/* + * Bits in the COMMAND register + */ +#define COMMAND_BUSM 0x04 + +/* + * Bits in the MODE0 register + */ +#define MODE0_QPKTDS 0x80 +#define MODE0_GWTHSEL 0x04 +#define MODE0_FFWHSEL 0x02 +#define MODE0_DLWHSEL 0x01 + +/* + * Bits in the MODE2 register + */ +#define MODE2_PCEROPT 0x80 +#define MODE2_TXQ16 0x40 +#define MODE2_TCPLSOPT 0x01 + +/* + * Bits in the MODE3 register + */ +#define MODE3_MIION 0x04 + +/* + * Bits in PMCSR0 register + */ +#define PMCSR0_PW_STAT1 0x02 +#define PMCSR0_PW_STAT0 0x01 + +/* + * Bits in PMCSR1 register + */ +#define PMCSR1_PME_STATUS 0x80 +#define PMCSR1_PME_EN 0x01 + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ +extern int g_IO_point; +extern int g_Mem_point; +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL NPCIbIsRegBitsOn(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits); +BOOL NPCIbIsRegBitsOff(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits); + +void NPCIvRegBitsOn(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits); +void NPCIvRegBitsOff(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, BYTE byBits); + +void NPCIvReadManyConfigSpace(HANDLE hHandle, WORD wBusDevFunId, BYTE byRegOffset, + PBYTE pbyBuffer, WORD wCount); + +void NPCIvReadRevisionId(HANDLE hHandle, WORD wBusDevFunId, PBYTE pbyRevId); + +BOOL NPCIbReadDeviceInfo(HANDLE hHandle, WORD wVendorID, WORD wDeviceID, PSPciDevice pPciDevs); + +void NPCIvInitialize(HANDLE hHandle, WORD wBusDevFunId, BYTE byRevId); + +BOOL NPCIbPCIAlloc(HANDLE hHandle, WORD wVendorID, WORD wDeviceID, PSPciDevice pPciDevs); + +void pciconfigurationdump(WORD wBusDevFunId); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __PCINET_H__ */ diff --git a/cpu/arm920t/wmt/pmc.h b/cpu/arm920t/wmt/pmc.h new file mode 100755 index 0000000..238823d --- /dev/null +++ b/cpu/arm920t/wmt/pmc.h @@ -0,0 +1,370 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __PMC_H_ +#define __PMC_H_ + +typedef struct _PMC_REG_ { + volatile unsigned int PM_Sts; /* [Rx00-03] Power Management Status Register */ + volatile unsigned int PM_Sts1; /* [Rx04-07] Device clock update status 1 Register*/ + volatile unsigned char Idle; /* [Rx08] IDEL Processor Request Register */ + volatile unsigned char Resv9_0B[3]; /* [Rx09 - 0B] Reserved */ + volatile unsigned short PU_Time_Ctrl; /* [Rx0C] Power-up Tme Control Register */ + volatile unsigned char Resv0E_0F[2]; /* Reserved*/ + volatile unsigned short Hib_Val; /* [Rx10 - Rx11] Hibernation Value Register */ + volatile unsigned short Hib_Ctrl; /* [Rx12 - Rx13] Hibernation Control Register*/ + volatile unsigned int Wakeup_Sts; /* [Rx14-17]Wake up Status register*/ + volatile unsigned int PM_Sts2; /* [Rx18-1B] Power Management Status Register*/ + volatile unsigned int Wakeup_Event_Enable; /* [Rx1C-1F] Wake-up Event Enable Register*/ + volatile unsigned int Wakeup_Event_Type; /* [Rx20-23] Wake-up Event Type Register*/ + volatile unsigned int Wakeup_CardDet_Event_Type;/* [Rx24-27] Card Detect Wake-up Event Type Register*/ + volatile unsigned int CardDet_Sts_Int;/* [Rx28-2B] Card Detect Status And Card Detect Interrupt Register*/ + volatile unsigned int CardReader_Debounce_Int_Type;/* [Rx2C-2F] Card Reader Attachment Debounce Control and Interrupt Type Register*/ + volatile unsigned int Hib_Scratch0; /* [Rx30-33] Hibernate Scratch Pad Register0 */ + volatile unsigned int Hib_Scratch1; /* [Rx34-37] Hibernate Scratch Pad Register1 */ + volatile unsigned int Hib_Scratch2; /* [Rx38-3B] Hibernate Scratch Pad Register2 */ + volatile unsigned int Hib_Scratch3; /* [Rx3c-3F] Hibernate Scratch Pad Register3 */ + volatile unsigned int Hib_Scratch4; /* [Rx40-43] Hibernate Scratch Pad Register4*/ + volatile unsigned int Hib_Scratch5; /* [Rx44-47] Hibernate Scratch Pad Register5*/ + volatile unsigned int Hib_Scratch6; /* [Rx48-4B] Hibernate Scratch Pad Register6*/ + volatile unsigned int Hib_Scratch7; /* [Rx4c-4F] Hibernate Scratch Pad Register7*/ + volatile unsigned int Reset_Sts; /* [Rx50-53] Reset Status Register */ + volatile unsigned int PB_Control; /* [Rx54-57] Power Button Control Register; */ + volatile unsigned int AXI_LowPwr_Control; /* [Rx58-5B] AXI Low Power Interface Control Register;*/ + volatile unsigned int Resv5c_5F[1]; + volatile unsigned int SW_Reset_Req; /* [Rx60-63] Software Reset Request Register */ + volatile unsigned int Resv64_7F[0x7]; + volatile unsigned int PM_Div_Upt2_sts; /* [Rx80-83] Device clock update status 2 Register*/ + volatile unsigned int PM_Div_Upt3_sts; /* [Rx84-87] Device clock update status 3 Register*/ + volatile unsigned char Resv88_93[0xC]; + volatile unsigned int RTC_Clk_Exist_Monitor; /* [Rx94-97] RTC clock exist monitor Register*/ + volatile unsigned char Resv98_FF[0x68]; + volatile unsigned int OS_Timer_Match0; /* [Rx100-Rx103] OS Timer Match Register0 */ + volatile unsigned int OS_Timer_Match1; /* [Rx104-Rx107] OS Timer Match Registe1 */ + volatile unsigned int OS_Timer_Match2; /* [Rx108-Rx10B] OS Timer Match Register2 */ + volatile unsigned int OS_Timer_Match3; /* [Rx10C-Rx10F] OS Timer Match Register3 */ + volatile unsigned int OS_Timer_Count; /* [Rx110-113] OS Timer Counter Register */ + volatile unsigned int OS_Timer_Sts; /* [Rx114-117] OS Timer Status Register */ + volatile unsigned int OS_Timer_WatchDog_Enable; /* [Rx118-Rx11B] */ + volatile unsigned int OS_Timer_Int_Enable; /* [Rx11C-Rx11F] */ + volatile unsigned int OS_Timer_Ctrl; /* [Rx120-Rx123] OS Timer Control Register */ + volatile unsigned int OS_Timer_Access_Sts; /* [Rx124-Rx127] OS Timer Access Status Register */ + volatile unsigned int Resv128_1FB[0x35]; + volatile unsigned char Resv1FC_1FF[4]; + volatile unsigned int PLLA; /* [Rx200-203] PLLA Multiplier and */ + /* Range Values Register */ + volatile unsigned int PLLB; /* [Rx204-207] PLLB Multiplier and */ + /* Range Values Register */ + volatile unsigned int PLLC; /* [Rx208-20B] PLLC Multiplier and */ + /* Range Values Register */ + volatile unsigned int PLLD; /* [Rx20C-20F] PLLD Multiplier and */ + /* Range Values Register */ + volatile unsigned int PLLE; /* [Rx210-213] PLLE Multiplier and Range Values Register*/ + volatile unsigned int PLLF; /* [Rx214-217] PLLF Multiplier and Range Values Register*/ + volatile unsigned int PLL_25; /* [Rx218-21B] PLL_25 Multiplier and Range Values Register*/ + volatile unsigned int PLL_AUD; /* [Rx21C-21F] PLL_AUD Multiplier and Range Values Register*/ + volatile unsigned int PLL_Rdy_Sts; /* [Rx220-223] PLL Ready Status Register*/ + volatile unsigned int Resv224_24F[0x0B]; + volatile unsigned int Clock_Enable0; /* [Rx250-253] Clock Enable 0 Register*/ + volatile unsigned int Clock_Enable1; /* [Rx254-257] Clock Enable 1 Register*/ + volatile unsigned int Clock_Enable2; /* [Rx258-25B] Clock Enable 2 Register*/ + volatile unsigned int Clock_Enable3; /* [Rx25C-25F] Clock Enable 3 Register*/ + volatile unsigned int Resv260_2FF[0x28]; + volatile unsigned char ARM_Clock_Divisor; /* [Rx300] ARM Clock Divisor Register*/ + volatile unsigned char ARM_Clock_HiPulse; + volatile unsigned char Resv302_303[2]; + volatile unsigned char AHB_Clock_Divisor; /* [Rx304] AHB Clock Divisor Value Register */ + volatile unsigned char Resv305_30B[7]; + volatile unsigned char L2C_Clock_Divisor; /* [Rx30C] Clock Divisor Value L2C Register*/ + volatile unsigned char L2C_Clock_HiPulse; + volatile unsigned char Resv30E_30F[2]; + volatile unsigned char DDR_Clock_Divisor; /* [Rx310] DDR Memory Controller Clock */ + volatile unsigned char Resv311_313[3]; + volatile unsigned char SF_Clock_Divisor; /* [Rx314] Serial Flash Memory Controller */ + volatile unsigned char SF_Clock_HiPulse; /* [Rx315] */ + volatile unsigned char Resv316_317[2]; + volatile unsigned char NF_Clock_Divisor; /* [Rx318] NF Clock Divisor Value Register*/ + volatile unsigned char NF_Clock_HiPulse; /* [Rx319]*/ + volatile unsigned char Resv31A_31B[2]; + volatile unsigned char NOR_Clock_Divisor; /* [Rx31C] NOR Clock Divisor Value Register*/ + volatile unsigned char NOR_Clock_HiPulse; /* [Rx31D]*/ + volatile unsigned char Resv31E_31F[2]; + volatile unsigned char APB_Clock_Divisor; /* [Rx320] APB Clock Divisor Value Register*/ + volatile unsigned char Resv321_32F[15]; + volatile unsigned char SD_Clock_Divisor; /* [Rx330] SD/MMC Clock Divisor Value Reigster*/ + volatile unsigned char SD_Clock_HiPulse; /* [Rx331]*/ + volatile unsigned char Resv332_333[2]; + volatile unsigned char SD1_Clock_Divisor; /* [Rx334] SD/MMC1 Clock Divisor Value Reigster*/ + volatile unsigned char SD1_Clock_HiPulse; /* [Rx335]*/ + volatile unsigned char Resv336_337[2]; + volatile unsigned char SD2_Clock_Divisor; /* [Rx338] SD/MMC2 Clock Divisor Value Reigster*/ + volatile unsigned char SD2_Clock_HiPulse; /* [Rx339]*/ + volatile unsigned char Resv33A_33B[2]; + volatile unsigned char Resv33C_33F[4]; + volatile unsigned char SPI0_Clock_Divisor; /* [Rx340] SPI0 Clock Divisor Value Register*/ + volatile unsigned char SPI0_Clock_HiPulse; /* [Rx341] SPI0 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv342_343[2]; + volatile unsigned char SPI1_Clock_Divisor; /* [Rx344] SPI1 Clock Divisor Value Register*/ + volatile unsigned char SPI1_Clock_HiPulse; /* [Rx345] SPI1 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv346_34F[10]; + volatile unsigned char PWM_Clock_Divisor; /* [Rx350] PWM Clock Divisor Register*/ + volatile unsigned char PWM_Clock_HiPulse; /* [Rx351] PWM Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv352_353[2]; + volatile unsigned char PCM_Clock_Divisor; /* [Rx354] PCM Clock Divisor Value Register*/ + volatile unsigned char PCM_Clock_HiPulse; /* [Rx355] PCM Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv356_357[2]; + volatile unsigned char NA0_Clock_Divisor; /* [Rx358]*/ + volatile unsigned char NA0_Clock_HiPulse; /* [Rx359] NA0 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv35A_35B[2]; + volatile unsigned char NA12_Clock_Divisor; /* [Rx35C]*/ + volatile unsigned char NA12_Clock_HiPulse; /* [Rx35D] NA12 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv35E_367[10]; + volatile unsigned char VDU_Clock_Divisor; /* [Rx368]*/ + volatile unsigned char VDU_Clock_HiPulse; /* [Rx369] VDU Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv36A_36B[2]; + volatile unsigned char DVOTV2_Clock_Divisor;/* [Rx36C]*/ + volatile unsigned char DVOTV2_Clock_HiPulse;/* [Rx36D] DVOTV2 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv36E_373[6]; + volatile unsigned char AUD_Clock_Divisor; /* [Rx374] AUD Clock Divisor Value Register*/ + volatile unsigned char AUD_Clock_HiPulse; /* [Rx375] AUD Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv376_377[2]; + volatile unsigned char Ring1_Clock_Divisor; /* [Rx378] Ring OSC 1st divider Register*/ + volatile unsigned char Resv379_37B[3]; + volatile unsigned char Ring2_Clock_Divisor; /* [Rx37C] Ring OSC 2st divider Register*/ + volatile unsigned char Resv37D_387[11]; + volatile unsigned char MALI_Clock_Divisor; /* [Rx388]*/ + volatile unsigned char MALI_Clock_HiPulse; /* [Rx389] MALI Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv38A_38F[6]; + volatile unsigned char HDMI_I2C_Clock_Divisor;/* [Rx390]*/ + volatile unsigned char HDMI_I2C_Clock_HiPulse;/* [Rx391] HDMI Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv392_393[2]; + volatile unsigned char GENET_Clock_Divisor; /* [Rx394] GENET Clock Divisor Value Register*/ + volatile unsigned char GENET_Clock_HiPulse; /* [Rx395]*/ + volatile unsigned char Resv396_39F[10]; + volatile unsigned char I2C0_Clock_Divisor; /* [Rx3A0]*/ + volatile unsigned char I2C0_Clock_HiPulse; /* [Rx3A1] I2C0 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3A2_3A3[2]; + volatile unsigned char I2C1_Clock_Divisor; /* [Rx3A4]*/ + volatile unsigned char I2C1_Clock_HiPulse; /* [Rx3A5] I2C1 Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3A6_3AF[10]; + volatile unsigned char L2C_AXI_Clock_Divisor; /* [Rx3B0]*/ + volatile unsigned char L2C_AXI_Clock_HiPulse; /* [Rx3B1] L2C_AXI Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3B2_3BF[14]; + volatile unsigned char L2C_PAXI_Clock_Divisor;/* [Rx3C0]*/ + volatile unsigned char L2C_PAXI_Clock_HiPulse;/* [Rx3C1] L2C_PAXI Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3C2_3E3[18]; + volatile unsigned char Hz24M_Clock_Divisor; /* [Rx3C0]*/ + volatile unsigned char Hz24M_Clock_HiPulse; /* [Rx3C1] 24MHZ Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3E6_3EF[10]; + volatile unsigned char L2C_RAM_Clock_Divisor; /* [Rx3F0]*/ + volatile unsigned char L2C_RAM_Clock_HiPulse; /* [Rx3F1] L2C_RAM Clock High Pulse is the Wide Pulse Register*/ + volatile unsigned char Resv3F2_4FF[0x10E]; + volatile unsigned char PS_Control; /* [Rx500] 1.1.1.85 CARD, SD, CF Power Switch Control Register*/ + volatile unsigned char Resv501[0xFF]; + volatile unsigned int MALI_PWR_Shut_Off_CTRL_STS; /* [Rx600-603] mali power shut off control and status Register*/ + volatile unsigned int C_M_PWR_Shut_Off_CTRL_STS; /* [Rx604-607] C&M power shut off control and status Register*/ + volatile unsigned char Resv608_64F[0x48]; + volatile unsigned int AXI_TO_AHB_Bridge_Pwr_Ctrl; /* [Rx650-653] AXI to AHB bridge power control and status Register*/ + volatile unsigned int PAXI_TO_AHB_Bridge_Pwr_Ctrl;/* [Rx654-657] AXI to AHB bridge power control and status Register*/ +} PMC_REG, *PPMC_REG; + +/* + * (URRDR) Receive Data Regiser Description + */ +#define URRDR_PER 0x100 /* Parity Error. This bit is the same as URISR[8] */ +#define URRDR_FER 0x200 /* Frame Error. This bit is the same as URISR[9] */ + +/* + * PMCS_REG PM (Current) Status Register bits definitions. + */ +#define PMCS_NORTC BIT0 /* RTC Clock Logic Disabled */ +#define PMCS_IDLE BIT1 /* IDLE Operation Active */ +#define PMCS_HIBER BIT2 /* Hibernation Operation Active */ +#define PMCS_ANY_CLK_DIV BIT4 /* Updating Any Clock Divisor */ +#define PMCS_ANY_PLL_MUL BIT5 /* Updating Any PLL Multiplier */ +#define PMCS_ZAC2 BIT8 /* Updating ZAC2_MA Clock Divisor */ +#define PMCS_AHB BIT9 /* Updating AHB Clock Divisor */ +#define PMCS_DSP BIT10 /* Updating DSP Clock Divisor */ +#define PMCS_LCD BIT11 /* Updating LCD Clock Divisor */ +#define PMCS_MC BIT12 /* Updating Memory Controller Clock Divisor */ +#define PMCS_CFC BIT13 /* Updating Compact Flash Controller Clock Divisor */ +#define PMCS_USB BIT14 /* Updating USB Clock Divisor */ +#define PMCS_PCM BIT15 /* Updating Pulse Code Modulation Clock Divisor */ +#define PMCS_PLLA BIT16 /* Updating PLL A Multiplier Value */ +#define PMCS_PLLB BIT17 /* Updating PLL B Multiplier Value */ +#define PMCS_PLLC BIT18 /* Updating PLL C Multiplier Value */ +#define PMCS_SF BIT19 /* Updating Serial Flash Memory Cntrlr Divisor */ +#define PMCS_PATA BIT21 /* Updating PATA Clock Divisor */ +#define PMCS_SDMMC BIT22 /* Updating SD/MMC Clock Divisor */ +#define PMCS_MSC BIT23 /* Updating MS/MSPRO Clock Divisor */ +#define PMCS_LPC BIT24 /* Updating LPC Memory Cntrlr Clock Divisor */ +#define PMCS_NAND BIT25 /* Updating NAND Clock Divisor */ +#define PMCS_SPI BIT26 /* Updating SPI Clock Divisor */ +#define PMCS_PLLD BIT27 /* Updating PLL D Multiplier Value */ +#define PMCS_BUSY 0xfffffffe + +/* + * PMIR_REG PM Idle processor Request Register bit function. + */ +#define PMIR_IDLE /* IDLE Processor Request Bit */ + + +/* + * PMHC_REG PM Hibernation Control Register bits functions. + */ +#define PMHC_SLEEP 0x03 /* A Power-on Hibernation Mode */ +#define PMHC_SUSPEND 0x01 /* A Power-off Hibernation Mode */ +#define PMHC_SHUTDOWN 0x05 /* A Power-off Hibernation Mode */ +#define PMHC_25M_OSCLR BIT8 /* 25MHz Oscillator Enable */ + +/* + * PMWS_REG PM Wake-up Status register bits definitions. + */ +#define PMWS_WAKEMASK 0xFF /* General Purpose Wake-up Status */ +#define PMWS_PWRBUTTON BIT14 /* Power Button Wake-up Status */ +#define PMWS_RTC BIT15 /* RTC Wake-up Status */ + +/* + * PMWE_REG PM Wake-up event Enable Register bits functions. + */ +#define PMWE_WAKEMASK 0xFF /* General Purpose Wake-up Enable */ +#define PMWE_WAKEUP(x) (BIT0 << ((x) & 0x7)) /* Genaral Wake-up 0-7 Enable */ +#define PMWE_RTC BIT15 /* RTC Wake-up Enable */ + +/* + * PMWT_REG PM Wake-up event Type Register bits functions. + */ +#define PMWT_ZERO 0x00 /* Wake-up signal is a zero */ +#define PMWT_ONE 0x01 /* Wake-up signal is a one */ +#define PMWT_FALLING 0x02 /* Wake-up signal generates a falling edge */ +#define PMWT_RISING 0x03 /* Wake-up signal generates a rising edge */ +#define PMWT_EDGE 0x04 /* Wake-up signal generates an edge */ + +#define PMWT_TYPEMASK 0xFF /* Wake-up event Type Mask */ + +/* General Purpose Wake-up 0 Type bits */ +#define PMWT_WAKEUP0(x) (((x) & PMWT_TYPEMASK) << 0) +/* General Purpose Wake-up 1 Type bits */ +#define PMWT_WAKEUP1(x) (((x) & PMWT_TYPEMASK) << 4) +/* General Purpose Wake-up 2 Type bits */ +#define PMWT_WAKEUP2(x) (((x) & PMWT_TYPEMASK) << 8) +/* General Purpose Wake-up 3 Type bits */ +#define PMWT_WAKEUP3(x) (((x) & PMWT_TYPEMASK) << 12) +/* General Purpose Wake-up 4 Type bits */ +#define PMWT_WAKEUP4(x) (((x) & PMWT_TYPEMASK) << 16) +/* General Purpose Wake-up 5 Type bits */ +#define PMWT_WAKEUP5(x) (((x) & PMWT_TYPEMASK) << 20) +/* General Purpose Wake-up 6 Type bits */ +#define PMWT_WAKEUP6(x) (((x) & PMWT_TYPEMASK) << 24) +/* General Purpose Wake-up 7 Type bits */ +#define PMWT_WAKEUP7(x) (((x) & PMWT_TYPEMASK) << 28) +/* Max wakeup source number */ +#define PMWT_WAKEUPMASK 0x07 + +#define PMWT_WAKEUP(src, type) ((type & PMWT_TYPEMASK) << ((src & PMWT_WAKEUPMASK) * 4)) + +/* + * PMRS_REG PM Reset Status Register bits definitions. + */ +#define PMRS_PMR BIT0 /* Power Managment Reset */ +#define PMRS_IOR BIT1 /* I/O normal power Reset */ +#define PMRS_HBR BIT2 /* HiBernation Reset */ +#define PMRS_WDR BIT3 /* WatchDog Reset */ +#define PMRS_SWR BIT4 /* SoftWare Reset */ +#define PMRS_SHR BIT5 /* Shutdown Reset */ +#define PMRS_PGR BIT6 /* Power good reset */ +/* Bits 7-31: Reserved */ + +/* + * PMPB_REG PM Power Button Control Register + */ +#define PMPB_SOFTPWR BIT0 /* Soft Power Enable */ +/* Bits 1-31: Reserved */ + +/* + * PMSR_REG PM Software Reset request Register bit function. + */ +#define PMSR_SWR BIT0 /* SoftWare Reset request */ +/* Bits 1-31: Reserved */ + +/* + * PMPATA_REG PM PATA Interface Drive Strength Register (8-bit Register) + */ +#define PMPATA_ONETHIRD 0x00 /* One-third Drive Strength */ +#define PMPATA_ONEHALF 0x01 /* One-half Drive Strength */ +#define PMPATA_TWOTHIRD 0x02 /* Two-third Drive Strength */ +#define PMPATA_FULL 0x03 /* Full Drive Strength */ +#define PMSR_SWR BIT0 /* SoftWare Reset request */ +/* Bits 2-7: Reserved */ + +/* + * OSTS_REG OS Timer Status Register bits definitions. + */ +#define OSTS_M0 BIT0 /* OS Timer 0 Match detected */ +#define OSTS_M1 BIT1 /* OS Timer 1 Match detected */ +#define OSTS_M2 BIT2 /* OS Timer 2 Match detected */ +#define OSTS_M3 BIT3 /* OS Timer 3 Match detected */ +/* Bits 4-31: Reserved */ + +/* + * OSTW_REG OS Timer Watchdog enable Register bit function. + */ +#define OSTW_WE BIT0 /* OS Timer Channel 0 Watchdog Enable */ +/* Bits 1-31: Reserved */ + +/* + * OSTI_REG OS Timer Interrupt enable Register bits functions. + */ +#define OSTI_E0 BIT0 /* OS Timer Channel 0 Interrupt Enable */ +#define OSTI_E1 BIT1 /* OS Timer Channel 0 Interrupt Enable */ +#define OSTI_E2 BIT2 /* OS Timer Channel 0 Interrupt Enable */ +#define OSTI_E3 BIT3 /* OS Timer Channel 0 Interrupt Enable */ + +/* Bits 4-31: Reserved */ +/* + * OSTC_REG OS Timer Control Register bits functions. + */ +#define OSTC_ENABLE BIT0 /* OS Timer Enable bit */ +#define OSTC_RDREQ BIT1 /* OS Timer Read Count Request bit */ +/* Bits 2-31: Reserved */ + +/* + * OSTA_REG OS Timer Access status Register bits definitions. + */ +#define OSTA_MWA0 BIT0 /* OS Timer Match 0 Write Active */ +#define OSTA_MWA1 BIT1 /* OS Timer Match 1 Write Active */ +#define OSTA_MWA2 BIT2 /* OS Timer Match 2 Write Active */ +#define OSTA_MWA3 BIT3 /* OS Timer Match 3 Write Active */ +#define OSTA_CWA BIT4 /* OS Timer Count Write Active */ +#define OSTA_RCA BIT5 /* OS Timer Read Count Active */ +/* Bits 6-31: Reserved */ + +/* + * PMMISC_REG PM Miscellaneous Clock Controls Register + */ +#define PMMISC_24MHZ BIT0 /* 24MHz Clock Source */ +/* Bits 1-31: Reserved */ + +/* + * Miscellaneous definitions + */ +#define __OST_BASE 0xD8130100 /* OS Timers base address */ +#define OST_MAX_CHANNEL 4 /* Four channels OS Timer */ +/* #define PMC_MAX_WAKEUP 9 // Wakeup source number */ +/* // 8 general purpose + 1 RTC */ + +#endif /* __PMC_H_ */ diff --git a/cpu/arm920t/wmt/proto.h b/cpu/arm920t/wmt/proto.h new file mode 100755 index 0000000..d0b9ef7 --- /dev/null +++ b/cpu/arm920t/wmt/proto.h @@ -0,0 +1,92 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __PROTO_H__ +#define __PROTO_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif + +#define HW_8021PQ_TAG TCR0_VETAG +#define HW_IP_CHECKSUM TCR0_IPCK +#define HW_UDP_CHECKSUM TCR0_UDPCK +#define HW_TCP_CHECKSUM TCR0_TCPCK + +/*--------------------- Export Definitions -------------------------*/ +/* + * Protocol buffer ring + */ +typedef struct tagSProtocolBuffer { + + UINT uProtoIndex; /* protocol index */ + + int idxRxBufHead; + int idxRxBufTail; + PBYTE apbyRxBuffer[CB_MAX_RD_NUM]; + UINT auRxBufLength[CB_MAX_RD_NUM]; + BOOL abRxBufOccupied[CB_MAX_RD_NUM]; + + /* for pingpong test */ + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + DWORD dwSerialNo; + BYTE byDataSeed; + +} SProtocolBuffer, DEF * PSProtocolBuffer; + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ +extern SProtocolBuffer sg_aGProBuf[MAX_NET_DEVICE]; + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +BOOL GPRObDriverSend(PSAdapterInfo pAdapter, PBYTE pbyPacket, UINT uPktLen, BYTE byTxQue); +BOOL GPRObDriverSendEx(PSAdapterInfo pAdapter, BYTE byTxQue, WORD wVID, + BYTE byPri, BYTE byHwOpt, PBYTE pbyPacket, UINT uPktLen); +BOOL GPRObProtocolReceive(PSAdapterInfo pAdapter, PBYTE *ppbyPacket, PUINT puPktLen); +VOID GPROvProtocolReturnPacket(PSAdapterInfo pAdapter); + +BOOL GPRObProtocolConstruct(PSAdapterInfo pAdapter); +VOID GPROvProtocolDestruct(PSAdapterInfo pAdapter); + +VOID GPROvPrepareTxPacketEx(PSAdapterInfo pAdapter, BYTE byTxQue, UINT uIdx, UINT uNumSeg); + +VOID GPROvDoTransmitSinglePacket(PSAdapterInfo pAdapter, BYTE byTxQue); + +VOID GPROvDoTransmitEx(PSAdapterInfo pAdapter, BYTE byTxQue); + +/* VOID vSetBit(PDWORD pdwTD0); */ + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __PROTO_H__ */ + + + diff --git a/cpu/arm920t/wmt/read me.txt b/cpu/arm920t/wmt/read me.txt new file mode 100755 index 0000000..ec68441 --- /dev/null +++ b/cpu/arm920t/wmt/read me.txt @@ -0,0 +1,29 @@ +Date :2007/01/25 +Function :U-boot ethernet driver +1.eth_init() :ok!have fixed the bug of reallocation of memory +2.eth_tx() :ok! +3.eth_rx() :ok! +3.mac_halt() :ok!equal adapteshutdown() +4.Mii_read() :not finished yet! +5.Mii_write():not finished yet! +6.Original file in mac are moved to wmt and makefile is modifed +7.output message is omitted +------------------------------------------------------------------------------------------- +Date :2007/01/25 +Function :U-boot ethernet driver +1.eth_init() :ok!have fixed the bug of reallocation of memory +2.eth_tx() :ok! +3.eth_rx() :ok! +3.mac_halt() :ok!equal adapteshutdown() +4.Mii_read() :not finished yet! +5.Mii_write():not finished yet! +-------------------------------------------------------------------------------------------- +Date :2007/01/24 +Function :U-boot ethernet driver +1.eth_init() :ok!but it will reallocate memory and cause procedure not to go further +2.eth_tx() :ok! +3.eth_rx() :ok! +3.mac_halt() :ok!do nothing!because halt will be processed before eth_init() +4.Mii_read() :not finished yet! +5.Mii_write():not finished yet! +
\ No newline at end of file diff --git a/cpu/arm920t/wmt/sdc.h b/cpu/arm920t/wmt/sdc.h new file mode 100755 index 0000000..b42dee5 --- /dev/null +++ b/cpu/arm920t/wmt/sdc.h @@ -0,0 +1,508 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/
+
+#ifndef __SDC_H__
+#define __SDC_H__
+
+#define SD_FALSE 0
+#define SD_TRUE 1
+
+//SD command definition
+
+#define GO_IDLE_STATE 0
+#define SEND_OP_COND 1 //for MMC
+#define ALL_SEND_CID 2
+#define SEND_RELATIVE_ADDR 3
+#define SET_RELATIVE_ADDR 3 //for MMC1
+#define SET_DSR 4
+#define SELECT_DESELECT_CARD 7
+#define SEND_IF_COND 8 //for SD2.0 2006/01/20 janshiue
+#define SEND_EXT_CSD 8 //for MMC
+#define SEND_CSD 9
+#define SEND_CID 10
+//#define READ_DAT_UNTIL_STOP 11
+#define STOP_TRANSMISSION 12
+#define SEND_STATUS 13
+//#define SET_BUS_WIDTH_REGISTER 14
+#define GO_INACTIVE_STATE 15
+#define SET_BLOCKLEN 16
+#define READ_SINGLE_BLOCK 17
+#define READ_MULTIPLE_BLOCK 18
+//#define WRITE_DAT_UNTIL_STOP 20
+#define WRITE_SINGLE_BLOCK 24
+#define WRITE_MULTIPLE_BLOCK 25
+//#define PROGRAM_CID 26
+#define PROGRAM_CSD 27
+#define SET_WRITE_PROT 28
+#define CLR_WRITE_PROT 29
+#define SEND_WRITE_PROT 30
+#define ERASE_START 32
+#define ERASE_END 33
+//#define UNTAG_SECTOR 34
+//#define TAG_ERASE_GROUP_START 35
+//#define TAG_ERASE_GROUP_END 36
+//#define UNTAG_ERASE_GROUP 37
+#define ERASE_GO 38
+//for SPI mode
+#define READ_OCR 58 //for SPI
+#define CRC_ON_OFF 59
+#define APP_CMD 55
+//APP command
+#define SET_BUS_WIDTH 6
+#define SD_STATUS 13
+#define SD_NUM_WR_BLOCKS 22
+#define SD_WR_BLK_ERASE_COUNT 23
+#define SD_APP_OP_COND 41
+#define SD_SET_CLR_CARD_DETECT 42
+#define SD_SEND_SCR 51
+
+#define SWITCH_MMC 6
+// SD Response types
+#define R0 0 // NONE response
+#define R1 1 // Basic response format
+#define R2 2 // R2 response. Used by ALL_SEND_CID(CMD2),
+ // SEND_CID(CMD10) and SEND_CSD(CMD9)
+#define R3 3 // R3 response. Used by SEND_APP_OP_COND(ACMD41)
+#define R6 6 // R6 response. Used by SEND_RELATIVE_ADDR(CMD3)
+#define R1b 9
+
+//bit definition for SD controller register
+
+// 0x0 Control register
+#define FIFO_RESET 0x08
+#define CMD_START 0x01
+#define CMD_READ 0x00
+#define CMD_WRITE 0x04
+#define CMD_SWRITE 0x10
+#define CMD_SREAD 0x20
+#define CMD_MWRITE 0x30
+#define CMD_MREAD 0x40
+
+//0x08 BusMode register
+#define SOFT_RESET 0x80
+#define SD_POWER 0x40
+#define SPI_CS 0x20
+#define SD_OFF 0x10
+#define FOURBIT_MODE 0x02
+#define ONEBIT_MODE 0xFD
+#define SPI_MODE 0x01
+#define SD_MODE 0x00
+#define EIGHTBIT_MODE 0x04
+
+//0x0C BlkLen
+#define INT_ENABLE 0x80
+#define DATA3_CD 0x40
+#define GPI_CD 0x20
+#define CD_POL_HIGH 0x10
+#define CRCERR_ABORT 0x08 //abort multiple-blk-transfer when CRC-Err
+
+
+//0x24 IntMask0
+#define DI_INT_EN 0x80
+#define CD_INT_EN 0x40
+#define BLK_TRAN_DONE_INT_EN 0x20
+#define MBLK_TRAN_DONE_INT_EN 0x10
+
+//0x25 IntMask0
+#define WCRC_ERR_INT_EN 0x80
+#define RCRC_ERR_INT_EN 0x40
+#define RESCRC_ERR_INT_EN 0x20
+#define DATA_TOUT_INT_EN 0x10
+#define MBLK_AUTO_STOP_INT_EN 0x08
+#define CMD_RES_TOUT_INT_EN 0x04
+#define CMD_RES_TRAN_DONE_INT_EN 0x02
+
+//0x28 Status0 register
+#define DEVICE_INS 0x80
+#define CARD_DETECT 0x40
+#define BLK_DONE 0x20
+#define MBLK_DONE 0x10
+#define CD_GPI 0x08
+#define CD_DATA3 0x04
+#define Write_Protect 0x02
+
+
+//0x29 Status1 register
+#define WCRC_ERR 0x80
+#define RCRC_ERR 0x40
+#define RSP_CRC_ERR 0x20
+#define DATA_TIMEOUT 0x10
+#define AUTOSTOP_DONE 0x08
+#define RSP_TIMEOUT 0x04
+#define CMDRSP_DONE 0x02
+#define SDIO_INT 0x01
+
+//0x2A Status2 register
+#define DIS_FORCECLK 0x80
+#define DATARSP_BUSY 0x20
+#define CMD_RES_BUSY 0x10
+
+//0x30 Clock register
+#define Clk_375 0x00
+#define Clk_10 0x01
+#define Clk_12 0x02
+#define Clk_15 0x03
+#define Clk_20 0x04
+#define Clk_24 0x05
+#define Clk_30 0x06
+#define Clk_40 0x07
+#define Clk_48 0x08
+
+#define SD_Clk_Auto 0
+#define SD_Clk_15MHz 1
+#define SD_Clk_20MHz 2
+#define SD_Clk_25MHz 3
+#define SD_Clk_33MHz 4
+#define SD_Clk_40MHz 5
+#define SD_Clk_44MHz 6
+#define SD_Clk_50MHz 7
+#define SD_Clk_400KHz 8
+
+
+//0x34 Extension Control register
+#define ArgShift 0x02
+#define AutoStop 0x01
+
+//return sdstatus
+#define CMD_OK 0x00
+#define CMDRSP_TOUT 0x01
+#define RSP_CRCERR 0x02
+#define APPCMD_FAIL 0x03
+#define DATA_TOUT 0x04
+#define WRITE_CRCERR 0x05
+#define READ_CRCERR 0x06
+#define TYPE_UNKNOWN 0x07
+#define NOCARD_INSERT 0x08
+#define POWER_FAIL 0x09
+#define READ_CID_ERR 0x0a
+#define READ_RCA_ERR 0x0b
+#define SET_RCA_ERR 0x0c
+#define READ_CSD_ERR 0x0d
+#define SELECT_CARD_ERR 0x0e
+#define READ_SCR_ERR 0x0f
+#define SET_BUSWIDTH_ERR 0x10
+#define SET_BLKLEN_ERR 0x11
+#define STOP_FAIL 0x12
+#define MBLK_FAIL 0x13
+#define TURE_T 0x14
+#define FALSE_F 0x15
+
+#define SWITCH_ERR 0x14
+#define SD1_0 0x00
+#define SD1_1 0x01
+#define SD2_0 0x02
+
+#define MMC1_12 0x00
+#define MMC1_4 0x01
+#define MMC2_02 0x02
+#define MMC3_123 0x03
+#define MMC4_01 0x04
+
+#define HostCapacitySupport 0x40
+#define StandardCapacity 0x00
+#define HighCapacity 0x01
+
+#define MMC_BLOCK_SIZE 512
+#define CFG_MMC_BASE 0xF0000000
+
+//SD DMA channel control registers -- CTR
+
+/* Reserved [07:05] */
+#define SD_DMA_CTR_SW_REQ_EN 0x10 /* [04:04] */
+#define SD_DMA_CTR_SW_REQ_DIS 0x00
+
+/* Reserved [03:01] */
+#define SD_DMA_CTR_CH_EN 0x01 /* [00:00] */
+#define SD_DMA_CTR_CH_DIS 0x00 /* [00:00] */
+
+//SD DMA channel status registers -- CSR
+#define SD_DMA_CSR_DMA_REQ 0x80 /* [07:07] */
+/* Reserved [06:04] */
+#define SD_DMA_CSR_FIFO_EMPTY_INT 0x08 /* [03:03] */
+#define SD_DMA_CSR_FIFO_EMPTY_INT_WRITE_CLEAR 0x08 /* [03:03] */
+#define SD_DMA_CSR_AHB_BUS_ERR 0x04 /* [02:02] */
+#define SD_DMA_CSR_AHB_BUS_ERR_WRITE_CLEAR 0x04 /* [02:02] */
+/* For USB use [01:01] */
+#define SD_DMA_CSR_TC 0x01 /* [00:00] */
+#define SD_DMA_CSR_TC_WRITE_CLEAR 0x01
+
+#define SD_DMA_CSR_ALL_SET_CLEAR 0x0F
+
+//SD DMA global control registers -- GCR
+
+/* Reserved [31:25] */
+#define SD_DMA_GCR_MANUAL_FLUSH_EN 0x01000000 /* [24:24] */
+#define SD_DMA_GCR_MANUAL_FLUAH_DIS 0x00000000 /* [24:24] */
+/* Reserved [23:17] */
+#define SD_DMA_GCR_FLUSH_FIFO 0x00010000 /* [16:16] */
+#define SD_DMA_GCR__FLUSH_SELF_CLEAR 0x00000000 /* [16:16] */
+/* Reserved [15:9] */
+#define SD_DMA_GCR_GINT_EN 0x00000100 /* [08:08] */
+#define SD_DMA_GCR_GINT_DIS 0x00000000 /* [08:08] */
+/* Reserved [07:01] */
+#define SD_DMA_GCR_GDMA_EN 0x00000001 /* [00:00] */
+#define SD_DMA_GCR_GDMA_DIS 0x00000000 /* [00:00] */
+
+/*
+ * SD PDMA
+ */
+#define SD_PDMA_BASE_ADDR 0xD800A100
+#define SD_DESC_BASE_ADDR 0x00d00000
+struct _SD_PDMA_REG_ {
+ volatile unsigned long DMA_GCR; /* Rx00 */
+ volatile unsigned long DMA_IER; /* Rx04 */
+ volatile unsigned long DMA_ISR; /* Rx08 */
+ volatile unsigned long *DMA_DESPR; /* Rx0C */
+ volatile unsigned long DMA_RBR; /* Rx10 */
+ volatile unsigned long DMA_DAR; /* Rx14 */
+ volatile unsigned long DMA_BAR; /* Rx18 */
+ volatile unsigned long DMA_CPR; /* Rx1C */
+ volatile unsigned long DMA_CCR; /* RX20 */
+ volatile unsigned long resv[5]; /* RX2C-3C */
+}; +//} SD_PDMA_REG, *PSD_PDMA_REG;
+
+/*
+ * SD PDMA - DMA_GCR : DMA Global Control Register
+ */
+#define SD_PDMA_GCR_DMA_EN 0x00000001 /* [0] -- DMA controller enable */
+#define SD_PDMA_GCR_SOFTRESET 0x00000100 /* [8] -- Software rest */
+
+/*
+ * SD PDMA - DMA_IER : DMA Interrupt Enable Register
+ */
+#define SD_PDMA_IER_INT_EN 0x00000001 /* [0] -- DMA interrupt enable */
+/*
+ * SD PDMA - DMA_ISR : DMA Interrupt Status Register
+ */
+#define SD_PDMA_IER_INT_STS 0x00000001 /* [0] -- DMA interrupt status */
+/*
+ * SD PDMA - DMA_DESPR : DMA Descriptor base address Pointer Register
+ */
+
+/*
+ * SD PDMA - DMA_RBR : DMA Residual Bytes Register
+ */
+#define SD_PDMA_RBR_End 0x80000000 /* [0] -- DMA interrupt status */
+#define SD_PDMA_RBR_Format 0x40000000 /* [0] -- DMA interrupt status */
+/*
+ * SD PDMA - DMA_DAR : DMA Data Address Register
+ */
+
+/*
+ * SD PDMA - DMA_BAR : DMA Rbanch Address Register
+ */
+
+/*
+ * SD PDMA - DMA_CPR : DMA Command Pointer Register
+ */
+
+/*
+ * SD PDMA - DMA_CCR : DMAContext Control Register for Channel 0
+ */
+#define SD_PDMA_READ 0x00
+#define SD_PDMA_WRITE 0x01
+#define SD_PDMA_CCR_RUN 0x00000080
+#define SD_PDMA_CCR_IF_to_peripheral 0x00000000
+#define SD_PDMA_CCR_peripheral_to_IF 0x00400000
+#define SD_PDMA_CCR_EvtCode 0x0000000f
+#define SD_PDMA_CCR_Evt_no_status 0x00000000
+#define SD_PDMA_CCR_Evt_ff_underrun 0x00000001
+#define SD_PDMA_CCR_Evt_ff_overrun 0x00000002
+#define SD_PDMA_CCR_Evt_desp_read 0x00000003
+#define SD_PDMA_CCR_Evt_data_rw 0x00000004
+#define SD_PDMA_CCR_Evt_early_end 0x00000005
+#define SD_PDMA_CCR_Evt_success 0x0000000f
+
+/*
+ * PDMA Descriptor short
+ */
+struct _SD_PDMA_DESC_S{
+ unsigned long volatile ReqCount:16; /* bit 0 -15 -Request count */
+ unsigned long volatile i:1; /* bit 16 -interrupt */
+ unsigned long volatile reserve:13; /* bit 17-29 -reserved */
+ unsigned long volatile format:1; /* bit 30 -The descriptor format */
+ unsigned long volatile end:1; /* bit 31 -End flag of descriptor list*/
+ unsigned long volatile *DataBufferAddr; /* bit 31 -Data Buffer address */
+};//__attribute__((packed)); /*mvl tool chain can't uas __attribute__((packed))*/
+
+/*
+ * PDMA Descriptor long
+ */
+struct _SD_PDMA_DESC_L{
+ unsigned long volatile ReqCount:16; /* bit 0 -15 -Request count */
+ unsigned long volatile i:1; /* bit 16 -interrupt */
+ unsigned long volatile reserve:13; /* bit 17-29 -reserved */
+ unsigned long volatile format:1; /* bit 30 -The descriptor format */
+ unsigned long volatile end:1; /* bit 31 -End flag of descriptor list*/
+ unsigned long volatile *DataBufferAddr; /* bit 31-0 -Data Buffer address */
+ unsigned long volatile *BranchAddr; /* bit 31-2 -Descriptor Branch address */
+ unsigned long volatile reserve0; /* bit 31-0 -reserved */
+};//__attribute__((packed));
+
+//SD card related information
+typedef struct sd_info_s {
+ unsigned char RCAHi;
+ unsigned char RCALo;
+ unsigned long SDCard_Size;
+ unsigned char MMC_Card;
+ unsigned char SD_Card;
+ unsigned char SD_IO_Card;
+ unsigned char InitOK;
+ unsigned char CardStateChange;
+ unsigned char CardInsert;
+ unsigned char CardRemove;
+ unsigned char SDVersion;
+ unsigned char CardCapacityStatus;
+ unsigned char MMCMaxClockRate;
+ unsigned char HighSpeedSupport;
+ unsigned char MMCVersion;
+ unsigned char ocr[4];
+ unsigned char cid[16];
+ unsigned char csd[16];
+ unsigned char ext_csd[512];
+ unsigned char scr[8];
+ unsigned char CtrlID;
+ unsigned long RCA;
+ unsigned long strapping;
+} sd_info_t;
+
+/*SDMMC control registers.*/
+typedef struct{
+ volatile unsigned char ctlr; /*Control Register*/
+ volatile unsigned char cmdi; /*Command Index Register*/
+ volatile unsigned char respt; /*Response Type Register*/
+ volatile unsigned char Reserved1; /*Reserved1*/
+ volatile unsigned char cmdarg0; /*Command Argument Register 0x03*/
+ volatile unsigned char cmdarg1; /*Command Argument Register 0x04*/
+ volatile unsigned char cmdarg2; /*Command Argument Register 0x05*/
+ volatile unsigned char cmdarg3; /*Command Argument Register 0x06*/
+ volatile unsigned char busm; /*Bus Mode Register*/
+ volatile unsigned char Reserved2[3]; /*Reserved2*/
+ volatile unsigned short blklen; /*Block Length Register*/
+ volatile unsigned short blkcnt; /*Block Count Register*/
+ volatile unsigned char resr[16]; /*Response Register*/
+ volatile unsigned short cbc; /*Current Block Count*/
+ volatile unsigned short Reserved3; /*Reserved3*/
+ volatile unsigned char imr0; /*Interrupt Mask Register 0*/
+ volatile unsigned char imr1; /*Interrupt Mask Register 1*/
+ volatile unsigned char Reserved4[2]; /*Reserved3*/
+ volatile unsigned char str0; /*SD Status Register 0*/
+ volatile unsigned char str1; /*SD Status Register 1*/
+ volatile unsigned char str2; /*SD Status Register 2*/
+ volatile unsigned char str3; /*SD Status Register 3 (SPI Data Error)*/
+ volatile unsigned char rtor; /*Response Time Out Register*/
+ volatile unsigned char Reserved5[3]; /*Reserved4*/
+ volatile unsigned long Reserved6; /*Reserved5*/
+ volatile unsigned char extctl; /*Extend Control Register*/
+ volatile unsigned char Reserved7[3]; /*Reserved6*/
+ volatile unsigned short sblklen; /*Shadowed Block Length Register*/
+ volatile unsigned short Reserved8; /*Reserved7*/
+ volatile unsigned short timeval; /*Timer Value Register*/
+}
+WMT_SDMMC_REG, *PWMT_SDMMC_REG;
+
+
+
+/*GPIO*/
+typedef struct _GPIO_REG_
+{
+ volatile unsigned long CTRL_KPAD_MPGTS_ROM; // [Rx00] GPIO Enable Control Register for Kpad, Mpeg-TS, CEN_SEEROM
+ volatile unsigned long CTRL_DVI; // [Rx04] GPIO Enable Control Register for DVI Signal
+ volatile unsigned long CTRL_CF; // [Rx08] GPIO Enable Control Register for CF
+ volatile unsigned long CTRL_NF; // [Rx0C] GPIO Enable Control Register for NF
+ volatile unsigned long CTRL_PCIAD; // [Rx10] GPIO Enable Control for PCI AD BUS
+ volatile unsigned long CTRL_PCI; // [Rx14] GPIO Eanble Control for Non PCI AD BUS
+ volatile unsigned long CTRL_LCD_SPDIF; // [Rx18] GPIO Enable Control for LCD, SPDIF
+ volatile unsigned long RESV_1C; // [Rx1C]
+
+ volatile unsigned long OC_KPAD_MPGTS_ROM; // [Rx20] GPIO Output Control Register for Kpad, Mpeg-TS, CEN_SEEROM
+ volatile unsigned long OC_DVI; // [Rx24] GPIO Output Control Register for DVI Signal
+ volatile unsigned long OC_CF; // [Rx28] GPIO Output Control Register for CF
+ volatile unsigned long OC_NF; // [Rx2C] GPIO Output Control Register for NF
+ volatile unsigned long OC_PCIAD; // [Rx30] GPIO Output Control Register for PCI AD BUS
+ volatile unsigned long OC_PCI; // [Rx34] GPIO Output Control Register for Non PCI AD BUS
+ volatile unsigned long OC_LCD_SPDIF; // [Rx38] GPIO Output Control Register for LCD, SPDIF
+ volatile unsigned long RESV_3C; // [Rx3C]
+
+ volatile unsigned long OD_KPAD_MPGTS_ROM; // [Rx40] GPIO Output Data Register for Kpad, Mpeg-TS, CEN_SEEROM
+ volatile unsigned long OD_DVI; // [Rx44] GPIO Output Data Register for DVI Signal
+ volatile unsigned long OD_CF; // [Rx44] GPIO Output Data Register for CF
+ volatile unsigned long OD_NF; // [Rx4C] GPIO Output Data Register for NF
+ volatile unsigned long OD_PCIAD; // [Rx50] GPIO Output Data Register for PCIAD
+ volatile unsigned long OD_PCI; // [Rx54] GPIO Output Data Register for Non PCI AD BUS
+ volatile unsigned long OD_LCD_SPDIF; // [Rx58] GPIO Output Data Register for LCD, SPDIF
+ volatile unsigned long RESV_5C; // [Rx5C]
+
+ volatile unsigned long ID_KPAD_MPGTS_ROM; // [Rx60] GPIO Input Data Register for Kpad, Mpeg-TS, CEN_SEEROM
+ volatile unsigned long ID_DVI; // [Rx64] GPIO Input Data Register for DVI Signal
+ volatile unsigned long ID_CF; // [Rx68] GPIO Input Data Register for CF
+ volatile unsigned long ID_NF; // [Rx6C] GPIO Input Data Register for NF
+ volatile unsigned long ID_PCIAD; // [Rx70] GPIO Input Data Register for PCIAD
+ volatile unsigned long ID_PCI; // [Rx74] GPIO Input Data Register for Non PCI AD BUS
+ volatile unsigned long ID_LCD_SPDIF; // [Rx78] GPIO Input Data Register for LCD, SPDIF
+ volatile unsigned long RESV_7C; // [Rx7C]
+
+ volatile unsigned long RESV_80[0x20]; // [Rx80-RxFF]
+
+ volatile unsigned long STRAP_STS1; // [Rx100] Strapping Option Status Register1
+ volatile unsigned long STRAP_STS2; // [Rx104] Strapping Option Status Register2
+ volatile unsigned long AHB_CTRL; // [Rx108] AHB Control Register
+ volatile unsigned long RESV_10C[0x3D]; // [Rx10C-Rx1FF]
+
+ volatile unsigned long PIN_MULTI; // [Rx200] Pin Multiplexing
+ volatile unsigned long RESV_204[0x3]; // [Rx204-Rx20F]
+ volatile unsigned long PCI_DELAY_TEST; // [Rx210]
+ volatile unsigned long PCI_RESET; // [Rx214]
+ volatile unsigned long RESV_218[2]; // [Rx218 - Rx21F]
+ volatile unsigned long PCI_1X_DELAY; // [Rx220]
+ volatile unsigned long PCI_2X_DELAY; // [Rx224]
+ volatile unsigned long PCI_2X_RELAY_INVERT; // [Rx228]
+ volatile unsigned long RESV_22C[0x35]; // [Rx22C - Rx2FF]
+
+ volatile unsigned long INT_REQ_TYPE; // [Rx300] GPIO Interrupt Request Type Register
+ volatile unsigned long INT_REQ_STS; // [Rx304] GPIO Interrupt Request Status Register
+ volatile unsigned long RESV_308[0x3E]; // [Rx308-Rx3FF]
+
+ volatile unsigned long IDE_IO_DRV; // [Rx400] IDE I/O Drive Strength Register
+ volatile unsigned long MS_IO_DRV; // [Rx404] MS I/O Drive Strength and Slew Rate Register
+ volatile unsigned long PCI_IO_DRV; // [Rx408] PCI Bus I/O Drive Strength and Slew Rate Register
+ volatile unsigned long SD_IO_DRV; // [Rx40C] SD I/O Drive Strength and Slwe Rate Register
+ volatile unsigned long VID_IO_DRV; // [Rx410] VID Clock I/O Drive Strength and Slew Rate Register
+ volatile unsigned long SPI_IO_DRV; // [Rx414] SPI I/O Drive Strength and Slew Rate Register
+ volatile unsigned long CF_IO_DRV; // [Rx418] CF I/O Drive Strength and Slew Rate Register
+ volatile unsigned long LPC_IO_DRV; // [Rx41C] LPC I/O Drive Strength and Slew Rate Register
+ volatile unsigned long NF_IO_DRV; // [Rx420] NAND I/O Drive Strength and Slew Rate Register
+ volatile unsigned long MISC_IO_DRV; // [Rx424] MISC I/O Drive Strength and Slew Rate Register
+}GPIO_REG, * PGPIO_REG;
+
+
+typedef struct root_dir {
+ char MagicHeader[32];
+ char filename1[16];
+ unsigned int filesize1;
+ char resv1[12];
+ char filename2[16];
+ unsigned int filesize2;
+ char resv2[12];
+ char filename3[16];
+ unsigned int filesize3;
+ char resv3[12];
+} root_dir;
+
+
+#endif
diff --git a/cpu/arm920t/wmt/serial.c b/cpu/arm920t/wmt/serial.c new file mode 100755 index 0000000..5777507 --- /dev/null +++ b/cpu/arm920t/wmt/serial.c @@ -0,0 +1,264 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* + * serial.c - serial support for the WMT evaluation board + */ + +#include <common.h> + +#ifdef CFG_WMT_SERIAL + +#include <asm/arch/hardware.h> +#include "uart.h" +#include "gpio.h" +extern int bootcmdflag; +extern int showinfoflag; + +DECLARE_GLOBAL_DATA_PTR; + +PUART_REG pUart_Reg = (PUART_REG)BA_UART0; +PGPIO_REG pGpioReg = (PGPIO_REG)BA_GPIO; + +/* + * Function purpose: + * UART initialization + */ +int serial_init(void) +{ + /* Switch the Uart's pin from default GPIO into uart function pins for UART0/UART1 */ + pGpioReg->CTRL_UR_LPC_SF &= ~(GPIO_UR0_ALL | GPIO_UR1_ALL); + + serial_setbrg(); + + return 0; +} + +/* + * Function purpose: + * Output character data through UART + */ +#ifdef CONFIG_USB_TTY +unsigned int do_puts=0; +#endif +void +serial_putc(const char c) +{ + if (bootcmdflag == 1 || showinfoflag == 1) { +#ifdef CONFIG_USB_TTY + char tmp[2]; + + tmp[0] = c; + tmp[1] = 0; + + if(( c != '\r' )&&(do_puts == 0)) + { + usbtty_putc(c); + } +#endif + while (1) { + if ((pUart_Reg->URUSR & URUSR_TXDBSY) == 0) /* TX data not busy */ + break; + } + + pUart_Reg->URTDR = c; + if (c == '\n') + serial_putc('\r'); +} +} + +/* + * Function purpose: + * Output string data through UART + */ +void +serial_puts(const char *s) +{ +#ifdef CONFIG_USB_TTY + int tmp=0; + + do_puts = 1; +#endif + while (*s) + { + serial_putc(*s++); +#ifdef CONFIG_USB_TTY + tmp++; +#endif +} +#ifdef CONFIG_USB_TTY + do_puts = 0; + usbtty_puts ((const char *)((int)s-tmp)); +#endif +} +/* + * Function purpose: + * Require character data from UART + */ +int +serial_getc(void) +{ +#ifdef CONFIG_USB_TTY + int tmp=0; + char c; + + while (1) + { + if(pUart_Reg->URUSR & URUSR_RXDRDY) + { + tmp++; + break; + } + if(c = usbtty_getc()) + break; + } + + return tmp?(pUart_Reg->URRDR&0xff):c; +#else + while (!(pUart_Reg->URUSR & URUSR_RXDRDY)); + + return pUart_Reg->URRDR&0xff; +#endif +} + +/* + * Function purpose: + * return RXDRDY status bit in Uart status register + */ +int +serial_tstc(void) +{ +#ifdef CONFIG_USB_TTY + return (((pUart_Reg->URUSR & URUSR_RXDRDY)||usbtty_getc()) ? 1 : 0); +#else + return ((pUart_Reg->URUSR & URUSR_RXDRDY) ? 1 : 0); +#endif +} + +/* + * Function purpose: + * Uart baud rate setting and initialization + * Note: + * Relative settings according to UART/IrDA + * Programmer Guide Revision 0.13 + */ +void +serial_setbrg(void) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned long TmpDiv = 0; + unsigned long TmpBkr = 0; + + switch (gd->baudrate) { + /* + case BR_921K6: + TmpDiv = UART_BR_921K6; + TmpBkr = UART_BK_921K6; + break; + + case BR_460K8: + TmpDiv = UART_BR_460K8; + TmpBkr = UART_BK_460K8; + break; + + case BR_230K4: + TmpDiv = UART_BR_230K4; + TmpBkr = UART_BK_230K4; + break; + */ + + case BR_57K6: + TmpDiv = UART_BR_57K6; + TmpBkr = UART_BK_57K6; + break; + /* + case BR_28K8: + TmpDiv = UART_BR_28K8; + TmpBkr = UART_BK_28K8; + break; + + case BR_14K4: + TmpDiv = UART_BR_14K4; + TmpBkr = UART_BK_14K4; + break; + + case BR_7K2: + TmpDiv = UART_BR_7K2; + TmpBkr = UART_BK_7K2; + break; + + case BR_3K6: + TmpDiv = UART_BR_3K6; + TmpBkr = UART_BK_3K6; + break; + */ + + case BR_38K4: + TmpDiv = UART_BR_38K4; + TmpBkr = UART_BK_38K4; + break; + + case BR_19K2: + TmpDiv = UART_BR_19K2; + TmpBkr = UART_BK_19K2; + break; + + case BR_9K6: + TmpDiv = UART_BR_9K6; + TmpBkr = UART_BK_9K6; + break; + + case BR_115K2: + default: + TmpDiv = UART_BR_115K2; + TmpBkr = UART_BK_115K2; + break; + } + + pUart_Reg->URDIV = TmpDiv; + pUart_Reg->URBKR = TmpBkr; + + /* Disable TX,RX */ + pUart_Reg->URLCR = 0; + + /* Disable all interrupt */ + pUart_Reg->URIER = 0; + + /* Clear all interrupt status until all zeros */ + /* + while (pUart_Reg->URISR) { + pUart_Reg->URISR = pUart_Reg->URISR; + } + */ + + /* Reset Tx,Rx Fifo until all zeros */ + while (pUart_Reg->URFCR) { + /* Reset TX,RX Fifo */ + pUart_Reg->URFCR = URFCR_TXFRST | URFCR_RXFRST; + } + + /* Disable Fifo */ + pUart_Reg->URFCR &= (~URFCR_FIFOEN); + + /* 8-N-1 */ + pUart_Reg->URLCR |= (URLCR_DLEN8B & ~URLCR_STBLEN2b & ~URLCR_PYTEN); + + /* Enable TX,RX */ + pUart_Reg->URLCR |= URLCR_RXEN | URLCR_TXEN; +} + +#endif /* CFG_WMT_SERIAL */ diff --git a/cpu/arm920t/wmt/setup.h b/cpu/arm920t/wmt/setup.h new file mode 100755 index 0000000..a4267af --- /dev/null +++ b/cpu/arm920t/wmt/setup.h @@ -0,0 +1,108 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __SETUP_H__ +#define __SETUP_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__ADAPTER_H__) +#include "adapter.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define DIAG_AUTO_NONE 0 +#define DIAG_AUTO_DIAG 1 +#define DIAG_AUTO_2CTEST 2 +#define DIAG_AUTO_PINGPONG 3 +#define DIAG_AUTO_PHYTEST 4 + +typedef struct CmdParaSet { + + /* command-line auto-function number, default = 0 (no auto-function), diagnositic test = 1, */ + /* network test = 2 */ + UINT uCmdFuncNum; + /* function execution frequency, default = 0 (forever) */ + ULONG ulTestFreq; + /* specify auto-test NIC number */ + UINT uCardNum; + /* init NIC with forced mode, default = 0 (Auto mode), 1=10H, 2=10F, 3=100H, 4=100F */ + UINT uForceMode; + /* shared IRQ support, default = TRUE */ + BOOL bSharedIRQ; + + /* 2-card network test with specified transmit packet size */ + /* 0 = increased packet size, 1 = Random packet size */ + /* 60 - 1514 = packet size */ + UINT uPktSize; + + /* test cable link status in diagnostic, default = TRUE */ + BOOL bTstCable; + + /* Connect to Altima-PHY slave RxNoReply exampt count, default = 0 */ + UINT uAltimaSlaveRxNoReply; + + /* Internal/external loopback test, default = FALSE */ + BOOL bExtLoopback; + + /* [1.34], Gigabit mode external loopback test, default = FALSE */ + BOOL bExtLoopbackGiga; + + /* RAMBIST test, default = TRUE */ + BOOL bRAMBISTTest; + + /* FIFO test, default = FALSE */ + BOOL bFIFOTest; + + /* IOL test flag, default = FALSE */ + BOOL bIOLTest; + + /* EEPROM checksum checking flag, default = FALSE */ + BOOL bEEPROMCheck; + + /* ForceMode loop flag, default = FALSE */ + BOOL bForceModeLoop; + + /* [1.33], Random data of packets for 2-card test, default = FALSE (normal content filling) */ + BOOL bRandomPktData; + + /* [1.33], Control transmission traffic for 2-card test, default = FALSE (normal load) */ + BOOL bHeavyLoad; + +} SCmdParaSet, DEF * PSCmdParaSet; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +void SETUPvSetupMenu(PSAdapterInfo pAdapter, SCmdParaSet sCmdPara); +ULONG SETUPuSetupSilence(PSAdapterInfo pAdapter[], SCmdParaSet sCmdPara); +void SETUPvGetStringForRealTimeMedia(PTSTR pszString, PSAdapterInfo pAdapter); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __SETUP_H__ */ diff --git a/cpu/arm920t/wmt/tascii.h b/cpu/arm920t/wmt/tascii.h new file mode 100755 index 0000000..6924306 --- /dev/null +++ b/cpu/arm920t/wmt/tascii.h @@ -0,0 +1,145 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __TASCII_H__ +#define __TASCII_H__ + +/*--------------------- Export Definitions -------------------------*/ + +/* + * CONTROL ASCII CODE + */ +#define MC_NULL 0x00 /* null char */ +#define MC_SOH 0x01 /* Ctrl+A : */ +#define MC_STX 0x02 /* Ctrl+B : */ +#define MC_ETX 0x03 /* Ctrl+C : */ +#define MC_EOT 0x04 /* Ctrl+D : end of text */ +#define MC_ENQ 0x05 /* Ctrl+E : */ +#define MC_ACK 0x06 /* Ctrl+F : */ + +#define MC_BELL 0x07 /* Ctrl+G : bell sound */ +#define MC_BACKSPACE 0x08 /* Ctrl+H : backspace */ +#define MC_TAB 0x09 /* Ctrl+I : harizontal tab */ +#define MC_LINEFEED 0x0A /* Ctrl+J : line feed */ +/* EOL(end of line for UNIX) */ +#define MC_VTAB 0x0B /* Ctrl+K : vertical tab */ +#define MC_FORMFEED 0x0C /* Ctrl+L : form feed */ +#define MC_ENTER 0x0D /* Ctrl+M : carriage return */ + +#define MC_SO 0x0E /* Ctrl+N : */ +#define MC_SI 0x0F /* Ctrl+O : */ +#define MC_DLE 0x10 /* Ctrl+P : */ + +#define MC_XON 0x11 /* Ctrl+Q : device control 1 */ +/* xon */ +#define MC_DC2 0x12 /* Ctrl+R : */ +#define MC_XOFF 0x13 /* Ctrl+S : device conteol 3 */ +/* xoff */ +#define MC_DC4 0x14 /* Ctrl+T : */ +#define MC_NAK 0x15 /* Ctrl+U : */ +#define MC_SYN 0x16 /* Ctrl+V : */ +#define MC_ETB 0x17 /* Ctrl+W : */ +#define MC_CAN 0x18 /* Ctrl+X : */ +#define MC_EM 0x19 /* Ctrl+Y : */ + +#define MC_SUB 0x1A /* Ctrl+Z : */ +/* EOF(end of file for MSDOS) */ +#define MC_ESCAPE 0x1B /* Ctrl+[ : escape */ + +#define MC_FS 0x1C /* Ctrl+\ : */ +#define MC_GS 0x1D /* Ctrl+] : */ +#define MC_RS 0x1E /* Ctrl+^ : */ +#define MC_US 0x1F /* Ctrl+_ : */ + +/* + * PRINTABLE ASCII CODE + */ +#define MC_SPACE 0x20 /* space char */ + +#define MC_0 0x30 /* 0 */ +#define MC_1 0x31 /* 1 */ +#define MC_2 0x32 /* 2 */ +#define MC_3 0x33 /* 3 */ +#define MC_4 0x34 /* 4 */ +#define MC_5 0x35 /* 5 */ +#define MC_6 0x36 /* 6 */ +#define MC_7 0x37 /* 7 */ +#define MC_8 0x38 /* 8 */ +#define MC_9 0x39 /* 9 */ + +#define MC_A 0x41 /* A */ +#define MC_B 0x42 /* B */ +#define MC_C 0x43 /* C */ +#define MC_D 0x44 /* D */ +#define MC_E 0x45 /* E */ +#define MC_F 0x46 /* F */ +#define MC_G 0x47 /* G */ +#define MC_H 0x48 /* H */ +#define MC_I 0x49 /* I */ +#define MC_J 0x4A /* J */ +#define MC_K 0x4B /* K */ +#define MC_L 0x4C /* L */ +#define MC_M 0x4D /* M */ +#define MC_N 0x4E /* N */ +#define MC_O 0x4F /* O */ +#define MC_P 0x50 /* P */ +#define MC_Q 0x51 /* Q */ +#define MC_R 0x52 /* R */ +#define MC_S 0x53 /* S */ +#define MC_T 0x54 /* T */ +#define MC_U 0x55 /* U */ +#define MC_V 0x56 /* V */ +#define MC_W 0x57 /* W */ +#define MC_X 0x58 /* X */ +#define MC_Y 0x59 /* Y */ +#define MC_Z 0x5A /* Z */ + +#define MC_a 0x61 /* a */ +#define MC_b 0x62 /* b */ +#define MC_c 0x63 /* c */ +#define MC_d 0x64 /* d */ +#define MC_e 0x65 /* e */ +#define MC_f 0x66 /* f */ +#define MC_g 0x67 /* g */ +#define MC_h 0x68 /* h */ +#define MC_i 0x69 /* i */ +#define MC_j 0x6A /* j */ +#define MC_k 0x6B /* k */ +#define MC_l 0x6C /* l */ +#define MC_m 0x6D /* m */ +#define MC_n 0x6E /* n */ +#define MC_o 0x6F /* o */ +#define MC_p 0x70 /* p */ +#define MC_q 0x71 /* q */ +#define MC_r 0x72 /* r */ +#define MC_s 0x73 /* s */ +#define MC_t 0x74 /* t */ +#define MC_u 0x75 /* u */ +#define MC_v 0x76 /* v */ +#define MC_w 0x77 /* w */ +#define MC_x 0x78 /* x */ +#define MC_y 0x79 /* y */ +#define MC_z 0x7A /* z */ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __TASCII_H__ */ diff --git a/cpu/arm920t/wmt/tbit.h b/cpu/arm920t/wmt/tbit.h new file mode 100755 index 0000000..39db55d --- /dev/null +++ b/cpu/arm920t/wmt/tbit.h @@ -0,0 +1,69 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __TBIT_H__ +#define __TBIT_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/* test single bit on */ +#define BITbIsBitOn(tData, tTestBit) \ + (((tData) & (tTestBit)) != 0) + +/* test single bit off */ +#define BITbIsBitOff(tData, tTestBit) \ + (((tData) & (tTestBit)) == 0) + +#define BITbIsAllBitsOn(tData, tTestBit) \ + (((tData) & (tTestBit)) == (tTestBit)) + +#define BITbIsAllBitsOff(tData, tTestBit) \ + (((tData) & (tTestBit)) == 0) + +#define BITbIsAnyBitsOn(tData, tTestBit) \ + (((tData) & (tTestBit)) != 0) + +#define BITbIsAnyBitsOff(tData, tTestBit) \ + (((tData) & (tTestBit)) != (tTestBit)) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +BYTE BITbyReverseB(BYTE byData); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __TBIT_H__ */ diff --git a/cpu/arm920t/wmt/tconvert.c b/cpu/arm920t/wmt/tconvert.c new file mode 100755 index 0000000..0c00273 --- /dev/null +++ b/cpu/arm920t/wmt/tconvert.c @@ -0,0 +1,262 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* #include <string.h> */ +/* #include <stdlib.h> */ + +#if !defined(__UASSERT_H__) +#include "uassert.h" +#endif +#if !defined(__TASCII_H__) +#include "tascii.h" +#endif +#if !defined(__TCONVERT_H__) +#include "tconvert.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +void CVTvBy6ToStr12(PBYTE pbyEtherAddr, const PTSTR pszResult) +{ + int ii; + UINT uDigit; + PBYTE pbyResult = (PBYTE)pszResult; + + for (ii = 0; ii < 6; ii++) { + /* each time we convert one byte to two digits */ + + /* the 16^^1 portion */ + uDigit = pbyEtherAddr[ii] / 16; + + if (uDigit < 10) + *pbyResult = (BYTE)(MC_0 + uDigit); + else + *pbyResult = (BYTE)(MC_A + uDigit - 10); + pbyResult++; + + /* the 16^^0 portion */ + uDigit = pbyEtherAddr[ii] % 16; + if (uDigit < 10) + *pbyResult = (BYTE)(MC_0 + uDigit); + else + *pbyResult = (BYTE)(MC_A + uDigit - 10); + pbyResult++; + } + *pbyResult = 0; +} + +void CVTvStr12ToBy6(const PCTSTR pszSrc, PBYTE pbyEtherAddr) +{ + int ii; + PBYTE pbySrc = (PBYTE)pszSrc; + + /* before conversion, make it all uppercase */ + /* strupr((PTSTR)pbySrc); */ + + for (ii = 0; ii < 6; ii++) { + /* each time we convert two digits to one byte */ + + /* the 16^^1 portion */ + if (MC_0 <= *pbySrc && *pbySrc <= MC_9) + pbyEtherAddr[ii] = (BYTE)((*pbySrc - MC_0) * 16); + else + pbyEtherAddr[ii] = (BYTE)((*pbySrc - MC_A + 10) * 16); + pbySrc++; + + /* the 16^^0 portion */ + if (MC_0 <= *pbySrc && *pbySrc <= MC_9) + pbyEtherAddr[ii] += (BYTE)(*pbySrc - MC_0); + else + pbyEtherAddr[ii] += (BYTE)(*pbySrc - MC_A + 10); + pbySrc++; + } +} + +/* + * Description: + * + * Parameters: + * + */ +void CVTvHexToAsc(PBYTE pbyValue, const PTSTR pszResult, UINT cbByte) +{ + int ii; + UINT uDigit; + PBYTE pbyResult = (PBYTE)pszResult; + + + for (ii = cbByte - 1; ii >= 0; ii--) { + /* each time we convert one byte to two digits */ + + /* the 16^^1 portion */ + uDigit = pbyValue[ii] / 16; + + if (uDigit < 10) + *pbyResult = (BYTE)(MC_0 + uDigit); + else + *pbyResult = (BYTE)(MC_A + uDigit - 10); + pbyResult++; + + /* the 16^^0 portion */ + uDigit = pbyValue[ii] % 16; + if (uDigit < 10) + *pbyResult = (BYTE)(MC_0 + uDigit); + else + *pbyResult = (BYTE)(MC_A + uDigit - 10); + pbyResult++; + } + *pbyResult = 0; +} + +/* + * Description: + * + * Parameters: + * + */ +void CVTvAscToHex(const PCTSTR pszSrc, PBYTE pbyValue, UINT cbByte) +{ + int ii; + PBYTE pbySrc = (PBYTE)pszSrc; + PBYTE pbyHi2Lo; + UINT cbDigit; + UINT cbAscByte; + + /* before conversion, make it all uppercase */ + /* strupr((PTSTR)pbySrc); */ + /* conversion from highest byte to lowerest byte */ + pbyHi2Lo = pbyValue + cbByte - 1; + + cbDigit = _tcslen((PTSTR)pbySrc); + + /* # of bytes is (# of hex digits + 1) / 2 */ + cbAscByte = (cbDigit + 1) / 2; + + /* pre padding zero */ + if (cbByte > cbAscByte) { + for (ii = 0; ii < (cbByte - cbAscByte); ii++) { + *pbyHi2Lo = 0; + pbyHi2Lo--; + } + } else { + /* if # of bytes of ascii string is greater than cbByte, */ + /* only cbByte will be done */ + cbAscByte = cbByte; + } + + /* pre padding half byte */ + if ((cbDigit % 2) != 0) { + if (MC_0 <= *pbySrc && *pbySrc <= MC_9) + *pbyHi2Lo = (BYTE)(*pbySrc - MC_0); + else + *pbyHi2Lo = (BYTE)(*pbySrc - MC_A + 10); + pbySrc++; + pbyHi2Lo--; + /* # of bytes we want to do should minus 1 */ + cbAscByte--; + } + + for (ii = 0; (ii < cbAscByte) && (pbySrc != _T('\0')); ii++) { + if (MC_0 <= *pbySrc && *pbySrc <= MC_9) + *pbyHi2Lo = (BYTE)((*pbySrc - MC_0) * 16); + else + *pbyHi2Lo = (BYTE)((*pbySrc - MC_A + 10) * 16); + pbySrc++; + + if (MC_0 <= *pbySrc && *pbySrc <= MC_9) + *pbyHi2Lo += (BYTE)(*pbySrc - MC_0); + else + *pbyHi2Lo += (BYTE)(*pbySrc - MC_A + 10); + pbySrc++; + pbyHi2Lo--; + } +} + +void CVTvIP4ToStr15(PBYTE pbyIPAddr, const PTSTR pszResult) +{ + int ii; + BYTE uNetAddr; + TCHAR IPStr[4]; + PTSTR pbyResult = pszResult; + + for (ii = 0; ii < 4; ii++) { + uNetAddr = pbyIPAddr[ii]; + + if (uNetAddr < 0x0A) { + /* pad two '0' if lower than 10 */ + strncpy(pbyResult, "00", 2); + strncpy(pbyResult+2, IPStr, 1); + } else if (uNetAddr < 0x064) { + /* pad '0' if lower than 100 */ + strncpy(pbyResult, "0", 1); + strncpy(pbyResult+1, IPStr, 2); + } else { + /* if > 100 , no padding needs to be performed */ + strncpy(pbyResult, IPStr, 3); + } + + pbyResult += 3; + if (ii == 3) + break; + *pbyResult = '.'; + pbyResult++; + } + + *pbyResult = '\0'; +} + +void CVTvStr15ToIP4(const PCTSTR pszSrc, PBYTE pbyIPAddr) +{ + int ii, jj; + PBYTE pbySrc = (PBYTE)pszSrc; + TCHAR IPStr[16]; + PBYTE pbyIPStr = (PBYTE)IPStr; + + ii = 0; + while (TRUE) { + /* reset digit counter */ + jj = 0; + pbyIPStr = (PBYTE)IPStr; + while ((*pbySrc != '.') && (*pbySrc != '\0')) { + *pbyIPStr = *pbySrc; + pbyIPStr++; + pbySrc++; + jj++; + } + + *pbyIPStr = '\0'; + if (jj > 3) + /* more than 3 digits */ + pbyIPAddr[ii] = 0xFF; + else + /* pbyIPAddr[ii]=(BYTE)atoi(IPStr); */ + + if (*pbySrc == '\0') + break; + ii++; + pbySrc++; /* skip "." */ + } +} diff --git a/cpu/arm920t/wmt/tconvert.h b/cpu/arm920t/wmt/tconvert.h new file mode 100755 index 0000000..db638f6 --- /dev/null +++ b/cpu/arm920t/wmt/tconvert.h @@ -0,0 +1,55 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __TCONVERT_H__ +#define __TCONVERT_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TTCHAR_H__) +#include "ttchar.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +void CVTvBy6ToStr12(PBYTE pbyEtherAddr, const PTSTR pszResult); +void CVTvStr12ToBy6(const PCTSTR pszSrc, PBYTE pbyEtherAddr); +void CVTvHexToAsc(PBYTE pbyValue, const PTSTR pszResult, UINT cbByte); +void CVTvAscToHex(const PCTSTR pszSrc, PBYTE pbyValue, UINT cbByte); +void CVTvIP4ToStr15(PBYTE pbyIPAddr, const PTSTR pszResult); +void CVTvStr15ToIP4(const PCTSTR pszSrc, PBYTE pbyIPAddr); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __TCONVERT_H__ */ diff --git a/cpu/arm920t/wmt/tcrc.c b/cpu/arm920t/wmt/tcrc.c new file mode 100755 index 0000000..718e217 --- /dev/null +++ b/cpu/arm920t/wmt/tcrc.c @@ -0,0 +1,139 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +/* 32-bit CRC table */ +static const DWORD s_adwCrc32Table[256] = { + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, + 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, + 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, + 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, + 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, + 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, + 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, + 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, + 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, + 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, + 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, + 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, + 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, + 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, + 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, + 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, + 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, + 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, + 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, + 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, + 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, + 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, + 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, + 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, + 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, + 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, + 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, + 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, + 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, + 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, + 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, + 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, + 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, + 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, + 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, + 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, + 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, + 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, + 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, + 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, + 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, + 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, + 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, + 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, + 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, + 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, + 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL +}; + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +DWORD +CRCdwCrc32( + PBYTE pbyData, + UINT cbByte, + DWORD dwCrcSeed + ) +{ + DWORD dwCrc; + + dwCrc = dwCrcSeed; + while (cbByte--) { + dwCrc = s_adwCrc32Table[(BYTE)((dwCrc ^ (*pbyData)) & 0xFF)] ^ (dwCrc >> 8); + pbyData++; + } + + return dwCrc; +} + +DWORD +CRCdwGetCrc32( + PBYTE pbyData, + UINT cbByte + ) +{ + return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL); +} + +DWORD +CRCdwGetCrc32Ex( + PBYTE pbyData, + UINT cbByte, + DWORD dwPreCRC + ) +{ + return CRCdwCrc32(pbyData, cbByte, dwPreCRC); +} diff --git a/cpu/arm920t/wmt/tcrc.h b/cpu/arm920t/wmt/tcrc.h new file mode 100755 index 0000000..9f3d4a5 --- /dev/null +++ b/cpu/arm920t/wmt/tcrc.h @@ -0,0 +1,57 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __TCRC_H__ +#define __TCRC_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +DWORD CRCdwCrc32(PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed); +DWORD CRCdwGetCrc32(PBYTE pbyData, UINT cbByte); +DWORD CRCdwGetCrc32Ex(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC); + +/* +DWORD CRCdwCrc(PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed); +DWORD CRCdwGetCrc(PBYTE pbyData, UINT cbByte); +DWORD CRCdwGetCrcEx(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC); +*/ + +WORD CRCwCrc16(WORD wCRC, BYTE *cp, int len); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __TCRC_H__ */ diff --git a/cpu/arm920t/wmt/tether.h b/cpu/arm920t/wmt/tether.h new file mode 100755 index 0000000..fdae4e4 --- /dev/null +++ b/cpu/arm920t/wmt/tether.h @@ -0,0 +1,188 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __TETHER_H__ +#define __TETHER_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +/* + * constants + */ +#define U_ETHER_ADDR_LEN 6 /* Ethernet address length */ +#define U_TYPE_LEN 2 +#define U_CRC_LEN 4 +#define U_HEADER_LEN (U_ETHER_ADDR_LEN * 2 + U_TYPE_LEN) +#define U_ETHER_ADDR_STR_LEN (U_ETHER_ADDR_LEN * 2 + 1) /* Ethernet address string length */ +#define MIN_DATA_LEN 46 /* min data length */ +#define MAX_DATA_LEN 1500 /* max data length */ + +#define MIN_PACKET_LEN (MIN_DATA_LEN + U_HEADER_LEN) /* 60, min total packet length (tx) */ +#define MAX_PACKET_LEN (MAX_DATA_LEN + U_HEADER_LEN) /* 1514, max total packet length (tx) */ +#define MAX_JUMBO_PKT_LEN 9040 + +#define MAX_LOOKAHEAD_SIZE MAX_PACKET_LEN + +#define U_MULTI_ADDR_LEN 8 /* multicast address length */ + +/* + * wType field in the SEthernetHeader + * + * NOTE.... + * in network byte order, high byte is going first + */ +#define TYPE_PKT_IP 0x0008 +#define TYPE_PKT_ARP 0x0608 +#define TYPE_PKT_RARP 0x3580 +#define TYPE_PKT_IPX 0x3781 + +#define TYPE_PKT_PING_M_REQ 0x1180 /* master reguest */ +#define TYPE_PKT_PING_S_GNT 0x2280 /* slave grant */ +#define TYPE_PKT_PING_M 0x7780 /* pingpong master packet */ +#define TYPE_PKT_PING_S 0x8880 /* pingpong slave packet */ +#define TYPE_PKT_DISCONN_M 0x9980 /* pingpong master disconnect packet */ +#define TYPE_PKT_WOL_M_REQ 0x3380 /* WOL waker request */ +#define TYPE_PKT_WOL_S_GNT 0x4480 /* WOL sleeper grant */ + +/* + * wFrameCtl field in the S802_11Header + * + * NOTE.... + * in network byte order, high byte is going first + */ + +#define FC_TODS 0x0100 +#define FC_FROMDS 0x0200 +#define FC_MOREFRAG 0x0400 +#define FC_RETRY 0x0800 +#define TYPE_802_11_DATA 0x0008 +#define TYPE_802_11_MASK 0x000C +#define TYPE_802_11_RTS 0x00B4 + +#define TYPE_802_11_CONTROL 0x0004 +#define TYPE_802_11_MGMT 0x0000 + +#define U_WMAC_HEADER_LEN 24 +/*--------------------- Export Types ------------------------------*/ + +/* + * Ethernet packet + */ +typedef struct tagSEthernetHeader { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wType; +} SEthernetHeader, DEF * PSEthernetHeader; + +/* + * 802_3 packet + */ +typedef struct tagS802_3Header { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wLen; +} S802_3Header, DEF * PS802_3Header; + +typedef struct tagS802_2LCCHeader { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wLen; + BYTE byDSAP; + BYTE bySSAP; + BYTE byCtrl; +} S802_2LCCHeader, DEF * PS802_2LCCHeader; + +typedef struct tagS802_3SNAPHeader { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wLen; + BYTE byDSAP; + BYTE bySSAP; + BYTE byCtrl; + BYTE Org[3]; + WORD wType; +} S802_2SNAPHeader, DEF * PS802_2SNAPHeader; + +typedef struct tagMACCtrlFrameHeader { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wType; + WORD wOpCode; + WORD wPauseTimer; + BYTE abyReserved[42]; +} SMACCtrlFrameHeader, DEF * PSMACCtrlFrameHeader; + +/* + * 802_11 packet + */ +typedef struct tagS802_11Header { + WORD wFrameCtl; + WORD wDurationID; + BYTE abyAddr1[U_ETHER_ADDR_LEN]; + BYTE abyAddr2[U_ETHER_ADDR_LEN]; + BYTE abyAddr3[U_ETHER_ADDR_LEN]; + WORD wSeqCtl; +#ifdef DS2DS + BYTE abyAddr4[U_ETHER_ADDR_LEN]; +#endif + DWORD dwIV; +} S802_11Header, DEF * PS802_11Header; + +/*--------------------- Export Macros ------------------------------*/ +/* Frame type macro */ + +#define IS_MULTICAST_ADDRESS(pbyEtherAddr) \ + ((*(PBYTE)(pbyEtherAddr) & 0x01) == 1) + +#define IS_BROADCAST_ADDRESS(pbyEtherAddr) ( \ + (*(PDWORD)(pbyEtherAddr) == 0xFFFFFFFFL) && \ + (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0xFFFF) \ +) + +#define IS_NULL_ADDRESS(pbyEtherAddr) ( \ + (*(PDWORD)(pbyEtherAddr) == 0L) && \ + (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0) \ +) + +#define IS_ETH_ADDRESS_EQUAL(pbyAddr1, pbyAddr2) ( \ + (*(PDWORD)(pbyAddr1) == *(PDWORD)(pbyAddr2)) && \ + (*(PWORD)((PBYTE)(pbyAddr1) + 4) == \ + *(PWORD)((PBYTE)(pbyAddr2) + 4)) \ +) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr); +/* BYTE ETHbyGetHashIndexByCrc(PBYTE pbyMultiAddr); */ +BOOL ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, UINT cbFrameLength); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __TETHER_H__ */ diff --git a/cpu/arm920t/wmt/tmacro.h b/cpu/arm920t/wmt/tmacro.h new file mode 100755 index 0000000..23755c1 --- /dev/null +++ b/cpu/arm920t/wmt/tmacro.h @@ -0,0 +1,133 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __TMACRO_H__ +#define __TMACRO_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/****** Common helper macros ***********************************************/ + +#if !defined(LONIBBLE) +#define LONIBBLE(b) ((BYTE)(b) & 0x0F) +#endif +#if !defined(HINIBBLE) +#define HINIBBLE(b) ((BYTE)(((WORD)(b) >> 4) & 0x0F)) +#endif + +#if !defined(LOBYTE) +#define LOBYTE(w) ((BYTE)(w)) +#endif +#if !defined(HIBYTE) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) +#endif + +#if !defined(LOWORD) +#define LOWORD(d) ((WORD)(d)) +#endif +#if !defined(HIWORD) +#define HIWORD(d) ((WORD)((((DWORD)(d)) >> 16) & 0xFFFF)) +#endif + +#define LODWORD(q) ((q).u.dwLowDword) +#define HIDWORD(q) ((q).u.dwHighDword) + +#define MAKEBYTE(ln, hn) ((BYTE)(((BYTE)(ln) & 0x0F) | ((BYTE)(hn) << 4))) +#if !defined(MAKEWORD) +#define MAKEWORD(lb, hb) ((WORD)(((BYTE)(lb)) | (((WORD)((BYTE)(hb))) << 8))) +#endif +#if !defined(MAKEDWORD) +#define MAKEDWORD(lw, hw) ((DWORD)(((WORD)(lw)) | (((DWORD)((WORD)(hw))) << 16))) +#endif +#define MAKEQWORD(ld, hd, pq) {pq->u.dwLowDword = ld; pq->u.dwHighDword = hd; } + +#if !defined(MAKELONG) +#define MAKELONG(low, high) ((LONG)(((WORD)(low)) | (((DWORD)((WORD)(high))) << 16))) +#endif + +#if !defined(REVDWORD) +#define REVDWORD(d) (MAKEDWORD(MAKEWORD(HIBYTE(HIWORD(d)), LOBYTE(HIWORD(d))), \ + MAKEWORD(HIBYTE(LOWORD(d)), LOBYTE(LOWORD(d))))) +#endif + +#ifndef NOMINMAX +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#endif /* NOMINMAX */ + +/****** Misc macros ********************************************************/ + +/* get the field offset in the type(struct, class, ...) */ +#define OFFSET(type, field) ((int)(&((type NEAR*)1)->field)-1) + +/* string equality shorthand */ +#define STR_EQ(x, y) (strcmp(x, y) == 0) +#define STR_NE(x, y) (strcmp(x, y) != 0) + + +/* calculate element # of array */ +#define ELEMENT_NUM(array) (sizeof(array) / sizeof(array[0])) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +/* null statement */ +#define NULL_FUNC() + +/* Since not all compilers support structure assignment, the ASSIGN() + * macro is used. This controls how it's actually implemented. + */ +#ifdef NOSTRUCTASSIGN /* Version for old compilers that don't support it */ +#define ASSIGN(a, b) memcpy((char *)&(a), (char *)&(b), sizeof(b); +#else /* Version for compilers that do */ +#define ASSIGN(a, b) ((a) = (b)) +#endif + +/* Wrap Around */ +#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) >= ((uModulo) - 1)) \ + (uVar) = 0; \ + else \ + (uVar)++; \ +} + +#define ADD_N_WITH_WRAP_AROUND(uVar, uNum, uModulo) { \ + if (((uVar) + (uNum)) > ((uModulo) - 1)) \ + (uVar) = (uVar) + (uNum) - (uModulo); \ + else \ + (uVar) += (uNum); \ +} + +#define SUB_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) <= 0) \ + (uVar) = ((uModulo) - 1); \ + else \ + (uVar)--; \ +} + +#if defined(__WATCOMC__) +#define RANDOM(_x_) (UINT)(((UINT)rand()*(_x_)) / (UINT)(RAND_MAX+1)) +#else +#define RANDOM(_x_) random(_x_) +#endif + +#endif /* __TMACRO_H__ */ diff --git a/cpu/arm920t/wmt/tmem.h b/cpu/arm920t/wmt/tmem.h new file mode 100755 index 0000000..dfe8315 --- /dev/null +++ b/cpu/arm920t/wmt/tmem.h @@ -0,0 +1,99 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +#include "gmacif.h" +#include "pcinet.h" + +/*--------------------- Export Definitions -------------------------*/ +/* memory allocation map from RAW(allocated) memory -> ALIGNED memory */ +typedef struct tagSAllocMap { + /* this dwRawSize value must assign */ + DWORD dwRawSize; /* allocated size of the memory block */ + DWORD dwRawVAddr; /* allocated virtual address of the memory block */ + QWORD qwRawPAddr; /* allocated physical address of the memory block */ + DWORD dwSize; /* aligned size (exactly) */ + DWORD dwVAddr; /* aligned virtual address */ + DWORD dwPAddr; /* aligned physical address */ + PVOID pvHandle; /* handle to do system-call */ +} SAllocMap, *PSAllocMap; + +#define malloc GMEMvAllocate +/* #define memset MEMvSet */ +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ +#define freemem() \ +{ \ + g_pvGBufferIndex = (PVOID)GMEMORY_BUFFER_START;\ + g_IO_point = PCI_base_addr; \ + g_Mem_point = PCI_base_addr+PCI_io_range ; \ +} +/*--------------------- Export Classes ----------------------------*/ +#define MEMvFree(a, b) +#define MEMvFreeShared(a) +#define free(a); +/*--------------------- Export Variables --------------------------*/ +extern PVOID g_pvGBufferIndex; +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +MEMvAlign( + PSAllocMap pamMem, + UINT uBoundary + ); + +PVOID +GMEMvAllocate( + UINT uCount + ); + +VOID +GMEMvAllocateShared( + PSAllocMap pamMem + ); + +VOID +MEMvCopy( + PVOID pvDst, + PVOID pvSrc, + UINT uCount + ); + +VOID +MEMvSet( + PVOID pvDst, + BYTE byPattern, + UINT uCount + ); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __MEM_H__ */ diff --git a/cpu/arm920t/wmt/tpci.h b/cpu/arm920t/wmt/tpci.h new file mode 100755 index 0000000..66a3100 --- /dev/null +++ b/cpu/arm920t/wmt/tpci.h @@ -0,0 +1,94 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __TPCI_H__ +#define __TPCI_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define MAX_PCI_BUS 256 /* max. # of PCI bus that we support */ +#define MAX_PCI_DEVICE 32 /* max. # of PCI devices */ + +/* + * Registers in the PCI configuration space + */ +#define PCI_REG_VENDOR_ID 0x00 +#define PCI_REG_DEVICE_ID 0x02 +#define PCI_REG_COMMAND 0x04 +#define PCI_REG_STATUS 0x06 +#define PCI_REG_REV_ID 0x08 +#define PCI_REG_CLASS_CODE 0x09 +#define PCI_REG_CACHELINE_SIZE 0x0C +#define PCI_REG_LAT_TIMER 0x0D +#define PCI_REG_HDR_TYPE 0x0E +#define PCI_REG_BIST 0x0F + +#define PCI_REG_BAR0 0x10 +#define PCI_REG_BAR1 0x14 +#define PCI_REG_BAR2 0x18 +#define PCI_REG_CARDBUS_CIS_PTR 0x28 + +#define PCI_REG_SUB_VEN_ID 0x2C +#define PCI_REG_SUB_SYS_ID 0x2E +#define PCI_REG_EXP_ROM_BAR 0x30 +#define PCI_REG_CAP 0x34 + +#define PCI_REG_INT_LINE 0x3C +#define PCI_REG_INT_PIN 0x3D +#define PCI_REG_MIN_GNT 0x3E +#define PCI_REG_MAX_LAT 0x3F + +#define PCI_REG_MAX_SIZE 0x100 /* maximun total PCI registers */ + +/* added by kevin */ +#define PCI_base_addr 0xc0000000 +#define PCI_io_range 0x10000 +#define PCI_memory_range 0x400000 +#define PCI_io_page 0x100 /* 256 byte */ +#define PCI_memory_page 0x1000 /* 4k */ +#define PCI_invalid 0xffffffff +#define PCI_IO_ENABLE 0x1 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/* macro MAKE Bus Dev Fun ID into WORD */ +#define MAKE_BDF_TO_WORD(byBusId, byDevId, byFunId) \ + MAKEWORD(((((BYTE)(byDevId)) & 0x1F) << 3) + (((BYTE)(byFunId)) & 0x07), (byBusId)) + +#define GET_BUSID(wBusDevFunId) \ + HIBYTE(wBusDevFunId) + +#define GET_DEVID(wBusDevFunId) \ + (LOBYTE(wBusDevFunId) >> 3) + +#define GET_FUNID(wBusDevFunId) \ + (LOBYTE(wBusDevFunId) & 0x07) + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __TPCI_H__ */ diff --git a/cpu/arm920t/wmt/ttchar.h b/cpu/arm920t/wmt/ttchar.h new file mode 100755 index 0000000..3265227 --- /dev/null +++ b/cpu/arm920t/wmt/ttchar.h @@ -0,0 +1,245 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __TTCHAR_H__ +#define __TTCHAR_H__ + +#include <stddef.h> + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/* + * UNICODE (Wide Character) types + */ +typedef wchar_t WCHAR; /* wc, 16-bit UNICODE character */ + +typedef WCHAR * PWCHAR; + +typedef WCHAR * PWCH; +typedef WCHAR * LPWCH; +typedef CONST WCHAR * PCWCH; +typedef CONST WCHAR * LPCWCH; + +typedef WCHAR * PWSTR; +typedef WCHAR * NWPSTR; +typedef WCHAR * LPWSTR; +typedef CONST WCHAR * PCWSTR; +typedef CONST WCHAR * LPCWSTR; + +/* + * ANSI (Multi-byte Character) types + */ +#ifdef _MBCS + +typedef CHAR * PCHAR; + +typedef CHAR * PCH; +typedef CHAR * LPCH; +typedef CONST CHAR * PCCH; +typedef CONST CHAR * LPCCH; + +typedef CHAR * PSTR; +typedef CHAR * NPSTR; +typedef CHAR * LPSTR; +typedef CONST CHAR * PCSTR; +typedef CONST CHAR * LPCSTR; + +#endif /* _MBCS */ + +/* + * Neutral ANSI(SBCS,MBCS)/UNICODE types and macros + */ +#ifdef _UNICODE + +#ifndef _TCHAR_DEFINED +typedef WCHAR TCHAR; +typedef WCHAR * PTCHAR; +typedef WCHAR TBYTE; +typedef WCHAR * PTBYTE; +#define _TCHAR_DEFINED +#endif /* !_TCHAR_DEFINED */ + +typedef LPWSTR PTCH; +typedef LPWSTR LPTCH; +typedef LPWSTR PTSTR; +typedef LPWSTR LPTSTR; +typedef LPCWSTR PCTSTR; +typedef LPCWSTR LPCTSTR; + +#define __TEXT(quote) L##quote + +/* String functions */ + +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcscpy wcscpy +#define _tcscspn wcscspn +#define _tcslen wcslen +#define _tcsncat wcsncat +#define _tcsncpy wcsncpy +#define _tcspbrk wcspbrk +#define _tcsrchr wcsrchr +#define _tcsspn wcsspn +#define _tcsstr wcsstr +#define _tcstok wcstok + +#define _tcsdup _wcsdup +#define _tcsnset _wcsnset +#define _tcsrev _wcsrev +#define _tcsset _wcsset + +#define _tcscmp wcscmp +#define _tcsicmp _wcsicmp +#define _tcsnccmp wcsncmp +#define _tcsncmp wcsncmp +#define _tcsncicmp _wcsnicmp +#define _tcsnicmp _wcsnicmp + +#define _tcscoll wcscoll +#define _tcsicoll _wcsicoll +#define _tcsnccoll _wcsncoll +#define _tcsncoll _wcsncoll +#define _tcsncicoll _wcsnicoll +#define _tcsnicoll _wcsnicoll + +/* ctype functions */ + +#define _istalnum iswalnum +#define _istalpha iswalpha +#define _istascii iswascii +#define _istcntrl iswcntrl +#define _istdigit iswdigit +#define _istgraph iswgraph +#define _istlower iswlower +#define _istprint iswprint +#define _istpunct iswpunct +#define _istspace iswspace +#define _istupper iswupper +#define _istxdigit iswxdigit + +#define _totupper towupper +#define _totlower towlower + +#else /* !_UNICODE */ + +/* ++++++++++++++++++++ SBCS and MBCS ++++++++++++++++++++ */ + +#ifdef _MBCS +/* ++++++++++++++++++++ MBCS ++++++++++++++++++++ */ +/* there are no definitons here, now. */ +/* TBD.... */ + +#else /* !_MBCS */ + +/* ++++++++++++++++++++ SBCS ++++++++++++++++++++ */ + +#ifndef _TCHAR_DEFINED +typedef char TCHAR; +typedef char *PTCHAR; +typedef unsigned char TBYTE; +typedef unsigned char *PTBYTE; +#define _TCHAR_DEFINED +#endif /* !_TCHAR_DEFINED */ + +typedef PCH PTCH; +typedef LPCH LPTCH; +typedef PSTR PTSTR; +typedef LPSTR LPTSTR; +typedef PCSTR PCTSTR; +typedef LPCSTR LPCTSTR; + +#define __TEXT(quote) quote + +/* String functions */ + +#define _tcscat strcat +#define _tcscpy strcpy +#define _tcslen strlen +#define _tcsxfrm strxfrm +#define _tcsdup _strdup + +/* String functions */ + +#define _tcschr strchr +#define _tcscspn strcspn +#define _tcsncat strncat +#define _tcsncpy strncpy +#define _tcspbrk strpbrk +#define _tcsrchr strrchr +#define _tcsspn strspn +#define _tcsstr strstr +#define _tcstok strtok + +#define _tcsnset _strnset +#define _tcsrev _strrev +#define _tcsset _strset + +#define _tcscmp strcmp +#define _tcsicmp _stricmp +#define _tcsnccmp strncmp +#define _tcsncmp strncmp +#define _tcsncicmp _strnicmp +#define _tcsnicmp _strnicmp + +#define _tcscoll strcoll +#define _tcsicoll _stricoll +#define _tcsnccoll _strncoll +#define _tcsncoll _strncoll +#define _tcsncicoll _strnicoll +#define _tcsnicoll _strnicoll + +/* ctype functions */ + +#define _istascii isascii +#define _istcntrl iscntrl +#define _istxdigit isxdigit + +/* ctype functions */ + +#define _istalnum isalnum +#define _istalpha isalpha +#define _istdigit isdigit +#define _istgraph isgraph +#define _istlower islower +#define _istprint isprint +#define _istpunct ispunct +#define _istspace isspace +#define _istupper isupper + +#define _totupper toupper +#define _totlower tolower + +#endif /* !_MBCS */ + +#endif /* !_UNICODE */ + +/* Generic text macros to be used with string literals and character constants. + Will also allow symbolic constants that resolve to same. */ +#define _T(x) __TEXT(x) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __TTCHAR_H__ */ diff --git a/cpu/arm920t/wmt/ttype.h b/cpu/arm920t/wmt/ttype.h new file mode 100755 index 0000000..68ea47c --- /dev/null +++ b/cpu/arm920t/wmt/ttype.h @@ -0,0 +1,181 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <common.h> +#ifndef __TTYPE_H__ +#define __TTYPE_H__ + +/******* Common definitions and typedefs ***********************************/ +#ifndef VOID +#define VOID void +#endif + +#ifndef CONST +#define CONST const +#endif + +#ifndef STATIC +#define STATIC static +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(SUCCESS) +#define SUCCESS 0 +#endif +#if !defined(FAILED) +#define FAILED -1 +#endif + +typedef int BOOL; + +/****** Simple typedefs ***************************************************/ +typedef char CHAR; +typedef signed short SHORT; +typedef signed int INT; +typedef signed long LONG; + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; + +#ifndef BYTE +#define BYTE unsigned char +#endif + +#ifndef WORD +#define WORD unsigned short +#endif + +#ifndef DWORD +#define DWORD unsigned long +#endif + +/* QWORD is for those situation that we want */ +/* an 8-byte-aligned 8 byte long structure */ +/* which is NOT really a floating point number. */ +typedef union tagUQuadWord { + struct { + DWORD dwLowDword; + DWORD dwHighDword; + } u; + double DoNotUseThisField; +} UQuadWord; +typedef UQuadWord QWORD; /* 64-bit */ + +#define U8 unsigned char +#define U16 unsigned short +#define USHORT unsigned short +#define UINT unsigned int + +/* flat memory model */ +#if !defined(FAR) +#define FAR +#endif +#if !defined(NEAR) +#define NEAR +#endif +#if !defined(DEF) +#define DEF +#endif +#if !defined(CALLBACK) +#define CALLBACK +#endif + +/****** Common pointer types ***********************************************/ +typedef signed char *PI8; +typedef signed short *PI16; +typedef signed long *PI32; + +typedef unsigned char *PU8; +typedef unsigned short *PU16; +typedef unsigned long *PU32; + +/* boolean pointer */ +typedef int *PBOOL; + +typedef int *PINT; +typedef const int *PCINT; + +typedef unsigned int *PUINT; +typedef const unsigned int *PCUINT; + +typedef long *PLONG; + +typedef BYTE * PBYTE; +typedef const BYTE * PCBYTE; + +typedef WORD * PWORD; +typedef const WORD * PCWORD; + +typedef DWORD *PDWORD; +typedef const DWORD *PCDWORD; + +typedef QWORD * PQWORD; +typedef const QWORD * PCQWORD; + +/* typedef void *PVOID; */ +typedef void DEF * PVOID; +typedef void NEAR * NPVOID; +typedef void FAR * LPVOID; + +/* + * ANSI (Single-byte Character) types + */ +typedef char DEF * PCH; +typedef char NEAR * NPCH; +typedef char FAR * LPCH; +typedef const char DEF * PCCH; +typedef const char NEAR * NPCCH; +typedef const char FAR * LPCCH; + +typedef char DEF * PSTR; +typedef char NEAR * NPSTR; +typedef char FAR * LPSTR; +typedef const char DEF * PCSTR; +typedef const char NEAR * NPCSTR; +typedef const char FAR * LPCSTR; + +/* +typedef char *PCH; +typedef const char *PCCH; + +typedef char *PSTR; +typedef const char *PCSTR; +*/ + +/****** Misc definitions, types ********************************************/ + +/* parameter prefix */ +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +typedef void *HANDLE; +#define MAX_NET_DEVICE 4 + +#endif /* __TTYPE_H__ */ diff --git a/cpu/arm920t/wmt/uart.h b/cpu/arm920t/wmt/uart.h new file mode 100755 index 0000000..52ad0f3 --- /dev/null +++ b/cpu/arm920t/wmt/uart.h @@ -0,0 +1,290 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * Copyright (c) 2008 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +#ifndef __UART_H_ +#define __UART_H_ + +typedef struct _UART_REG_ { + volatile unsigned long URTDR; /* Transmit data register */ + volatile unsigned long URRDR; /* Receive data register */ + volatile unsigned long URDIV; /* UART clock divisor & Bard rate divisor */ + volatile unsigned long URLCR; /* Line control register */ + volatile unsigned long URICR; /* IrDA control register */ + volatile unsigned long URIER; /* Interrupt enable register */ + volatile unsigned long URISR; /* Interrupt status register */ + volatile unsigned long URUSR; /* Status register */ + volatile unsigned long URFCR; /* Fifo control register */ + volatile unsigned long URFIDX; /* Fifo index register */ + volatile unsigned long URBKR; /* Break signal count value register */ + volatile unsigned long URTOD; /* UART time out divisor register */ + volatile unsigned long Resv30_FFF[0x3F4]; /* 0x0030 - 0x0FFF Reserved */ + volatile unsigned char TXFifo[32]; /* 0x1000 - 0x101F 16x8 bit asynchronous Fifo */ + volatile unsigned char RXFifo[32]; /* 0x1020 - 0x103F 16x10 bit asynchronous Fifo */ +} UART_REG, *PUART_REG; + +/* + * (URRDR) Receive Data Regiser Description + */ +#define URRDR_PER 0x100 /* Parity Error. This bit is the same as URISR[8] */ +#define URRDR_FER 0x200 /* Frame Error. This bit is the same as URISR[9] */ + +/* + * (URLCR) UART Line Control Register Description + */ +#define URLCR_TXEN 0x1 /* Transmit Enable */ +#define URLCR_RXEN 0x2 /* Receive Enable */ +#define URLCR_DLEN8B 0x4 /* Data length 8 bit mode enable */ +#define URLCR_STBLEN2b 0x8 /* 2 Stop bit enable */ +#define URLCR_PYTEN 0x10 /* Parity Enable */ +#define URLCR_PTYODD 0x20 /* Even Parity mode selected */ +#define URLCR_RTS 0x40 /* Request To Send. */ +/* Software control RTS modem signal, used when IrDA is disabled. */ +#define URLCR_LPBEN 0x80 /* Loop Back enable */ +#define URLCR_DMAEN 0x100 /* DMA enable */ +/* 0 : Disable DMA mode */ +/* 1 : Enable UART DMA mode. The UART must be configured in Fifo mode */ +/* if DMA is enabled. */ +#define URLCR_BKINIT 0x200 /* BlueTooth break signal initiation */ +#define URLCR_PSLVERR 0x400 /* Enable APB interface Error Response */ + +/* + * (URICR) IrDA Control Register Description + */ +#define URICR_IREN 0x1 /* Infrared Enable */ + +/* + * (URIER) UART Interrupt Enable Register Description + */ +#define URIER_TXDE 0x1 /* Enable TX Data Register Empty Interrupt */ +#define URIER_RXDF 0x2 /* Enable RX Data Register Full Interrupt */ +#define URIER_TXFAE 0x4 /* Enable TX Fifo Almost Empty Interrupt(Threshold) */ +#define URIER_TXFE 0x8 /* Enable TX Fifo Empty Interrupt */ +#define URIER_RXFAF 0x10 /* Enable Rx Fifo Almost Full Interrupt(Threshold) */ +#define URIER_RXFF 0x20 /* Enable Rx Fifo Full Interrupt */ +#define URIER_TXDUDR 0x40 /* Enable for TX Under Run Interrupt */ +#define URIER_RXDOVER 0x80 /* Enable for Rx Over Run Interrupt */ +#define URIER_PER 0x100 /* Enable for Parity Error Interrupt */ +#define URIER_FER 0x200 /* Enable for Frame Error Interrupt */ +#define URIER_MODM 0x400 /* Enable for Modem control signal - CTS interrupt */ +#define URIER_RXTOUT 0x800 /* Enable for Receive TimeOut Interrupt */ +#define URIER_BK 0x1000 /* Enable for Break Signal Done Interrupt */ +#define URIER_ERR 0x2000 /* Enable for APB Error Respone Interrupt */ + +/* + * (URISR) UART Interrupt Status Register Description + */ +#define URISR_TXDE 0x1 /* TX Data Register Empty */ +#define URISR_RXDF 0x2 /* RX Data Register Full */ +#define URISR_TXFAE 0x4 /* TX Fifo Almost Empty(Threshold) */ +#define URISR_TXFE 0x8 /* TX Fifo Empty */ +#define URISR_RXFAF 0x10 /* Rx Fifo Almost Full (Threshold) */ +#define URISR_RXFF 0x20 /* Rx Fifo Full */ +#define URISR_TXDUDR 0x40 /* TX Under Run */ +#define URISR_RXDOVER 0x80 /* Rx Over Run */ +#define URISR_PER 0x100 /* Parity Error */ +#define URISR_FER 0x200 /* Frame Error */ +#define URISR_MODM 0x400 /* Modem control signal */ +#define URISR_RXTOUT 0x800 /* Receive TimeOut */ +#define URISR_BK 0x1000 /* Break Signal Done */ +#define URISR_ERR 0x2000 /* APB Error Respone */ + +/* + * (URUSR) UART Status Register Description + */ +#define URUSR_TXON 0x1 /* Transmitter On */ +#define URUSR_TXDBSY 0x2 /* Transmitter Busy */ +#define URUSR_RXON 0x4 /* Receiver On */ +#define URUSR_RXDRDY 0x8 /* Receiver Ready */ +#define URUSR_CTS 0x10 /* Clear To Send Current status of CTS signal */ + +/* + * (URFCR) UART Fifo Control Register Description + */ +#define URFCR_FIFOEN 0x1 /* Fifo Enable */ +#define URFCR_TRAIL 0x2 /* RX Fifo Trailing data flush */ +#define URFCR_TXFRST 0x4 /* TX Fifo Reset */ +#define URFCR_RXFRST 0x8 /* Rx Fifo Reset */ +#define URFCR_TXFLV_0 0x0000 +#define URFCR_TXFLV_1 0x0010 +#define URFCR_TXFLV_2 0x0020 +#define URFCR_TXFLV_3 0x0030 +#define URFCR_TXFLV_4 0x0040 +#define URFCR_TXFLV_5 0x0050 +#define URFCR_TXFLV_6 0x0060 +#define URFCR_TXFLV_7 0x0070 +#define URFCR_TXFLV_8 0x0080 +#define URFCR_TXFLV_9 0x0090 +#define URFCR_TXFLV_10 0x00A0 +#define URFCR_TXFLV_11 0x00B0 +#define URFCR_TXFLV_12 0x00C0 +#define URFCR_TXFLV_13 0x00D0 +#define URFCR_TXFLV_14 0x00E0 +#define URFCR_TXFLV_15 0x00F0 +#define UFFCR_RXFLV_0 0x0000 +#define UFFCR_RXFLV_1 0x0100 +#define UFFCR_RXFLV_2 0x0200 +#define UFFCR_RXFLV_3 0x0300 +#define UFFCR_RXFLV_4 0x0400 +#define UFFCR_RXFLV_5 0x0500 +#define UFFCR_RXFLV_6 0x0600 +#define UFFCR_RXFLV_7 0x0700 +#define UFFCR_RXFLV_8 0x0800 +#define UFFCR_RXFLV_9 0x0900 +#define UFFCR_RXFLV_10 0x0A00 +#define UFFCR_RXFLV_11 0x0B00 +#define UFFCR_RXFLV_12 0x0C00 +#define UFFCR_RXFLV_13 0x0D00 +#define UFFCR_RXFLV_14 0x0E00 +#define UFFCR_RXFLV_15 0x0F00 + +/* + * UART Controller Constant Definition + */ +#define UART_BR_921K6 0x10000 /* Uart Baud Rate Setting into 921.6KHz */ +#define UART_BR_460K8 0x10001 /* Uart Baud Rate Setting into 468.8KHz */ +#define UART_BR_230K4 0x10003 /* Uart Baud Rate Setting into 230.4KHz */ +#define UART_BR_115K2 0x10007 /* Uart Baud Rate Setting into 115.2KHz */ +#define UART_BR_57K6 0x1000F /* Uart Baud Rate Setting into 57.6KHz */ +#define UART_BR_38K4 0x2000F /* Uart Baud Rate Setting into 38.4KHz */ +#define UART_BR_28K8 0x1001F /* Uart Baud Rate Setting into 28.8KHz */ +#define UART_BR_19K2 0x2001F /* Uart Baud Rate Setting into 19.2KHz */ +#define UART_BR_14K4 0x1003F /* Uart Baud Rate Setting into 14.4KHz */ +#define UART_BR_9K6 0x2003F /* Uart Baud Rate Setting into 9.6KHz */ +#define UART_BR_7K2 0x1007F /* Uart Baud Rate Setting into 7.2KHz */ +#define UART_BR_3K6 0x100FF /* Uart Baud Rate Setting into 3.6KHz */ + +#define UART_BK_921K6 3775 /* Uart Break Signal Count Setting into 921.6KHz */ +#define UART_BK_460K8 1920 /* Uart Break Signal Count Setting into 468.8KHz */ +#define UART_BK_230K4 944 /* Uart Break Signal Count Setting into 230.4KHz */ +#define UART_BK_115K2 472 /* Uart Break Signal Count Setting into 115.2KHz */ +#define UART_BK_57K6 236 /* Uart Break Signal Count Setting into 57.6KHz */ +#define UART_BK_38K4 157 /* Uart Break Signal Count Setting into 38.4KHz */ +#define UART_BK_28K8 118 /* Uart Break Signal Count Setting into 28.8KHz */ +#define UART_BK_19K2 79 /* Uart Break Signal Count Setting into 19.2KHz */ +#define UART_BK_14K4 59 /* Uart Break Signal Count Setting into 14.4KHz */ +#define UART_BK_9K6 39 /* Uart Break Signal Count Setting into 9.6KHz */ +#define UART_BK_7K2 30 /* Uart Break Signal Count Setting into 7.2KHz */ +#define UART_BK_3K6 15 /* Uart Break Signal Count Setting into 3.6KHz */ + +#define BR_921K6 921600 /* 921.6KHz */ +#define BR_460K8 460800 /* 468.8KHz */ +#define BR_230K4 230400 /* 230.4KHz */ +#define BR_115K2 115200 /* 115.2KHz */ +#define BR_57K6 57600 /* 57.6KHz */ +#define BR_38K4 38400 /* 3.8.4KHz */ +#define BR_28K8 28800 /* 28.8KHz */ +#define BR_19K2 19200 /* 19.2KHz */ +#define BR_14K4 14400 /* 14.4KHz */ +#define BR_9K6 9600 /* 9.6KHz */ +#define BR_7K2 7200 /* 7.2KHz */ +#define BR_3K6 3600 /* 3.6KHz */ + +/* #define UART_CLK_SOURCE 24000000 */ + +/* + * UART Function Return Status Constant Definitions + */ +#define UR_SUCCESS 0x0 /* return success */ +#define UR_FAIL 0xFFFFFFFF /* return fail */ +#define UR_RXNOTRDY 0x2 /* return RX not Ready */ +#define UART0 0 +#define UART1 1 + +/* + * UART Public functions declaration + * + * Defined in uart.c + */ +ulong +init_uart( + uchar control_number, + ulong baud_rate + ); + +ulong +set_uart_DMA_mode( + uchar control_number + ); + +ulong +set_uart_fifo_mode( + uchar control_number + ); + +ulong +set_uart_reg_mode( + uchar control_number + ); + +ulong +get_ch_from_uart( + uchar control_number + ); + +ulong +write_ch_to_uart( + uchar control_number, + uchar ch + ); + +ulong +get_ch_from_uart_fifo( + uchar control_number + ); + +ulong +write_ch_to_uart_fifo( + uchar control_number, + uchar ch + ); + +ulong +uart_loopback_mode( + uchar control_number, + uchar enable + ); + +/* + * Defined in the uartif.c + */ +void +uart_initialization( + int FunctionNumber + ); + +void uart_startio(void); + +void +ugets( + char *p_dest, + int len + ); + +void +uputs( + char *str + ); + +void +uprintf( + char *format, ... + ); + +#endif /* __UART_H_ */ diff --git a/cpu/arm920t/wmt/uassert.h b/cpu/arm920t/wmt/uassert.h new file mode 100755 index 0000000..782704e --- /dev/null +++ b/cpu/arm920t/wmt/uassert.h @@ -0,0 +1,79 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __UASSERT_H__ +#define __UASSERT_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/* if not define _DEBUG, then DBG_ASSERT will be null */ +#ifndef _DEBUG +/* translate ASSERT(f) to empty space */ +#define DBG_ASSERT(f) +#define DBG_ASSERT_VALID(f) +#else /* _DEBUG */ +/* translate ASSERT(f) to c function call */ +#define DBG_ASSERT(f) +#define DBG_ASSERT_VALID(p) +#endif /* _DEBUG */ + +/* if (_DEBUG) then (_DEBUG_LOUD) */ +#ifndef _DEBUG +#define DBG_PRN(arg) +#else /* _DEBUG */ +#define _DEBUG_LOUD +#define DBG_PRN(arg) {DbgPrint("***** "); DbgPrint arg ; } +#endif /* _DEBUG */ + +#ifndef _DEBUG_LOUD +#define DBG_PRN_LOUD(arg) +#else /* _DEBUG_LOUD */ +#define DBG_PRN_LOUD(arg) {DbgPrint("##### "); DbgPrint arg ; } +#endif /* _DEBUG_LOUD */ + +#ifndef _DEBUG_PORT80 +#define DBG_IMM_PORT80(handle, value) +#define DBG_PORT80(value) +#else /* _DEBUG_PORT80 */ +#define DBG_IMM_PORT80(handle, value) NdisImmediateWritePortUchar(handle, 0x80, value); +#define DBG_PORT80(value) NdisRawWritePortUchar(0x80, value); +#endif /* _DEBUG_PORT80 */ + +#ifndef _DEBUG_PORT80_ALWAYS +#define DBG_PORT80_ALWAYS(value) +#else /* _DEBUG_PORT80_ALWAYS */ +#define DBG_PORT80_ALWAYS(value) NdisRawWritePortUchar(0x80, value); +#endif /* _DEBUG_PORT80_ALWAYS */ + +#ifndef _DEBUG_BREAK +#define DBG_BRK() +#else /* _DEBUG_BREAK */ +#define DBG_BRK() { ASM{ int 3 } } +#endif /* _DEBUG_BREAK */ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __UASSERT_H__ */ diff --git a/cpu/arm920t/wmt/upc.h b/cpu/arm920t/wmt/upc.h new file mode 100755 index 0000000..87373aa --- /dev/null +++ b/cpu/arm920t/wmt/upc.h @@ -0,0 +1,94 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __UPC_H__ +#define __UPC_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define INTERRUPT void +typedef INTERRUPT(*PISR)(void); +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#if defined(__cplusplus) +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +/* WMT Device do Memory-Mapped IO when in 32-bit environment */ +#define VNSvInPortB(dwIOAddress, pbyData) \ +do { \ + volatile BYTE *pbyAddr = ((PBYTE)(dwIOAddress)); \ + *(pbyData) = *pbyAddr; \ +} while (0) + +#define VNSvInPortW(dwIOAddress, pwData) \ +do { \ + volatile WORD *pwAddr = ((PWORD)(dwIOAddress)); \ + *(pwData) = *pwAddr; \ +} while (0) + +#define VNSvInPortD(dwIOAddress, pdwData) \ +do { \ + volatile DWORD *pdwAddr = ((PDWORD)(dwIOAddress)); \ + *(pdwData) = *pdwAddr; \ +} while (0) + +#define VNSvOutPortB(dwIOAddress, byData) \ +do { \ + volatile BYTE *pbyTmp = (PBYTE)(dwIOAddress); \ + *pbyTmp = (byData); \ +} while (0) + +#define VNSvOutPortW(dwIOAddress, wData) \ +do { \ + volatile WORD *pwTmp = (PWORD)(dwIOAddress); \ + *pwTmp = (wData); \ +} while (0) + +#define VNSvOutPortD(dwIOAddress, dwData) \ +do { \ + volatile DWORD *pdwTmp = (PDWORD)(dwIOAddress); \ + *pdwTmp = (dwData); \ +} while (0) + +#define PCAvDelayByIO(wDelayUnit) \ +do { \ + BYTE byTemp; \ + ULONG ii; \ + for (ii = 0; ii < (wDelayUnit); ii++) \ + VNSvInPortB(0x0, &byTemp); \ +} while (0) + +#define PCBvInPortB VNSvInPortB +#define PCBvInPortW VNSvInPortW +#define PCBvInPortD VNSvInPortD +#define PCBvOutPortB VNSvOutPortB +#define PCBvOutPortW VNSvOutPortW +#define PCBvOutPortD VNSvOutPortD + +#if defined(__cplusplus) +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __UPC_H__ */ diff --git a/cpu/arm920t/wmt/upci.h b/cpu/arm920t/wmt/upci.h new file mode 100755 index 0000000..7eb2e9a --- /dev/null +++ b/cpu/arm920t/wmt/upci.h @@ -0,0 +1,78 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __UPCI_H__ +#define __UPCI_H__ + +#if !defined(__UPCIX_H__) +#include "upcix.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +#define PCIvReadConfigB(pvHandle, wBusDevFunId, byRegOffset, pbyData) \ +{ \ + PCIXvReadB(wBusDevFunId, byRegOffset, pbyData); \ +} + +#define PCIvReadConfigW(pvHandle, wBusDevFunId, byRegOffset, pwData) \ +{ \ + PCIXvReadW(wBusDevFunId, byRegOffset, pwData); \ +} + +#define PCIvReadConfigD(pvHandle, wBusDevFunId, byRegOffset, pdwData) \ +{ \ + PCIXvReadD(wBusDevFunId, byRegOffset, pdwData); \ +} + +#define PCIvWriteConfigB(pvHandle, wBusDevFunId, byRegOffset, byData) \ +{ \ + PCIXvWriteB(wBusDevFunId, byRegOffset, byData); \ +} + +#define PCIvWriteConfigW(pvHandle, wBusDevFunId, byRegOffset, wData) \ +{ \ + PCIXvWriteW(wBusDevFunId, byRegOffset, wData); \ +} + +#define PCIvWriteConfigD(pvHandle, wBusDevFunId, byRegOffset, dwData) \ +{ \ + PCIXvWriteD(wBusDevFunId, byRegOffset, dwData); \ +} + +#define PCIvReadConfigManyBytes(pvHandle, wBusDevFunId, byRegOffset, pbyBuffer, byCount) \ +{ \ + PCIXvReadManyBytes(wBusDevFunId, byRegOffset, pbyBuffer, byCount); \ +} + +#define PCIbFindConfigDeviceInfo(dwDevVenID, pbyBusNum, pbySlotNum, pbyFuncNum, pbyRevId, \ + pdwIoBase, pdwIoSpaceRange, pbyIrqNo) \ + (PCIXbFindDeviceInfo(dwDevVenID, pbyBusNum, pbySlotNum, pbyFuncNum, pbyRevId, pdwIoBase, \ + pdwIoSpaceRange, pbyIrqNo)) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __UPCI_H__ */ diff --git a/cpu/arm920t/wmt/upcix.c b/cpu/arm920t/wmt/upcix.c new file mode 100755 index 0000000..bee3903 --- /dev/null +++ b/cpu/arm920t/wmt/upcix.c @@ -0,0 +1,194 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#if !defined(__UASSERT_H__) +#include "uassert.h" +#endif +#if !defined(__UPC_H__) +#include "upc.h" +#endif + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TPCI_H__) +#include "tpci.h" +#endif +#if !defined(__UPCIX_H__) +#include "upcix.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/* PCI configuration space IO port */ +#define PCI_INDEX 0xC0000CF8 +#define PCI_DATA 0xC0000CFC + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Import Functions --------------------------*/ + +VOID PCIXvReadB(WORD wBusDevFunId, BYTE byRegOffset, PBYTE pbyData) +{ + DWORD dwIndex; + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvInPortB(PCI_DATA + (byRegOffset % 4), pbyData); +} + +VOID PCIXvReadW(WORD wBusDevFunId, BYTE byRegOffset, PWORD pwData) +{ + DWORD dwIndex; + + /* must word alignment */ + DBG_ASSERT((byRegOffset % 2) == 0); + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvInPortW(PCI_DATA + (byRegOffset % 4), pwData); +} + +VOID PCIXvReadD(WORD wBusDevFunId, BYTE byRegOffset, PDWORD pdwData) +{ + DWORD dwIndex; + + /* must dword alignment */ + DBG_ASSERT((byRegOffset % 4) == 0); + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvInPortD(PCI_DATA, pdwData); +} + +VOID PCIXvWriteB(WORD wBusDevFunId, BYTE byRegOffset, BYTE byData) +{ + DWORD dwIndex; + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvOutPortB(PCI_DATA + (byRegOffset % 4), byData); +} + +VOID PCIXvWriteW(WORD wBusDevFunId, BYTE byRegOffset, WORD wData) +{ + DWORD dwIndex; + + /* must word alignment */ + DBG_ASSERT((byRegOffset % 2) == 0); + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvOutPortW(PCI_DATA + (byRegOffset % 4), wData); +} + +VOID PCIXvWriteD(WORD wBusDevFunId, BYTE byRegOffset, DWORD dwData) +{ + DWORD dwIndex; + + /* must dword alignment */ + DBG_ASSERT((byRegOffset % 4) == 0); + + dwIndex = wBusDevFunId; + dwIndex = 0x80000000L | (dwIndex << 8) | (byRegOffset & 0xFC); + + PCBvOutPortD(PCI_INDEX, dwIndex); + PCBvOutPortD(PCI_DATA, dwData); +} + +VOID PCIXvReadManyBytes(WORD wBusDevFunId, BYTE byRegOffset, PBYTE pbyBuffer, WORD wCount) +{ + WORD wIdx; + PBYTE pbyTmpBuf = pbyBuffer; + + for (wIdx = 0; wIdx < wCount; wIdx++, pbyTmpBuf++) + PCIXvReadB(wBusDevFunId, (BYTE)(byRegOffset + wIdx), pbyTmpBuf); +} + +BOOL PCIXbFindDeviceInfo(DWORD dwDevVenID, PBYTE pbyBusNum, + PBYTE pbySlotNum, PBYTE pbyFuncNum, PBYTE pbyRevId, PDWORD pdwIoBase, + PDWORD pdwIoSpaceRange, PBYTE pbyIrqNo) +{ + DWORD dwCurrDevVenID; + BYTE byBusNum = *pbyBusNum; + BYTE bySlotNum = *pbySlotNum; + BYTE byFuncNum = *pbyFuncNum; + BOOL bMultiFunc; + BYTE byData; + int i; + + for (i = byBusNum; i < MAX_PCI_BUS; i++) { + byBusNum = (BYTE)i; + + for ( ; bySlotNum < MAX_PCI_DEVICE; bySlotNum++) { + PCIXvReadB(MAKE_BDF_TO_WORD(byBusNum, bySlotNum, 0), PCI_REG_HDR_TYPE, &byData); + bMultiFunc = BITbIsAllBitsOn(byData, 0x80); + + for ( ; byFuncNum < ((bMultiFunc) ? 8 : 1); byFuncNum++) { + PCIXvReadD(MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum), + PCI_REG_VENDOR_ID, &dwCurrDevVenID); + + /* is this our device? */ + if (dwCurrDevVenID == dwDevVenID) { + PCIXvReadB(MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum), + PCI_REG_REV_ID, pbyRevId); + PCIXvReadD(MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum), + PCI_REG_BAR0, pdwIoBase); + *pdwIoBase = (*pdwIoBase) & 0xFFFFFFFEUL; + + /* IO space range: */ + /* 43:0x80(128B), 65:0x100(256B) */ + if (*pbyRevId < 0x40) + *pdwIoSpaceRange = 0x00000080L; + else + *pdwIoSpaceRange = 0x00000100L; + + PCIXvReadB(MAKE_BDF_TO_WORD(byBusNum, bySlotNum, byFuncNum), + PCI_REG_INT_LINE, pbyIrqNo); + *pbyBusNum = byBusNum; + *pbySlotNum = bySlotNum; + *pbyFuncNum = byFuncNum; + return TRUE; + } + } + byFuncNum = 0; + } + bySlotNum = 0; + } + + return FALSE; +} diff --git a/cpu/arm920t/wmt/upcix.h b/cpu/arm920t/wmt/upcix.h new file mode 100755 index 0000000..ac62be7 --- /dev/null +++ b/cpu/arm920t/wmt/upcix.h @@ -0,0 +1,59 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __UPCIX_H__ +#define __UPCIX_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID PCIXvReadB(WORD wBusDevFunId, BYTE byRegOffset, PBYTE pbyData); +VOID PCIXvReadW(WORD wBusDevFunId, BYTE byRegOffset, PWORD pwData); +VOID PCIXvReadD(WORD wBusDevFunId, BYTE byRegOffset, PDWORD pdwData); +VOID PCIXvWriteB(WORD wBusDevFunId, BYTE byRegOffset, BYTE byData); +VOID PCIXvWriteW(WORD wBusDevFunId, BYTE byRegOffset, WORD wData); +VOID PCIXvWriteD(WORD wBusDevFunId, BYTE byRegOffset, DWORD dwData); + +VOID PCIXvReadManyBytes(WORD wBusDevFunId, BYTE byRegOffset, PBYTE pbyBuffer, WORD wCount); + +BOOL PCIXbFindDeviceInfo(DWORD dwDevVenID, PBYTE pbyBusNum, + PBYTE pbySlotNum, PBYTE pbyFuncNum, PBYTE pbyRevId, PDWORD pdwIoBase, + PDWORD pdwIoSpaceRange, PBYTE pbyIrqNo); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __UPCIX_H__ */ diff --git a/cpu/arm920t/wmt/version.h b/cpu/arm920t/wmt/version.h new file mode 100755 index 0000000..560432f --- /dev/null +++ b/cpu/arm920t/wmt/version.h @@ -0,0 +1,41 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __VERSION_H__ +#define __VERSION_H__ + +/*--------------------- Export Definitions -------------------------*/ +#define SZ_DRIVER_VERSION "1.34" +#define SZ_DRIVER_BUILD_NUMBER "0045" + +#define SZ_ADAPTER_NAME "VIA Networking Velocity Family Gigabit Ethernet Adapter " +#define SZ_CHIP3119A "VT6110 " +#define SZ_CHIP3216A "VT6120/VT6122 " +#define SZ_CHIP3216A64 "VT6121 " +#define SZ_CHIP3286AQFP "VT6132 " +#define SZ_CHIP3286AQFN "VT6130 " + +#define ADAPTER_NAME_LEN 65 + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#endif /* __VERSION_H__ */ diff --git a/cpu/arm920t/wmt/vpci.c b/cpu/arm920t/wmt/vpci.c new file mode 100755 index 0000000..76d2ef4 --- /dev/null +++ b/cpu/arm920t/wmt/vpci.c @@ -0,0 +1,170 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__VPCI_H__) +#include "vpci.h" +#endif + +#if !defined(__PCINET_H__) +#include "pcinet.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +VOID +VPCIvInitialize( + DWORD dwIoBase, + BYTE byRevId + ) +{ + /* PATCH.... turn this on to avoid retry forever */ + VPCIvRegBitsOn(dwIoBase, PCI_REG_MODE2, MODE2_PCEROPT); + /* PATCH.... */ + /* for some legacy BIOS and OS don't open BusM */ + /* bit in PCI configuration space. So, turn it on. */ + VPCIvRegBitsOn(dwIoBase, PCI_REG_COMMAND, COMMAND_BUSM); + /* PATCH.... turn this on to detect MII coding error */ + VPCIvRegBitsOn(dwIoBase, PCI_REG_MODE3, MODE3_MIION); +} + +VOID +VPCIvReadB( + DWORD dwIoBase, + BYTE byRegOffset, + PBYTE pbyData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvInPortB(dwPCICfgAddr + byRegOffset, pbyData); +} + +VOID +VPCIvReadW( + DWORD dwIoBase, + BYTE byRegOffset, + PWORD pwData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvInPortW(dwPCICfgAddr + byRegOffset, pwData); +} + +VOID +VPCIvReadD( + DWORD dwIoBase, + BYTE byRegOffset, + PDWORD pdwData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvInPortD(dwPCICfgAddr + byRegOffset, pdwData); +} + +VOID +VPCIvRegBitsOn( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byBits + ) +{ + BYTE byOrgData; + + + VPCIvReadB(dwIoBase, byRegOffset, &byOrgData); + VPCIvWriteB(dwIoBase, byRegOffset, (BYTE)(byOrgData | byBits)); +} + +VOID +VPCIvRegBitsOff( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byBits + ) +{ + BYTE byOrgData; + + + VPCIvReadB(dwIoBase, byRegOffset, &byOrgData); + VPCIvWriteB(dwIoBase, byRegOffset, (BYTE)(byOrgData & ~byBits)); +} + +VOID +VPCIvWriteB( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvOutPortB(dwPCICfgAddr + byRegOffset, byData); +} + +VOID +VPCIvWriteW( + DWORD dwIoBase, + BYTE byRegOffset, + WORD wData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvOutPortW(dwPCICfgAddr + byRegOffset, wData); +} + +VOID +VPCIvWriteD( + DWORD dwIoBase, + BYTE byRegOffset, + DWORD dwData + ) +{ + DWORD dwPCICfgAddr; + + + dwPCICfgAddr = dwIoBase + PCI_CFG_SPACE_OFFSET; + VNSvOutPortD(dwPCICfgAddr + byRegOffset, dwData); +} diff --git a/cpu/arm920t/wmt/vpci.h b/cpu/arm920t/wmt/vpci.h new file mode 100755 index 0000000..d075f11 --- /dev/null +++ b/cpu/arm920t/wmt/vpci.h @@ -0,0 +1,212 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __VPCI_H__ +#define __VPCI_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define PCI_CFG_SPACE_OFFSET 0x0100 /* PCI Configuration Space appended after CSR */ + +/* + * Registers in the PCI configuration space + */ +#define PCI_REG_VENDOR_ID 0x00 +#define PCI_REG_DEVICE_ID 0x02 +#define PCI_REG_COMMAND 0x04 +#define PCI_REG_STATUS 0x06 +#define PCI_REG_REV_ID 0x08 +#define PCI_REG_CLASS_CODE 0x09 +#define PCI_REG_CACHELINE_SIZE 0x0C +#define PCI_REG_LAT_TIMER 0x0D +#define PCI_REG_HDR_TYPE 0x0E +#define PCI_REG_BIST 0x0F + +#define PCI_REG_BAR0 0x10 +#define PCI_REG_BAR1 0x14 +#define PCI_REG_BAR2 0x18 +#define PCI_REG_CARDBUS_CIS_PTR 0x28 + +#define PCI_REG_SUB_VEN_ID 0x2C +#define PCI_REG_SUB_SYS_ID 0x2E +#define PCI_REG_EXP_ROM_BAR 0x30 +#define PCI_REG_CAP 0x34 + +#define PCI_REG_INT_LINE 0x3C +#define PCI_REG_INT_PIN 0x3D +#define PCI_REG_MIN_GNT 0x3E +#define PCI_REG_MAX_LAT 0x3F + +/* + * Registers in the PCI configuration space + */ +/* #define PCI_REG_MODE0 0x50 // ? */ +#define PCI_REG_MODE0 0x60 +#define PCI_REG_MODE1 0x61 +#define PCI_REG_MODE2 0x62 +#define PCI_REG_MODE3 0x63 +#define PCI_REG_DELAY_TIMER 0x64 +#define PCI_REG_FIFOTST 0x51 +/* #define PCI_REG_MODE2 0x52 // ? */ +/* #define PCI_REG_MODE3 0x53 // ? */ +/* #define PCI_REG_DELAY_TIMER 0x54 // ? */ +#define PCI_REG_FIFOCMD 0x56 +#define PCI_REG_FIFOSTA 0x57 +#define PCI_REG_BNRY 0x58 +#define PCI_REG_CURR 0x5A +#define PCI_REG_FIFO_DATA 0x5C + +#define PCI_REG_MAX_SIZE 0x100 /* maximun total PCI registers */ + +/* + * Registers for power management (offset) + */ +/* #define PCI_REG_PM_BASE 0x40 // ? */ +#define PCI_REG_PM_BASE 0x50 +#define PM_CAP_ID 0x00 +#define PM_NEXT_ITEM_PTR 0x01 +#define PM_PMC0 0x02 +#define PM_PMC1 0x03 +#define PM_PMCSR0 0x04 +#define PM_PMCSR1 0x05 +#define PM_CSR_BSE 0x06 +#define PM_DATA 0x07 + +/* + * Bits in the COMMAND register + */ +#define COMMAND_BUSM 0x04 + +/* + * Bits in the MODE0 register + */ +#define MODE0_QPKTDS 0x80 + +/* + * Bits in the MODE2 register + */ +#define MODE2_PCEROPT 0x80 /* VT3065 only */ +#define MODE2_DISABT 0x40 +#define MODE2_MODE10T 0x02 + +/* + * Bits in the MODE3 register + */ +#define MODE3_XONOPT 0x80 +#define MODE3_TPACEN 0x40 +#define MODE3_BACKOPT 0x20 +#define MODE3_DLTSEL 0x10 +#define MODE3_MIIDMY 0x08 +#define MODE3_MIION 0x04 + +/* + * Bits in PMCSR0 register + */ +#define PMCSR0_PW_STAT1 0x02 +#define PMCSR0_PW_STAT0 0x01 + +/* + * Bits in PMCSR1 register + */ +#define PMCSR1_PME_STATUS 0x80 +#define PMCSR1_PME_EN 0x01 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +VPCIvInitialize( + DWORD dwIoBase, + BYTE byRevId + ); + +VOID +VPCIvReadB( + DWORD dwIoBase, + BYTE byRegOffset, + PBYTE pbyData + ); + +VOID +VPCIvReadW( + DWORD dwIoBase, + BYTE byRegOffset, + PWORD pwData + ); + +VOID +VPCIvReadD( + DWORD dwIoBase, + BYTE byRegOffset, + PDWORD pdwData + ); + +VOID +VPCIvRegBitsOn( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byBits + ); + +VOID +VPCIvRegBitsOff( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byBits + ); + +VOID +VPCIvWriteB( + DWORD dwIoBase, + BYTE byRegOffset, + BYTE byData + ); + +VOID +VPCIvWriteW( + DWORD dwIoBase, + BYTE byRegOffset, + WORD wData + ); + +VOID +VPCIvWriteD( + DWORD dwIoBase, + BYTE byRegOffset, + DWORD dwData + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif /* __VPCI_H__ */ diff --git a/cpu/arm920t/wmt/zde.c b/cpu/arm920t/wmt/zde.c new file mode 100755 index 0000000..1009dfc --- /dev/null +++ b/cpu/arm920t/wmt/zde.c @@ -0,0 +1,111 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <common.h> + +#ifdef CONFIG_ZDE_KERNEL_DEBUG + +#define SemiSWI 0x123456 + +/*************************************************/ +/* Semihosting extension SWI Operating Numbers */ +/*************************************************/ +#define SYS_BOOTLOADOS 0x6002 + +/* + * For manipulate CP15 cache and TLB control register. (R1) + */ +#define CR_M (1 << 0) /* MMU enable */ +#define CR_A (1 << 1) /* Alignment abort enable */ +#define CR_C (1 << 2) /* Dcache enable */ +#define CR_W (1 << 3) /* Write buffer enable */ +/* bit[4:7] are reserved */ +#define CR_S (1 << 8) /* System MMU protection */ +#define CR_R (1 << 9) /* ROM MMU protection */ +/* bit[10:11] are reserved */ +#define CR_I (1 << 12) /* Icache enable */ +#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ +/* bit[14:31] are reserved */ + +typedef struct __semi_sys_bootloados { + unsigned int os_type; /* 0x0: normal application; 0x1: Linux */ + unsigned int board_arch; /* 0x0: Reserved; 0x4A (vt8253C) just pass to kernel R1 */ + unsigned int kernel_addr; /* kernel address 0xC0008000 */ + unsigned int rootfs_addr; /* rootfs address 0xC8000000 */ + unsigned int loading_type; /* 0x0: boot loader handle; 0x1: Host use JTAG download */ + unsigned int vector_mask; /* 0x0: turn off all to clear all vector */ + unsigned int is_semihosting; /* 0x0: disable; 0x1: enable */ +} semi_sys_bootloados_t; + +/* + * Function Name: do_SemiSWI() + * Purpose: put op code in r0, put value or pointer in r1, send swi + * Return Value: value in r0 + */ +static inline int do_SemiSWI(int swi_op, void *arg) +{ + int value; + asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0" + : "=r" (value) /* Outputs */ + : "r" (swi_op), "r" (arg), "i" (SemiSWI) /* Inputs */ + : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" + /* Clobbers r0 and r1, and lr if in supervisor mode */); + + return value; +} + +static void cp15_set_vector_low(void) +{ + volatile unsigned int ctrl; + + asm volatile + ( + "mrc p15, 0, %0, c1, c0, 0" : "=r" (ctrl) + ); + ctrl &= ~CR_V; + asm volatile + ( + "mcr p15, 0, %0, c1, c0, 0" : : "r" (ctrl) + ); +} + +/* + * Function Name: semi_cbootloados() + * Purpose: Send SWI SYS_BOOTLOADOS to notify converter + * that we have load kernel and/or ramdisk successfully + * Return Value: Void return + */ +void semi_bootloados(void) +{ + semi_sys_bootloados_t semi_sys_bootloados; + + /* To support ZDE Linux kernel debugging, */ + /* Ensure vector table is at 0x0 */ + cp15_set_vector_low(); + + semi_sys_bootloados.os_type = 1; + semi_sys_bootloados.board_arch = 10002; /* 10002 mean vt3300 */ + semi_sys_bootloados.kernel_addr = 0x00008000 ; + semi_sys_bootloados.rootfs_addr = 0x01000000 ; + semi_sys_bootloados.loading_type = 0; + semi_sys_bootloados.vector_mask = 0; + semi_sys_bootloados.is_semihosting = 0; + + do_SemiSWI(SYS_BOOTLOADOS, &semi_sys_bootloados); +} + +#endif /* CONFIG_ZDE_KERNEL_DEBUG */ |