/* $NetBSD: tx39xx.c,v 1.8 2009/03/14 21:04:09 dsl Exp $ */ /*- * Copyright (c) 1999 Shin Takemura, UCHIYAMA Yasushi * All rights reserved. * * This software is part of the PocketBSD. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the PocketBSD project * and its contributors. * 4. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include extern void tx39xx_asm_code(); extern void tx39xx_asm_code_end(); void tx39xx_asm_code_holder(void); #define TX39_SYSADDR_CONFIG_REG 0x10C00000 #define TX39_SYSADDR_CONFIG_REG_LEN 0x00200000 typedef int tx_chipset_tag_t; u_int32_t __tx39conf_addr; u_int32_t tx_conf_read(tx_chipset_tag_t t, int reg) { return *((u_int32_t*)(__tx39conf_addr + reg)); } void tx_conf_write(tx_chipset_tag_t t, int reg, u_int32_t val) { u_int32_t addr = (u_int32_t)t; *((u_int32_t*)(__tx39conf_addr +reg)) = val; } void tx39xx_init(SYSTEM_INFO *info) { /* 4KByte page */ system_info.si_pagesize = info->dwPageSize; /* DRAM Bank 0/1 physical addr range */ system_info.si_dramstart = 0x04000000; system_info.si_drammaxsize = 0x04000000; /* Pointer for bootstrap code */ system_info.si_asmcode = (unsigned char*)tx39xx_asm_code; system_info.si_asmcodelen = (unsigned char*)tx39xx_asm_code_end - system_info.si_asmcode; system_info.si_boot = mips_boot; system_info.si_intrvec = 0x80; __tx39conf_addr = (int)VirtualAlloc(0, TX39_SYSADDR_CONFIG_REG_LEN, MEM_RESERVE, PAGE_NOACCESS); if (!VirtualCopy((LPVOID)__tx39conf_addr, (LPVOID)(TX39_SYSADDR_CONFIG_REG >> 8), TX39_SYSADDR_CONFIG_REG_LEN, PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL)) { msg_printf(MSG_ERROR, whoami, TEXT("Mapping TX39 configuration register failed.\n")); } } void tx39xx_asm_code_holder() { /* * void * startprog(register struct map_s *map) * { * register unsigned char *addr; * register unsigned char *p; * register int i; * * addr = map->base; * i = 0; * while (p = map->leaf[i / map->leafsize][i % map->leafsize]) { * register unsigned char *pe = p + map->pagesize; * while (p < pe) { * *addr++ = *p++; * } * i++; * } * } * * register assignment: * struct map_s *map a0 * unsigned char *addr a1 * unsigned char *p a2 * unsigned char *pe a3 * int i t0 * * struct map_s { * void *entry; +0 * void *base; +4 * int pagesize; +8 * int leafsize; +12 * int nleaves; +16 * void *arg0; +20 * void *arg1; +24 * void *arg2; +28 * void *arg3; +32 * void **leaf[32]; +36 * */ __asm( ".set noreorder;" ".globl tx39xx_asm_code;" "tx39xx_asm_code:" "lui a0, 0x0000;" "ori a0, 0x0000;" /* Disable interrupt */ "nop;" "mtc0 zero, $12;" "nop;" /* * Copy kernel to bootaddr */ /* addr = map->base; */ "lw a1, 4(a0);" /* i = 0; */ "ori t0, zero, 0;" " loop_start:" /* while (p = map->leaf[i / map->leafsize][i % map->leafsize]) { */ /* t1 = map->leafsize */ "lw t1, 12(a0);" /* lo = i / map->leafsize, hi = i % map->leafsize */ "addu t3, zero, t0;" "div t3, t1;" /* t2 = map->leaf */ "addiu t2, a0, 36;" /* t3 = i / map->leafsize */ "nop;" "mflo t3;" /* t2 = map->leaf[i / map->leafsize] */ "sll t3, t3, 2;" "addu t2, t2, t3;" "lw t2, 0(t2);" /* t3 = i % map->leafsize */ "mfhi t3;" /* p = map->leaf[i / map->leafsize][i % map->leafsize] */ "sll t3, t3, 2;" "addu t2, t2, t3;" "lw a2, 0(t2);" /* if (p == NULL) { */ /* break; */ /* } */ "beq a2, zero, loop_end;" "nop;" /* register unsigned char *pe = p + map->pagesize; */ "lw t1, 8(a0);" "add a3, a2, t1;" /* while (p < pe) { */ "loop_start2:" "sltu t1, a2, a3;" "beq zero,t1,loop_end2;" "nop;" /* *addr++ = *p++; */ "lw t1, 0(a2);" "sw t1, 0(a1);" "addi a2, a2, 4;" "addi a1, a1, 4;" /* } */ "beq zero, zero, loop_start2;" "nop;" /* i++; */ "loop_end2:" "addi t0, t0, 1;" "beq zero, zero, loop_start;" "nop;" "loop_end:" "move t3, a0;" ); /* * Flush cache */ __asm( "li t1, 16384;" "li t2, 8192;" /* Disable I-cache */ "li t5, ~0x00000020;" "mfc0 t6, $3;" "and t5, t5, t6;" "nop;" "mtc0 t5, $3;" /* Stop streaming */ "beq zero, zero, 1f;" "nop;" "1:" /* Flush I-cache */ "li t0, 0x80000000;" "addu t1, t0, t1;" "subu t1, t1, 128;" "2:" ".word 0xbd000000;" ".word 0xbd000010;" ".word 0xbd000020;" ".word 0xbd000030;" ".word 0xbd000040;" ".word 0xbd000050;" ".word 0xbd000060;" ".word 0xbd000070;" "bne t0, t1, 2b;" "addu t0, t0, 128;" /* Flush D-cache */ "li t0, 0x80000000;" "addu t1, t0, t2;" "3:" "lw t2, 0(t0);" "bne t1, t0, 3b;" "addiu t0, t0, 4;" /* Enable I-cache */ "nop;" "mtc0 t6, $3;" "nop;" ); /* * Jump to kernel entry */ __asm( "lw t0, 0(t3);" /* entry addr */ "lw a1, 24(t3);" /* arg1 */ "lw a2, 28(t3);" /* arg2 */ "lw a3, 32(t3);" /* arg3 */ "lw a0, 20(t3);" /* arg0 */ "jr t0;" "nop;" ".globl tx39xx_asm_code_end;" "tx39xx_asm_code_end: nop;" ".set reorder; " ); }