mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
* Add support for MIPS32 4Kc CPUs
* Add support for INCA-IP Board
This commit is contained in:
parent
ac6dbb85b7
commit
c021880ac5
25 changed files with 5874 additions and 3 deletions
14
CHANGELOG
14
CHANGELOG
|
@ -3,7 +3,9 @@ Changes since U-Boot 0.2.2:
|
|||
======================================================================
|
||||
|
||||
* Patch by Rick Bronson, 16 Mar 2003:
|
||||
Add support for Atmel AT91RM9200DK w/NAND
|
||||
- Add NAND flash support for reading, writing, and erasing NAND
|
||||
flash (certain forms of which are called SmartMedia).
|
||||
- Add support for Atmel AT91RM9200DK ARM920T based development kit.
|
||||
|
||||
* Patches by Robert Schwebel, 19 Mar 2003:
|
||||
- use arm-linux-gcc as default compiler for ARM
|
||||
|
@ -36,6 +38,12 @@ Changes since U-Boot 0.2.2:
|
|||
to existing PPC405GP designs.
|
||||
- Clip udiv to 5 bits on PPC405 (serial.c).
|
||||
|
||||
* Extend INCAIP board support:
|
||||
- add automatic RAM size detection
|
||||
- add "bdinfo" command
|
||||
- pass flash address and size to Linux kernel
|
||||
- switch to 150 MHz clock
|
||||
|
||||
* Avoid flicker on the TRAB's VFD by synchronizing the enable with
|
||||
the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
|
||||
boards, version 153 for Rev. 200 boards).
|
||||
|
@ -179,6 +187,10 @@ Changes since U-Boot 0.2.2:
|
|||
* Patch by Stefan Roese, 10 Feb 2003:
|
||||
Add support for 4MB and 128MB onboard SDRAM (cpu/ppc4xx/sdram.c)
|
||||
|
||||
* Add support for MIPS32 4Kc CPUs
|
||||
|
||||
* Add support for INCA-IP Board
|
||||
|
||||
======================================================================
|
||||
Changes for U-Boot 0.2.2:
|
||||
======================================================================
|
||||
|
|
2
CREDITS
2
CREDITS
|
@ -48,7 +48,7 @@ D: 8xxrom-0.3.0
|
|||
|
||||
N: Rick Bronson
|
||||
E: rick@efn.org
|
||||
D: Atmel AT91RM9200DK w/NAND support
|
||||
D: Atmel AT91RM9200DK and NAND support
|
||||
|
||||
N: David Brown
|
||||
E: DBrown03@harris.com
|
||||
|
|
10
MAKEALL
10
MAKEALL
|
@ -107,6 +107,14 @@ LIST_xscale="cradle csb226 innokom lubbock"
|
|||
|
||||
LIST_arm="${LIST_SA} ${LIST_ARM7} ${LIST_ARM9} ${LIST_xscale}"
|
||||
|
||||
#########################################################################
|
||||
## MIPS 4Kc Systems
|
||||
#########################################################################
|
||||
|
||||
LIST_mips4kc="incaip"
|
||||
|
||||
LIST_mips="${LIST_mips4kc}"
|
||||
|
||||
|
||||
#----- for now, just run PPC by default -----
|
||||
[ $# = 0 ] && set $LIST_ppc
|
||||
|
@ -128,7 +136,7 @@ build_target() {
|
|||
for arg in $@
|
||||
do
|
||||
case "$arg" in
|
||||
8xx|824x|8260|4xx|7xx|74xx|SA|ARM7|ARM9|ppc|arm|xscale)
|
||||
8xx|824x|8260|4xx|7xx|74xx|SA|ARM7|ARM9|ppc|arm|xscale|mips)
|
||||
for target in `eval echo '$LIST_'${arg}`
|
||||
do
|
||||
build_target ${target}
|
||||
|
|
41
board/incaip/Makefile
Normal file
41
board/incaip/Makefile
Normal file
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# (C) Copyright 2003
|
||||
# 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$(BOARD).a
|
||||
|
||||
OBJS = $(BOARD).o flash.o
|
||||
SOBJS = memsetup.o
|
||||
|
||||
$(LIB): .depend $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $^
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
32
board/incaip/config.mk
Normal file
32
board/incaip/config.mk
Normal file
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# (C) Copyright 2003
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# INCA-IP board with MIPS 4Kc CPU core
|
||||
#
|
||||
|
||||
# ROM version
|
||||
TEXT_BASE = 0xB0000000
|
||||
|
||||
# RAM version
|
||||
#TEXT_BASE = 0x80100000
|
671
board/incaip/flash.c
Normal file
671
board/incaip/flash.c
Normal file
|
@ -0,0 +1,671 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <asm/inca-ip.h>
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
|
||||
|
||||
/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
|
||||
* has nothing to do with the flash chip being 8-bit or 16-bit.
|
||||
*/
|
||||
#ifdef CONFIG_FLASH_16BIT
|
||||
typedef unsigned short FLASH_PORT_WIDTH;
|
||||
typedef volatile unsigned short FLASH_PORT_WIDTHV;
|
||||
#define FLASH_ID_MASK 0xFFFF
|
||||
#else
|
||||
typedef unsigned long FLASH_PORT_WIDTH;
|
||||
typedef volatile unsigned long FLASH_PORT_WIDTHV;
|
||||
#define FLASH_ID_MASK 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#define FPW FLASH_PORT_WIDTH
|
||||
#define FPWV FLASH_PORT_WIDTHV
|
||||
|
||||
#define ORMASK(size) ((-size) & OR_AM_MSK)
|
||||
|
||||
#if 0
|
||||
#define FLASH_CYCLE1 0x0555
|
||||
#define FLASH_CYCLE2 0x02aa
|
||||
#else
|
||||
#define FLASH_CYCLE1 0x0554
|
||||
#define FLASH_CYCLE2 0x02ab
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Functions
|
||||
*/
|
||||
static ulong flash_get_size(FPWV *addr, flash_info_t *info);
|
||||
static void flash_reset(flash_info_t *info);
|
||||
static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
|
||||
static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
|
||||
static void flash_get_offsets(ulong base, flash_info_t *info);
|
||||
static flash_info_t *flash_get_info(ulong base);
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* flash_init()
|
||||
*
|
||||
* sets up flash_info and returns size of FLASH (bytes)
|
||||
*/
|
||||
unsigned long flash_init (void)
|
||||
{
|
||||
unsigned long size = 0;
|
||||
int i;
|
||||
|
||||
/* Init: no FLASHes known */
|
||||
for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) {
|
||||
ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2;
|
||||
ulong * buscon = (ulong *)
|
||||
((i == 0) ? INCA_IP_EBU_EBU_BUSCON0 : INCA_IP_EBU_EBU_BUSCON2);
|
||||
|
||||
/* Disable write protection */
|
||||
*buscon &= ~INCA_IP_EBU_EBU_BUSCON1_WRDIS;
|
||||
|
||||
#if 1
|
||||
memset(&flash_info[i], 0, sizeof(flash_info_t));
|
||||
#endif
|
||||
|
||||
flash_info[i].size =
|
||||
flash_get_size((FPW *)flashbase, &flash_info[i]);
|
||||
|
||||
if (flash_info[i].flash_id == FLASH_UNKNOWN) {
|
||||
printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n",
|
||||
i, flash_info[i].size);
|
||||
}
|
||||
|
||||
size += flash_info[i].size;
|
||||
}
|
||||
|
||||
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
|
||||
/* monitor protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_MONITOR_BASE,
|
||||
CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
|
||||
flash_get_info(CFG_MONITOR_BASE));
|
||||
#endif
|
||||
|
||||
#ifdef CFG_ENV_IS_IN_FLASH
|
||||
/* ENV protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR,
|
||||
CFG_ENV_ADDR+CFG_ENV_SIZE-1,
|
||||
flash_get_info(CFG_ENV_ADDR));
|
||||
#endif
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
static void flash_reset(flash_info_t *info)
|
||||
{
|
||||
FPWV *base = (FPWV *)(info->start[0]);
|
||||
|
||||
/* Put FLASH back in read mode */
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
|
||||
*base = (FPW)0x00FF00FF; /* Intel Read Mode */
|
||||
else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
|
||||
*base = (FPW)0x00F000F0; /* AMD Read Mode */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
static void flash_get_offsets (ulong base, flash_info_t *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* set up sector start address table */
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
|
||||
&& (info->flash_id & FLASH_BTYPE)) {
|
||||
int bootsect_size; /* number of bytes/boot sector */
|
||||
int sect_size; /* number of bytes/regular sector */
|
||||
|
||||
bootsect_size = 0x00002000 * (sizeof(FPW)/2);
|
||||
sect_size = 0x00010000 * (sizeof(FPW)/2);
|
||||
|
||||
/* set sector offsets for bottom boot block type */
|
||||
for (i = 0; i < 8; ++i) {
|
||||
info->start[i] = base + (i * bootsect_size);
|
||||
}
|
||||
for (i = 8; i < info->sector_count; i++) {
|
||||
info->start[i] = base + ((i - 7) * sect_size);
|
||||
}
|
||||
}
|
||||
else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
|
||||
&& (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
|
||||
|
||||
int sect_size; /* number of bytes/sector */
|
||||
|
||||
sect_size = 0x00010000 * (sizeof(FPW)/2);
|
||||
|
||||
/* set up sector start address table (uniform sector type) */
|
||||
for( i = 0; i < info->sector_count; i++ )
|
||||
info->start[i] = base + (i * sect_size);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static flash_info_t *flash_get_info(ulong base)
|
||||
{
|
||||
int i;
|
||||
flash_info_t * info;
|
||||
|
||||
for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
|
||||
info = & flash_info[i];
|
||||
if (info->start[0] <= base && base < info->start[0] + info->size)
|
||||
break;
|
||||
}
|
||||
|
||||
return i == CFG_MAX_FLASH_BANKS ? 0 : info;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void flash_print_info (flash_info_t *info)
|
||||
{
|
||||
int i;
|
||||
uchar *boottype;
|
||||
uchar *bootletter;
|
||||
uchar *fmt;
|
||||
uchar botbootletter[] = "B";
|
||||
uchar topbootletter[] = "T";
|
||||
uchar botboottype[] = "bottom boot sector";
|
||||
uchar topboottype[] = "top boot sector";
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("missing or unknown FLASH type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_VENDMASK) {
|
||||
case FLASH_MAN_AMD: printf ("AMD "); break;
|
||||
case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break;
|
||||
case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
|
||||
case FLASH_MAN_SST: printf ("SST "); break;
|
||||
case FLASH_MAN_STM: printf ("STM "); break;
|
||||
case FLASH_MAN_INTEL: printf ("INTEL "); break;
|
||||
default: printf ("Unknown Vendor "); break;
|
||||
}
|
||||
|
||||
/* check for top or bottom boot, if it applies */
|
||||
if (info->flash_id & FLASH_BTYPE) {
|
||||
boottype = botboottype;
|
||||
bootletter = botbootletter;
|
||||
}
|
||||
else {
|
||||
boottype = topboottype;
|
||||
bootletter = topbootletter;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK) {
|
||||
case FLASH_AM640U:
|
||||
fmt = "29LV641D (64 Mbit, uniform sectors)\n";
|
||||
break;
|
||||
case FLASH_28F800C3B:
|
||||
case FLASH_28F800C3T:
|
||||
fmt = "28F800C3%s (8 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_INTEL800B:
|
||||
case FLASH_INTEL800T:
|
||||
fmt = "28F800B3%s (8 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_28F160C3B:
|
||||
case FLASH_28F160C3T:
|
||||
fmt = "28F160C3%s (16 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_INTEL160B:
|
||||
case FLASH_INTEL160T:
|
||||
fmt = "28F160B3%s (16 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_28F320C3B:
|
||||
case FLASH_28F320C3T:
|
||||
fmt = "28F320C3%s (32 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_INTEL320B:
|
||||
case FLASH_INTEL320T:
|
||||
fmt = "28F320B3%s (32 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_28F640C3B:
|
||||
case FLASH_28F640C3T:
|
||||
fmt = "28F640C3%s (64 Mbit, %s)\n";
|
||||
break;
|
||||
case FLASH_INTEL640B:
|
||||
case FLASH_INTEL640T:
|
||||
fmt = "28F640B3%s (64 Mbit, %s)\n";
|
||||
break;
|
||||
default:
|
||||
fmt = "Unknown Chip Type\n";
|
||||
break;
|
||||
}
|
||||
|
||||
printf (fmt, bootletter, boottype);
|
||||
|
||||
printf (" Size: %ld MB in %d Sectors\n",
|
||||
info->size >> 20,
|
||||
info->sector_count);
|
||||
|
||||
printf (" Sector Start Addresses:");
|
||||
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
if ((i % 5) == 0) {
|
||||
printf ("\n ");
|
||||
}
|
||||
|
||||
printf (" %08lX%s", info->start[i],
|
||||
info->protect[i] ? " (RO)" : " ");
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following code cannot be run from FLASH!
|
||||
*/
|
||||
|
||||
ulong flash_get_size (FPWV *addr, flash_info_t *info)
|
||||
{
|
||||
/* Write auto select command: read Manufacturer ID */
|
||||
|
||||
/* Write auto select command sequence and test FLASH answer */
|
||||
addr[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* for AMD, Intel ignores this */
|
||||
addr[FLASH_CYCLE2] = (FPW)0x00550055; /* for AMD, Intel ignores this */
|
||||
addr[FLASH_CYCLE1] = (FPW)0x00900090; /* selects Intel or AMD */
|
||||
|
||||
/* The manufacturer codes are only 1 byte, so just use 1 byte.
|
||||
* This works for any bus width and any FLASH device width.
|
||||
*/
|
||||
switch (addr[1] & 0xff) {
|
||||
|
||||
case (uchar)AMD_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_AMD;
|
||||
break;
|
||||
|
||||
case (uchar)INTEL_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_INTEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
info->sector_count = 0;
|
||||
info->size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
|
||||
if (info->flash_id != FLASH_UNKNOWN) switch (addr[0]) {
|
||||
|
||||
case (FPW)AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */
|
||||
info->flash_id += FLASH_AM640U;
|
||||
info->sector_count = 128;
|
||||
info->size = 0x00800000 * (sizeof(FPW)/2);
|
||||
break; /* => 8 or 16 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F800C3B:
|
||||
info->flash_id += FLASH_28F800C3B;
|
||||
info->sector_count = 23;
|
||||
info->size = 0x00100000 * (sizeof(FPW)/2);
|
||||
break; /* => 1 or 2 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F800B3B:
|
||||
info->flash_id += FLASH_INTEL800B;
|
||||
info->sector_count = 23;
|
||||
info->size = 0x00100000 * (sizeof(FPW)/2);
|
||||
break; /* => 1 or 2 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F160C3B:
|
||||
info->flash_id += FLASH_28F160C3B;
|
||||
info->sector_count = 39;
|
||||
info->size = 0x00200000 * (sizeof(FPW)/2);
|
||||
break; /* => 2 or 4 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F160B3B:
|
||||
info->flash_id += FLASH_INTEL160B;
|
||||
info->sector_count = 39;
|
||||
info->size = 0x00200000 * (sizeof(FPW)/2);
|
||||
break; /* => 2 or 4 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F320C3B:
|
||||
info->flash_id += FLASH_28F320C3B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000 * (sizeof(FPW)/2);
|
||||
break; /* => 4 or 8 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F320B3B:
|
||||
info->flash_id += FLASH_INTEL320B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000 * (sizeof(FPW)/2);
|
||||
break; /* => 4 or 8 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F640C3B:
|
||||
info->flash_id += FLASH_28F640C3B;
|
||||
info->sector_count = 135;
|
||||
info->size = 0x00800000 * (sizeof(FPW)/2);
|
||||
break; /* => 8 or 16 MB */
|
||||
|
||||
case (FPW)INTEL_ID_28F640B3B:
|
||||
info->flash_id += FLASH_INTEL640B;
|
||||
info->sector_count = 135;
|
||||
info->size = 0x00800000 * (sizeof(FPW)/2);
|
||||
break; /* => 8 or 16 MB */
|
||||
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
info->sector_count = 0;
|
||||
info->size = 0;
|
||||
return (0); /* => no or unknown flash */
|
||||
}
|
||||
|
||||
flash_get_offsets((ulong)addr, info);
|
||||
|
||||
/* Put FLASH back in read mode */
|
||||
flash_reset(info);
|
||||
|
||||
return (info->size);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int flash_erase (flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
FPWV *addr;
|
||||
int flag, prot, sect;
|
||||
int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
|
||||
ulong start, now, last;
|
||||
int rcode = 0;
|
||||
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("- missing\n");
|
||||
} else {
|
||||
printf ("- no sectors to erase\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK) {
|
||||
case FLASH_INTEL800B:
|
||||
case FLASH_INTEL160B:
|
||||
case FLASH_INTEL320B:
|
||||
case FLASH_INTEL640B:
|
||||
case FLASH_28F800C3B:
|
||||
case FLASH_28F160C3B:
|
||||
case FLASH_28F320C3B:
|
||||
case FLASH_28F640C3B:
|
||||
case FLASH_AM640U:
|
||||
break;
|
||||
case FLASH_UNKNOWN:
|
||||
default:
|
||||
printf ("Can't erase unknown flash type %08lx - aborted\n",
|
||||
info->flash_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
prot = 0;
|
||||
for (sect=s_first; sect<=s_last; ++sect) {
|
||||
if (info->protect[sect]) {
|
||||
prot++;
|
||||
}
|
||||
}
|
||||
|
||||
if (prot) {
|
||||
printf ("- Warning: %d protected sectors will not be erased!\n",
|
||||
prot);
|
||||
} else {
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
last = get_timer(0);
|
||||
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
|
||||
|
||||
if (info->protect[sect] != 0) /* protected, skip it */
|
||||
continue;
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
addr = (FPWV *)(info->start[sect]);
|
||||
if (intel) {
|
||||
*addr = (FPW)0x00500050; /* clear status register */
|
||||
*addr = (FPW)0x00200020; /* erase setup */
|
||||
*addr = (FPW)0x00D000D0; /* erase confirm */
|
||||
}
|
||||
else {
|
||||
/* must be AMD style if not Intel */
|
||||
FPWV *base; /* first address in bank */
|
||||
|
||||
base = (FPWV *)(info->start[0]);
|
||||
base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
|
||||
base[FLASH_CYCLE1] = (FPW)0x00800080; /* erase mode */
|
||||
base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
|
||||
*addr = (FPW)0x00300030; /* erase sector */
|
||||
}
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
start = get_timer(0);
|
||||
|
||||
/* wait at least 50us for AMD, 80us for Intel.
|
||||
* Let's wait 1 ms.
|
||||
*/
|
||||
udelay (1000);
|
||||
|
||||
while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
|
||||
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
|
||||
printf ("Timeout\n");
|
||||
|
||||
if (intel) {
|
||||
/* suspend erase */
|
||||
*addr = (FPW)0x00B000B0;
|
||||
}
|
||||
|
||||
flash_reset(info); /* reset to read mode */
|
||||
rcode = 1; /* failed */
|
||||
break;
|
||||
}
|
||||
|
||||
/* show that we're waiting */
|
||||
if ((get_timer(last)) > CFG_HZ) {/* every second */
|
||||
putc ('.');
|
||||
last = get_timer(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* show that we're waiting */
|
||||
if ((get_timer(last)) > CFG_HZ) { /* every second */
|
||||
putc ('.');
|
||||
last = get_timer(0);
|
||||
}
|
||||
|
||||
flash_reset(info); /* reset to read mode */
|
||||
}
|
||||
|
||||
printf (" done\n");
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
|
||||
{
|
||||
FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
|
||||
int bytes; /* number of bytes to program in current word */
|
||||
int left; /* number of bytes left to program */
|
||||
int i, res;
|
||||
|
||||
for (left = cnt, res = 0;
|
||||
left > 0 && res == 0;
|
||||
addr += sizeof(data), left -= sizeof(data) - bytes) {
|
||||
|
||||
bytes = addr & (sizeof(data) - 1);
|
||||
addr &= ~(sizeof(data) - 1);
|
||||
|
||||
/* combine source and destination data so can program
|
||||
* an entire word of 16 or 32 bits
|
||||
*/
|
||||
for (i = 0; i < sizeof(data); i++) {
|
||||
data <<= 8;
|
||||
if (i < bytes || i - bytes >= left )
|
||||
data += *((uchar *)addr + i);
|
||||
else
|
||||
data += *src++;
|
||||
}
|
||||
|
||||
/* write one word to the flash */
|
||||
switch (info->flash_id & FLASH_VENDMASK) {
|
||||
case FLASH_MAN_AMD:
|
||||
res = write_word_amd(info, (FPWV *)addr, data);
|
||||
break;
|
||||
case FLASH_MAN_INTEL:
|
||||
res = write_word_intel(info, (FPWV *)addr, data);
|
||||
break;
|
||||
default:
|
||||
/* unknown flash type, error! */
|
||||
printf ("missing or unknown FLASH type\n");
|
||||
res = 1; /* not really a timeout, but gives error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Write a word to Flash for AMD FLASH
|
||||
* A word is 16 or 32 bits, whichever the bus width of the flash bank
|
||||
* (not an individual chip) is.
|
||||
*
|
||||
* returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
|
||||
{
|
||||
ulong start;
|
||||
int flag;
|
||||
int res = 0; /* result, assume success */
|
||||
FPWV *base; /* first address in flash bank */
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
if ((*dest & data) != data) {
|
||||
return (2);
|
||||
}
|
||||
|
||||
|
||||
base = (FPWV *)(info->start[0]);
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
|
||||
base[FLASH_CYCLE1] = (FPW)0x00A000A0; /* selects program mode */
|
||||
|
||||
*dest = data; /* start programming the data */
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
start = get_timer (0);
|
||||
|
||||
/* data polling for D7 */
|
||||
while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
|
||||
*dest = (FPW)0x00F000F0; /* reset bank */
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Write a word to Flash for Intel FLASH
|
||||
* A word is 16 or 32 bits, whichever the bus width of the flash bank
|
||||
* (not an individual chip) is.
|
||||
*
|
||||
* returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
|
||||
{
|
||||
ulong start;
|
||||
int flag;
|
||||
int res = 0; /* result, assume success */
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
if ((*dest & data) != data) {
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
*dest = (FPW)0x00500050; /* clear status register */
|
||||
*dest = (FPW)0x00FF00FF; /* make sure in read mode */
|
||||
*dest = (FPW)0x00400040; /* program setup */
|
||||
|
||||
*dest = data; /* start programming the data */
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
start = get_timer (0);
|
||||
|
||||
while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
|
||||
*dest = (FPW)0x00B000B0; /* Suspend program */
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == 0 && (*dest & (FPW)0x00100010))
|
||||
res = 1; /* write failed, time out error is close enough */
|
||||
|
||||
*dest = (FPW)0x00500050; /* clear status register */
|
||||
*dest = (FPW)0x00FF00FF; /* make sure in read mode */
|
||||
|
||||
return (res);
|
||||
}
|
129
board/incaip/incaip.c
Normal file
129
board/incaip/incaip.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/inca-ip.h>
|
||||
|
||||
|
||||
static ulong max_sdram_size(void)
|
||||
{
|
||||
/* The only supported SDRAM data width is 16bit.
|
||||
*/
|
||||
#define CFG_DW 2
|
||||
|
||||
/* The only supported number of SDRAM banks is 4.
|
||||
*/
|
||||
#define CFG_NB 4
|
||||
|
||||
ulong cfgpb0 = *INCA_IP_SDRAM_MC_CFGPB0;
|
||||
int cols = cfgpb0 & 0xF;
|
||||
int rows = (cfgpb0 & 0xF0) >> 4;
|
||||
ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check memory range for valid RAM. A simple memory test determines
|
||||
* the actually available RAM size between addresses `base' and
|
||||
* `base + maxsize'. Some (not all) hardware errors are detected:
|
||||
* - short between address lines
|
||||
* - short between data lines
|
||||
*/
|
||||
|
||||
static long int dram_size(long int *base, long int maxsize)
|
||||
{
|
||||
volatile long int *addr;
|
||||
ulong cnt, val;
|
||||
ulong save[32]; /* to make test non-destructive */
|
||||
unsigned char i = 0;
|
||||
|
||||
for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
|
||||
addr = base + cnt; /* pointer arith! */
|
||||
|
||||
save[i++] = *addr;
|
||||
*addr = ~cnt;
|
||||
}
|
||||
|
||||
/* write 0 to base address */
|
||||
addr = base;
|
||||
save[i] = *addr;
|
||||
*addr = 0;
|
||||
|
||||
/* check at base address */
|
||||
if ((val = *addr) != 0) {
|
||||
*addr = save[i];
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
|
||||
addr = base + cnt; /* pointer arith! */
|
||||
|
||||
val = *addr;
|
||||
*addr = save[--i];
|
||||
|
||||
if (val != (~cnt)) {
|
||||
return (cnt * sizeof (long));
|
||||
}
|
||||
}
|
||||
return (maxsize);
|
||||
}
|
||||
|
||||
long int initdram(int board_type)
|
||||
{
|
||||
int rows, cols, best_val = *INCA_IP_SDRAM_MC_CFGPB0;
|
||||
ulong size, max_size = 0;
|
||||
ulong our_address;
|
||||
|
||||
asm volatile ("move %0, $25" : "=r" (our_address) :);
|
||||
|
||||
/* Can't probe for RAM size unless we are running from Flash.
|
||||
*/
|
||||
if (PHYSADDR(our_address) < PHYSADDR(PHYS_FLASH_1))
|
||||
{
|
||||
return max_sdram_size();
|
||||
}
|
||||
|
||||
for (cols = 0x8; cols <= 0xC; cols++)
|
||||
{
|
||||
for (rows = 0xB; rows <= 0xD; rows++)
|
||||
{
|
||||
*INCA_IP_SDRAM_MC_CFGPB0 = (0x14 << 8) |
|
||||
(rows << 4) | cols;
|
||||
size = dram_size((ulong *)CFG_SDRAM_BASE,
|
||||
max_sdram_size());
|
||||
|
||||
if (size > max_size)
|
||||
{
|
||||
best_val = *INCA_IP_SDRAM_MC_CFGPB0;
|
||||
max_size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*INCA_IP_SDRAM_MC_CFGPB0 = best_val;
|
||||
return max_size;
|
||||
}
|
||||
|
151
board/incaip/memsetup.S
Normal file
151
board/incaip/memsetup.S
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Memory sub-system initialization code for INCA-IP development board.
|
||||
*
|
||||
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
|
||||
#define EBU_MODUL_BASE 0xB8000200
|
||||
#define EBU_CLC(value) 0x0000(value)
|
||||
#define EBU_CON(value) 0x0010(value)
|
||||
#define EBU_ADDSEL0(value) 0x0020(value)
|
||||
#define EBU_ADDSEL1(value) 0x0024(value)
|
||||
#define EBU_ADDSEL2(value) 0x0028(value)
|
||||
#define EBU_BUSCON0(value) 0x0060(value)
|
||||
#define EBU_BUSCON1(value) 0x0064(value)
|
||||
#define EBU_BUSCON2(value) 0x0068(value)
|
||||
|
||||
#define MC_MODUL_BASE 0xBF800000
|
||||
#define MC_ERRCAUSE(value) 0x0100(value)
|
||||
#define MC_ERRADDR(value) 0x0108(value)
|
||||
#define MC_IOGP(value) 0x0800(value)
|
||||
#define MC_SELFRFSH(value) 0x0A00(value)
|
||||
#define MC_CTRLENA(value) 0x1000(value)
|
||||
#define MC_MRSCODE(value) 0x1008(value)
|
||||
#define MC_CFGDW(value) 0x1010(value)
|
||||
#define MC_CFGPB0(value) 0x1018(value)
|
||||
#define MC_LATENCY(value) 0x1038(value)
|
||||
#define MC_TREFRESH(value) 0x1040(value)
|
||||
|
||||
#if CPU_CLOCK_RATE==150000000 /* 150 MHz clock for the MIPS core */
|
||||
#define CGU_MODUL_BASE 0xBF107000
|
||||
#define CGU_PLL1CR(value) 0x0008(value)
|
||||
#define CGU_DIVCR(value) 0x0010(value)
|
||||
#define CGU_MUXCR(value) 0x0014(value)
|
||||
#define CGU_PLL1SR(value) 0x000C(value)
|
||||
#endif
|
||||
|
||||
.globl memsetup
|
||||
memsetup:
|
||||
|
||||
/* EBU Initialization for the Flash CS0 and CS2.
|
||||
*/
|
||||
li t0, EBU_MODUL_BASE
|
||||
|
||||
li t1, 0xA0000041
|
||||
sw t1, EBU_ADDSEL0(t0)
|
||||
|
||||
#if CPU_CLOCK_RATE==150000000 /* 150 MHz clock for the MIPS core */
|
||||
li t1, 0xE841417E
|
||||
sw t1, EBU_BUSCON0(t0) /* value set up by magic flash word */
|
||||
sw t1, EBU_BUSCON2(t0)
|
||||
#else /* 100 MHz */
|
||||
lw t1, EBU_BUSCON0(t0) /* value set up by magic flash word */
|
||||
sw t1, EBU_BUSCON2(t0)
|
||||
#endif
|
||||
|
||||
li t1, 0xA0800041
|
||||
sw t1, EBU_ADDSEL2(t0)
|
||||
|
||||
/* Need to initialize CS1 too, so as to to prevent overlapping with
|
||||
* Flash bank 1.
|
||||
*/
|
||||
li t1, 0xBE0000F1
|
||||
sw t1, EBU_ADDSEL1(t0)
|
||||
|
||||
#if CPU_CLOCK_RATE==150000000 /* 150 MHz clock for the MIPS core */
|
||||
li t1, 0x684143FD
|
||||
#else /* 100 MHz */
|
||||
li t1, 0x684142BD
|
||||
#endif
|
||||
sw t1, EBU_BUSCON1(t0)
|
||||
|
||||
#if CPU_CLOCK_RATE==150000000 /* 150 MHz clock for the MIPS core */
|
||||
li t0, CGU_MODUL_BASE
|
||||
li t1, 0x80000017
|
||||
sw t1, CGU_DIVCR(t0)
|
||||
li t1, 0xC00B0001
|
||||
sw t1, CGU_PLL1CR(t0)
|
||||
lui t2, 0x8000
|
||||
b1:
|
||||
lw t1, CGU_PLL1SR(t0)
|
||||
and t1, t1, t2
|
||||
beq t1, zero, b1
|
||||
li t1, 0x80000001
|
||||
sw t1, CGU_MUXCR(t0)
|
||||
#endif
|
||||
|
||||
/* SDRAM Initialization.
|
||||
*/
|
||||
li t0, MC_MODUL_BASE
|
||||
|
||||
/* Clear Error log registers */
|
||||
sw zero, MC_ERRCAUSE(t0)
|
||||
sw zero, MC_ERRADDR(t0)
|
||||
|
||||
/* Set clock ratio to 1:1 */
|
||||
li t1, 0x03 /* clkrat=1:1, rddel=3 */
|
||||
sw t1, MC_IOGP(t0)
|
||||
|
||||
/* Clear Power-down registers */
|
||||
sw zero, MC_SELFRFSH(t0)
|
||||
|
||||
/* Set CAS Latency */
|
||||
li t1, 0x00000020 /* CL = 2 */
|
||||
sw t1, MC_MRSCODE(t0)
|
||||
|
||||
/* Set word width to 16 bit */
|
||||
li t1, 0x2
|
||||
sw t1, MC_CFGDW(t0)
|
||||
|
||||
/* Set CS0 to SDRAM parameters */
|
||||
li t1, 0x000014C9
|
||||
sw t1, MC_CFGPB0(t0)
|
||||
|
||||
/* Set SDRAM latency parameters */
|
||||
li t1, 0x00026325 /* BC PC100 */
|
||||
sw t1, MC_LATENCY(t0)
|
||||
|
||||
/* Set SDRAM refresh rate */
|
||||
li t1, 0x00000C30 /* 4K/64ms @ 100MHz */
|
||||
sw t1, MC_TREFRESH(t0)
|
||||
|
||||
/* Finally enable the controller */
|
||||
li t1, 1
|
||||
sw t1, MC_CTRLENA(t0)
|
||||
|
||||
j ra
|
||||
nop
|
||||
|
64
board/incaip/u-boot.lds
Normal file
64
board/incaip/u-boot.lds
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Wolfgang Denk 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
|
||||
*/
|
||||
|
||||
/*
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
_gp = ALIGN(16);
|
||||
|
||||
__got_start = .;
|
||||
.got : { *(.got) }
|
||||
__got_end = .;
|
||||
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
uboot_end_data = .;
|
||||
num_got_entries = (__got_end - __got_start) >> 2;
|
||||
|
||||
. = ALIGN(4);
|
||||
.sbss : { *(.sbss) }
|
||||
.bss : { *(.bss) }
|
||||
uboot_end = .;
|
||||
}
|
44
cpu/mips/Makefile
Normal file
44
cpu/mips/Makefile
Normal file
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# (C) Copyright 2003
|
||||
# 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 = interrupts.o cpu.o incaip_clock.o serial.o
|
||||
SOBJS = incaip_wdt.o cache.o
|
||||
|
||||
all: .depend $(START) $(LIB)
|
||||
|
||||
$(LIB): $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $(OBJS) $(SOBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
265
cpu/mips/cache.S
Normal file
265
cpu/mips/cache.S
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* Cache-handling routined for MIPS 4K CPUs
|
||||
*
|
||||
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/cacheops.h>
|
||||
|
||||
|
||||
/* 16KB is the maximum size of instruction and data caches on
|
||||
* MIPS 4K.
|
||||
*/
|
||||
#define MIPS_MAX_CACHE_SIZE 0x4000
|
||||
|
||||
|
||||
/*
|
||||
* cacheop macro to automate cache operations
|
||||
* first some helpers...
|
||||
*/
|
||||
#define _mincache(size, maxsize) \
|
||||
bltu size,maxsize,9f ; \
|
||||
move size,maxsize ; \
|
||||
9:
|
||||
|
||||
#define _align(minaddr, maxaddr, linesize) \
|
||||
.set noat ; \
|
||||
subu AT,linesize,1 ; \
|
||||
not AT ; \
|
||||
and minaddr,AT ; \
|
||||
addu maxaddr,-1 ; \
|
||||
and maxaddr,AT ; \
|
||||
.set at
|
||||
|
||||
/* general operations */
|
||||
#define doop1(op1) \
|
||||
cache op1,0(a0)
|
||||
#define doop2(op1, op2) \
|
||||
cache op1,0(a0) ; \
|
||||
nop ; \
|
||||
cache op2,0(a0)
|
||||
|
||||
/* specials for cache initialisation */
|
||||
#define doop1lw(op1) \
|
||||
lw zero,0(a0)
|
||||
#define doop1lw1(op1) \
|
||||
cache op1,0(a0) ; \
|
||||
lw zero,0(a0) ; \
|
||||
cache op1,0(a0)
|
||||
#define doop121(op1,op2) \
|
||||
cache op1,0(a0) ; \
|
||||
nop; \
|
||||
cache op2,0(a0) ; \
|
||||
nop; \
|
||||
cache op1,0(a0)
|
||||
|
||||
#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
|
||||
.set noreorder ; \
|
||||
10: doop##tag##ops ; \
|
||||
bne minaddr,maxaddr,10b ; \
|
||||
add minaddr,linesize ; \
|
||||
.set reorder
|
||||
|
||||
/* finally the cache operation macros */
|
||||
#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
|
||||
blez n,11f ; \
|
||||
addu n,kva ; \
|
||||
_align(kva, n, cacheLineSize) ; \
|
||||
_oploopn(kva, n, cacheLineSize, tag, ops) ; \
|
||||
11:
|
||||
|
||||
#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
|
||||
_mincache(n, cacheSize); \
|
||||
blez n,11f ; \
|
||||
addu n,kva ; \
|
||||
_align(kva, n, cacheLineSize) ; \
|
||||
_oploopn(kva, n, cacheLineSize, tag, ops) ; \
|
||||
11:
|
||||
|
||||
#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
|
||||
vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
|
||||
|
||||
#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
|
||||
icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* mips_cache_reset - low level initialisation of the primary caches
|
||||
*
|
||||
* This routine initialises the primary caches to ensure that they
|
||||
* have good parity. It must be called by the ROM before any cached locations
|
||||
* are used to prevent the possibility of data with bad parity being written to
|
||||
* memory.
|
||||
* To initialise the instruction cache it is essential that a source of data
|
||||
* with good parity is available. This routine
|
||||
* will initialise an area of memory starting at location zero to be used as
|
||||
* a source of parity.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
*/
|
||||
.globl mips_cache_reset
|
||||
.ent mips_cache_reset
|
||||
mips_cache_reset:
|
||||
|
||||
li t2, CFG_ICACHE_SIZE
|
||||
li t3, CFG_DCACHE_SIZE
|
||||
li t4, CFG_CACHELINE_SIZE
|
||||
move t5, t4
|
||||
|
||||
|
||||
li v0, MIPS_MAX_CACHE_SIZE
|
||||
|
||||
/* Now clear that much memory starting from zero.
|
||||
*/
|
||||
|
||||
li a0, KSEG1
|
||||
addu a1, a0, v0
|
||||
|
||||
2: sw zero, 0(a0)
|
||||
sw zero, 4(a0)
|
||||
sw zero, 8(a0)
|
||||
sw zero, 12(a0)
|
||||
sw zero, 16(a0)
|
||||
sw zero, 20(a0)
|
||||
sw zero, 24(a0)
|
||||
sw zero, 28(a0)
|
||||
addu a0, 32
|
||||
bltu a0, a1, 2b
|
||||
|
||||
/* Set invalid tag.
|
||||
*/
|
||||
|
||||
mtc0 zero, CP0_TAGLO
|
||||
|
||||
/*
|
||||
* The caches are probably in an indeterminate state,
|
||||
* so we force good parity into them by doing an
|
||||
* invalidate, load/fill, invalidate for each line.
|
||||
*/
|
||||
|
||||
/* Assume bottom of RAM will generate good parity for the cache.
|
||||
*/
|
||||
|
||||
li a0, K0BASE
|
||||
move a2, t2 # icacheSize
|
||||
move a3, t4 # icacheLineSize
|
||||
move a1, a2
|
||||
icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
|
||||
|
||||
/* To support Orion/R4600, we initialise the data cache in 3 passes.
|
||||
*/
|
||||
|
||||
/* 1: initialise dcache tags.
|
||||
*/
|
||||
|
||||
li a0, K0BASE
|
||||
move a2, t3 # dcacheSize
|
||||
move a3, t5 # dcacheLineSize
|
||||
move a1, a2
|
||||
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
|
||||
|
||||
/* 2: fill dcache.
|
||||
*/
|
||||
|
||||
li a0, K0BASE
|
||||
move a2, t3 # dcacheSize
|
||||
move a3, t5 # dcacheLineSize
|
||||
move a1, a2
|
||||
icacheopn(a0,a1,a2,a3,1lw,(dummy))
|
||||
|
||||
/* 3: clear dcache tags.
|
||||
*/
|
||||
|
||||
li a0, K0BASE
|
||||
move a2, t3 # dcacheSize
|
||||
move a3, t5 # dcacheLineSize
|
||||
move a1, a2
|
||||
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
|
||||
|
||||
j ra
|
||||
.end mips_cache_reset
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* dcache_status - get cache status
|
||||
*
|
||||
* RETURNS: 0 - cache disabled; 1 - cache enabled
|
||||
*
|
||||
*/
|
||||
.globl dcache_status
|
||||
.ent dcache_status
|
||||
dcache_status:
|
||||
|
||||
mfc0 v0, CP0_CONFIG
|
||||
andi v0, v0, 1
|
||||
j ra
|
||||
|
||||
.end dcache_status
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* dcache_disable - disable cache
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
*/
|
||||
.globl dcache_disable
|
||||
.ent dcache_disable
|
||||
dcache_disable:
|
||||
|
||||
mfc0 t0, CP0_CONFIG
|
||||
li t1, -8
|
||||
and t0, t0, t1
|
||||
ori t0, t0, CONF_CM_UNCACHED
|
||||
mtc0 t0, CP0_CONFIG
|
||||
j ra
|
||||
|
||||
.end dcache_disable
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* mips_cache_lock - lock RAM area pointed to by a0 in cache.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
*/
|
||||
.globl mips_cache_lock
|
||||
.ent mips_cache_lock
|
||||
mips_cache_lock:
|
||||
li a1, K0BASE - CFG_DCACHE_SIZE
|
||||
addu a0, a1
|
||||
li a2, CFG_DCACHE_SIZE
|
||||
li a3, CFG_CACHELINE_SIZE
|
||||
move a1, a2
|
||||
icacheop(a0,a1,a2,a3,0x1d)
|
||||
|
||||
j ra
|
||||
.end mips_cache_lock
|
||||
|
25
cpu/mips/config.mk
Normal file
25
cpu/mips/config.mk
Normal file
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# (C) Copyright 2003
|
||||
# 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
|
||||
#
|
||||
|
||||
PLATFORM_CPPFLAGS += -mcpu=4kc -EB -mabicalls
|
||||
|
41
cpu/mips/cpu.c
Normal file
41
cpu/mips/cpu.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/inca-ip.h>
|
||||
|
||||
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
#ifdef CONFIG_INCA_IP
|
||||
*INCA_IP_WDT_RST_REQ = 0x3f;
|
||||
#endif
|
||||
fprintf(stderr, "*** reset failed ***\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flush_cache (ulong start_addr, ulong size)
|
||||
{
|
||||
|
||||
}
|
||||
|
107
cpu/mips/incaip_clock.c
Normal file
107
cpu/mips/incaip_clock.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <asm/inca-ip.h>
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* get_cpuclk - returns the frequency of the CPU.
|
||||
*
|
||||
* Gets the value directly from the INCA-IP hardware.
|
||||
*
|
||||
* RETURNS:
|
||||
* 150.000.000 for 150 MHz
|
||||
* 130.000.000. for 130 Mhz
|
||||
* 100.000.000. for 100 Mhz
|
||||
* NOTE:
|
||||
* This functions should be used by the hardware driver to get the correct
|
||||
* frequency of the CPU. Don't use the macros, which are set to init the CPU
|
||||
* frequency in the ROM code.
|
||||
*/
|
||||
uint incaip_get_cpuclk(void)
|
||||
{
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* CPU Clock Input Multiplexer (MUX I) */
|
||||
/* Multiplexer MUX I selects the maximum input clock to the CPU. */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
if (*((volatile ulong*)INCA_IP_CGU_CGU_MUXCR) & INCA_IP_CGU_CGU_MUXCR_MUXI)
|
||||
{
|
||||
/* MUX I set to 150 MHz clock */
|
||||
return 150000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MUX I set to 100/133 MHz clock */
|
||||
if (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0x40)
|
||||
{
|
||||
/* Division value is 1/3, maximum CPU operating */
|
||||
/* frequency is 133.3 MHz */
|
||||
return 130000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Division value is 1/4, maximum CPU operating */
|
||||
/* frequency is 100 MHz */
|
||||
return 100000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* get_fpiclk - returns the frequency of the FPI bus.
|
||||
*
|
||||
* Gets the value directly from the INCA-IP hardware.
|
||||
*
|
||||
* RETURNS: Frquency in Hz
|
||||
*
|
||||
* NOTE:
|
||||
* This functions should be used by the hardware driver to get the correct
|
||||
* frequency of the CPU. Don't use the macros, which are set to init the CPU
|
||||
* frequency in the ROM code.
|
||||
* The calculation for the
|
||||
*/
|
||||
uint incaip_get_fpiclk(void)
|
||||
{
|
||||
uint clkCPU;
|
||||
|
||||
clkCPU = incaip_get_cpuclk();
|
||||
|
||||
switch (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0xC)
|
||||
{
|
||||
case 0x4:
|
||||
return clkCPU >> 1; /* devided by 2 */
|
||||
break;
|
||||
case 0x8:
|
||||
return clkCPU >> 2; /* devided by 4 */
|
||||
break;
|
||||
default:
|
||||
return clkCPU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
73
cpu/mips/incaip_wdt.S
Normal file
73
cpu/mips/incaip_wdt.S
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* INCA-IP Watchdog timer management code.
|
||||
*
|
||||
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
|
||||
#define WD_BASE 0xb8000000
|
||||
#define WD_CON0(value) 0x0020(value)
|
||||
#define WD_CON1(value) 0x0024(value)
|
||||
#define WD_DISABLE 0x00000008
|
||||
#define WD_ENABLE 0x00000000
|
||||
#define WD_WRITE_PW 0xFFFC00F8
|
||||
#define WD_WRITE_ENDINIT 0xFFFC00F3
|
||||
#define WD_WRITE_INIT 0xFFFC00F2
|
||||
|
||||
|
||||
.globl disable_incaip_wdt
|
||||
disable_incaip_wdt:
|
||||
li t0, WD_BASE
|
||||
|
||||
/* Calculate password.
|
||||
*/
|
||||
lw t2, WD_CON1(t0)
|
||||
and t2, 0xC
|
||||
|
||||
lw t3, WD_CON0(t0)
|
||||
and t3, 0xFFFFFF01
|
||||
|
||||
or t3, t2
|
||||
or t3, 0xF0
|
||||
|
||||
sw t3, WD_CON0(t0) /* write password */
|
||||
|
||||
/* Clear ENDINIT.
|
||||
*/
|
||||
li t1, WD_WRITE_INIT
|
||||
sw t1, WD_CON0(t0)
|
||||
|
||||
|
||||
li t1, WD_DISABLE
|
||||
sw t1, WD_CON1(t0) /* disable watchdog */
|
||||
li t1, WD_WRITE_PW
|
||||
sw t1, WD_CON0(t0) /* write password */
|
||||
li t1, WD_WRITE_ENDINIT
|
||||
sw t1, WD_CON0(t0) /* end command */
|
||||
|
||||
j ra
|
||||
nop
|
||||
|
34
cpu/mips/interrupts.c
Normal file
34
cpu/mips/interrupts.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
}
|
||||
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
282
cpu/mips/serial.c
Normal file
282
cpu/mips/serial.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* (INCA) ASC UART support
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/inca-ip.h>
|
||||
#include "serial.h"
|
||||
|
||||
#define SET_BIT(reg, mask) reg |= (mask)
|
||||
#define CLEAR_BIT(reg, mask) reg &= (~mask)
|
||||
#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
|
||||
#define SET_BITS(reg, mask) SET_BIT(reg, mask)
|
||||
#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
|
||||
|
||||
extern uint incaip_get_fpiclk(void);
|
||||
|
||||
static int serial_setopt (void);
|
||||
|
||||
/* pointer to ASC register base address */
|
||||
static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* serial_init - initialize a INCAASC channel
|
||||
*
|
||||
* This routine initializes the number of data bits, parity
|
||||
* and set the selected baud rate. Interrupts are disabled.
|
||||
* Set the modem control signals if the option is selected.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*/
|
||||
|
||||
int serial_init (void)
|
||||
{
|
||||
/* we have to set PMU.EN13 bit to enable an ASC device*/
|
||||
INCAASC_PMU_ENABLE(13);
|
||||
|
||||
/* and we have to set CLC register*/
|
||||
CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
|
||||
SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
|
||||
|
||||
/* initialy we are in async mode */
|
||||
pAsc->asc_con = ASCCON_M_8ASYNC;
|
||||
|
||||
/* select input port */
|
||||
pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
|
||||
|
||||
/* TXFIFO's filling level */
|
||||
SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
|
||||
ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
|
||||
/* enable TXFIFO */
|
||||
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
|
||||
|
||||
/* RXFIFO's filling level */
|
||||
SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
|
||||
ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
|
||||
/* enable RXFIFO */
|
||||
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
|
||||
|
||||
/* enable error signals */
|
||||
SET_BIT(pAsc->asc_con, ASCCON_FEN);
|
||||
SET_BIT(pAsc->asc_con, ASCCON_OEN);
|
||||
|
||||
/* acknowledge ASC interrupts */
|
||||
ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
|
||||
|
||||
/* disable ASC interrupts */
|
||||
ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
|
||||
|
||||
/* set FIFOs into the transparent mode */
|
||||
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
|
||||
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
|
||||
|
||||
/* set baud rate */
|
||||
serial_setbrg();
|
||||
|
||||
/* set the options */
|
||||
serial_setopt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_setbrg (void)
|
||||
{
|
||||
ulong uiReloadValue, fdv;
|
||||
ulong f_ASC;
|
||||
|
||||
f_ASC = incaip_get_fpiclk();
|
||||
|
||||
#ifndef INCAASC_USE_FDV
|
||||
fdv = 2;
|
||||
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
|
||||
#else
|
||||
fdv = INCAASC_FDV_HIGH_BAUDRATE;
|
||||
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
|
||||
#endif /* INCAASC_USE_FDV */
|
||||
|
||||
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
|
||||
{
|
||||
#ifndef INCAASC_USE_FDV
|
||||
fdv = 3;
|
||||
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
|
||||
#else
|
||||
fdv = INCAASC_FDV_LOW_BAUDRATE;
|
||||
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
|
||||
#endif /* INCAASC_USE_FDV */
|
||||
|
||||
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
|
||||
{
|
||||
return; /* can't impossibly generate that baud rate */
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable Baud Rate Generator; BG should only be written when R=0 */
|
||||
CLEAR_BIT(pAsc->asc_con, ASCCON_R);
|
||||
|
||||
#ifndef INCAASC_USE_FDV
|
||||
/*
|
||||
* Disable Fractional Divider (FDE)
|
||||
* Divide clock by reload-value + constant (BRS)
|
||||
*/
|
||||
/* FDE = 0 */
|
||||
CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
|
||||
|
||||
if ( fdv == 2 )
|
||||
CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
|
||||
else
|
||||
SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
|
||||
|
||||
#else /* INCAASC_USE_FDV */
|
||||
|
||||
/* Enable Fractional Divider */
|
||||
SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
|
||||
|
||||
/* Set fractional divider value */
|
||||
pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
|
||||
|
||||
#endif /* INCAASC_USE_FDV */
|
||||
|
||||
/* Set reload value in BG */
|
||||
pAsc->asc_bg = uiReloadValue;
|
||||
|
||||
/* Enable Baud Rate Generator */
|
||||
SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* serial_setopt - set the serial options
|
||||
*
|
||||
* Set the channel operating mode to that specified. Following options
|
||||
* are supported: CREAD, CSIZE, PARENB, and PARODD.
|
||||
*
|
||||
* Note, this routine disables the transmitter. The calling routine
|
||||
* may have to re-enable it.
|
||||
*
|
||||
* RETURNS:
|
||||
* Returns 0 to indicate success, otherwise -1 is returned
|
||||
*/
|
||||
|
||||
static int serial_setopt (void)
|
||||
{
|
||||
ulong con;
|
||||
|
||||
switch ( ASC_OPTIONS & ASCOPT_CSIZE )
|
||||
{
|
||||
/* 7-bit-data */
|
||||
case ASCOPT_CS7:
|
||||
con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
|
||||
break;
|
||||
|
||||
/* 8-bit-data */
|
||||
case ASCOPT_CS8:
|
||||
if ( ASC_OPTIONS & ASCOPT_PARENB )
|
||||
con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
|
||||
else
|
||||
con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
|
||||
break;
|
||||
|
||||
/*
|
||||
* only 7 and 8-bit frames are supported
|
||||
* if we don't use IOCTL extensions
|
||||
*/
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ASC_OPTIONS & ASCOPT_STOPB )
|
||||
SET_BIT(con, ASCCON_STP); /* 2 stop bits */
|
||||
else
|
||||
CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
|
||||
|
||||
if ( ASC_OPTIONS & ASCOPT_PARENB )
|
||||
SET_BIT(con, ASCCON_PEN); /* enable parity checking */
|
||||
else
|
||||
CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
|
||||
|
||||
if ( ASC_OPTIONS & ASCOPT_PARODD )
|
||||
SET_BIT(con, ASCCON_ODD); /* odd parity */
|
||||
else
|
||||
CLEAR_BIT(con, ASCCON_ODD); /* even parity */
|
||||
|
||||
if ( ASC_OPTIONS & ASCOPT_CREAD )
|
||||
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
|
||||
|
||||
pAsc->asc_con |= con;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_putc (const char c)
|
||||
{
|
||||
uint txFl = 0;
|
||||
|
||||
if (c == '\n') serial_putc ('\r');
|
||||
|
||||
/* check do we have a free space in the TX FIFO */
|
||||
/* get current filling level */
|
||||
do
|
||||
{
|
||||
txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
|
||||
}
|
||||
while ( txFl == INCAASC_TXFIFO_FULL );
|
||||
|
||||
pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
|
||||
/* check for errors */
|
||||
if ( pAsc->asc_con & ASCCON_OE )
|
||||
{
|
||||
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void serial_puts (const char *s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
serial_putc (*s++);
|
||||
}
|
||||
}
|
||||
|
||||
int serial_getc (void)
|
||||
{
|
||||
ulong symbol_mask;
|
||||
char c;
|
||||
|
||||
while (!serial_tstc());
|
||||
|
||||
symbol_mask =
|
||||
((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
|
||||
|
||||
c = (char)(pAsc->asc_rbuf & symbol_mask);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int serial_tstc (void)
|
||||
{
|
||||
int res = 1;
|
||||
|
||||
if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
|
||||
{
|
||||
res = 0;
|
||||
}
|
||||
else if ( pAsc->asc_con & ASCCON_FE )
|
||||
{
|
||||
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
|
||||
res = 0;
|
||||
}
|
||||
else if ( pAsc->asc_con & ASCCON_PE )
|
||||
{
|
||||
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
|
||||
res = 0;
|
||||
}
|
||||
else if ( pAsc->asc_con & ASCCON_OE )
|
||||
{
|
||||
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
178
cpu/mips/serial.h
Normal file
178
cpu/mips/serial.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/* incaAscSio.h - (INCA) ASC UART tty driver header */
|
||||
|
||||
#ifndef __INCincaAscSioh
|
||||
#define __INCincaAscSioh
|
||||
|
||||
#include <asm/inca-ip.h>
|
||||
|
||||
/* channel operating modes */
|
||||
#define ASCOPT_CSIZE 0x00000003
|
||||
#define ASCOPT_CS7 0x00000001
|
||||
#define ASCOPT_CS8 0x00000002
|
||||
#define ASCOPT_PARENB 0x00000004
|
||||
#define ASCOPT_STOPB 0x00000008
|
||||
#define ASCOPT_PARODD 0x00000010
|
||||
#define ASCOPT_CREAD 0x00000020
|
||||
|
||||
#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
|
||||
|
||||
/* ASC input select (0 or 1) */
|
||||
#define CONSOLE_TTY 0
|
||||
|
||||
/* use fractional divider for baudrate settings */
|
||||
#define INCAASC_USE_FDV
|
||||
|
||||
#ifdef INCAASC_USE_FDV
|
||||
#define INCAASC_FDV_LOW_BAUDRATE 71
|
||||
#define INCAASC_FDV_HIGH_BAUDRATE 453
|
||||
#endif /*INCAASC_USE_FDV*/
|
||||
|
||||
|
||||
#define INCAASC_TXFIFO_FL 1
|
||||
#define INCAASC_RXFIFO_FL 1
|
||||
#define INCAASC_TXFIFO_FULL 16
|
||||
|
||||
/* interrupt lines masks for the ASC device interrupts*/
|
||||
/* change these macroses if it's necessary */
|
||||
#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */
|
||||
|
||||
#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */
|
||||
#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */
|
||||
#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */
|
||||
#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/
|
||||
|
||||
/* interrupt controller access macros */
|
||||
#define ASC_INTERRUPTS_ENABLE(X) \
|
||||
*((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X;
|
||||
#define ASC_INTERRUPTS_DISABLE(X) \
|
||||
*((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X;
|
||||
#define ASC_INTERRUPTS_CLEAR(X) \
|
||||
*((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X;
|
||||
|
||||
/* CLC register's bits and bitfields */
|
||||
#define ASCCLC_DISR 0x00000001
|
||||
#define ASCCLC_DISS 0x00000002
|
||||
#define ASCCLC_RMCMASK 0x0000FF00
|
||||
#define ASCCLC_RMCOFFSET 8
|
||||
|
||||
/* CON register's bits and bitfields */
|
||||
#define ASCCON_MODEMASK 0x0007
|
||||
#define ASCCON_M_8SYNC 0x0
|
||||
#define ASCCON_M_8ASYNC 0x1
|
||||
#define ASCCON_M_8IRDAASYNC 0x2
|
||||
#define ASCCON_M_7ASYNCPAR 0x3
|
||||
#define ASCCON_M_9ASYNC 0x4
|
||||
#define ASCCON_M_8WAKEUPASYNC 0x5
|
||||
#define ASCCON_M_8ASYNCPAR 0x7
|
||||
#define ASCCON_STP 0x0008
|
||||
#define ASCCON_REN 0x0010
|
||||
#define ASCCON_PEN 0x0020
|
||||
#define ASCCON_FEN 0x0040
|
||||
#define ASCCON_OEN 0x0080
|
||||
#define ASCCON_PE 0x0100
|
||||
#define ASCCON_FE 0x0200
|
||||
#define ASCCON_OE 0x0400
|
||||
#define ASCCON_FDE 0x0800
|
||||
#define ASCCON_ODD 0x1000
|
||||
#define ASCCON_BRS 0x2000
|
||||
#define ASCCON_LB 0x4000
|
||||
#define ASCCON_R 0x8000
|
||||
|
||||
/* WHBCON register's bits and bitfields */
|
||||
#define ASCWHBCON_CLRREN 0x0010
|
||||
#define ASCWHBCON_SETREN 0x0020
|
||||
#define ASCWHBCON_CLRPE 0x0100
|
||||
#define ASCWHBCON_CLRFE 0x0200
|
||||
#define ASCWHBCON_CLROE 0x0400
|
||||
#define ASCWHBCON_SETPE 0x0800
|
||||
#define ASCWHBCON_SETFE 0x1000
|
||||
#define ASCWHBCON_SETOE 0x2000
|
||||
|
||||
/* ABCON register's bits and bitfields */
|
||||
#define ASCABCON_ABEN 0x0001
|
||||
#define ASCABCON_AUREN 0x0002
|
||||
#define ASCABCON_ABSTEN 0x0004
|
||||
#define ASCABCON_ABDETEN 0x0008
|
||||
#define ASCABCON_FCDETEN 0x0010
|
||||
#define ASCABCON_EMMASK 0x0300
|
||||
#define ASCABCON_EMOFF 8
|
||||
#define ASCABCON_EM_DISAB 0x0
|
||||
#define ASCABCON_EM_DURAB 0x1
|
||||
#define ASCABCON_EM_ALWAYS 0x2
|
||||
#define ASCABCON_TXINV 0x0400
|
||||
#define ASCABCON_RXINV 0x0800
|
||||
|
||||
/* FDV register mask, offset and bitfields*/
|
||||
#define ASCFDV_VALUE_MASK 0x000001FF
|
||||
|
||||
/* WHBABCON register's bits and bitfields */
|
||||
#define ASCWHBABCON_SETABEN 0x0001
|
||||
#define ASCWHBABCON_CLRABEN 0x0002
|
||||
|
||||
/* ABSTAT register's bits and bitfields */
|
||||
#define ASCABSTAT_FCSDET 0x0001
|
||||
#define ASCABSTAT_FCCDET 0x0002
|
||||
#define ASCABSTAT_SCSDET 0x0004
|
||||
#define ASCABSTAT_SCCDET 0x0008
|
||||
#define ASCABSTAT_DETWAIT 0x0010
|
||||
|
||||
/* WHBABSTAT register's bits and bitfields */
|
||||
#define ASCWHBABSTAT_CLRFCSDET 0x0001
|
||||
#define ASCWHBABSTAT_SETFCSDET 0x0002
|
||||
#define ASCWHBABSTAT_CLRFCCDET 0x0004
|
||||
#define ASCWHBABSTAT_SETFCCDET 0x0008
|
||||
#define ASCWHBABSTAT_CLRSCSDET 0x0010
|
||||
#define ASCWHBABSTAT_SETSCSDET 0x0020
|
||||
#define ASCWHBABSTAT_SETSCCDET 0x0040
|
||||
#define ASCWHBABSTAT_CLRSCCDET 0x0080
|
||||
#define ASCWHBABSTAT_CLRDETWAIT 0x0100
|
||||
#define ASCWHBABSTAT_SETDETWAIT 0x0200
|
||||
|
||||
/* TXFCON register's bits and bitfields */
|
||||
#define ASCTXFCON_TXFEN 0x0001
|
||||
#define ASCTXFCON_TXFFLU 0x0002
|
||||
#define ASCTXFCON_TXTMEN 0x0004
|
||||
#define ASCTXFCON_TXFITLMASK 0x3F00
|
||||
#define ASCTXFCON_TXFITLOFF 8
|
||||
|
||||
/* RXFCON register's bits and bitfields */
|
||||
#define ASCRXFCON_RXFEN 0x0001
|
||||
#define ASCRXFCON_RXFFLU 0x0002
|
||||
#define ASCRXFCON_RXTMEN 0x0004
|
||||
#define ASCRXFCON_RXFITLMASK 0x3F00
|
||||
#define ASCRXFCON_RXFITLOFF 8
|
||||
|
||||
/* FSTAT register's bits and bitfields */
|
||||
#define ASCFSTAT_RXFFLMASK 0x003F
|
||||
#define ASCFSTAT_TXFFLMASK 0x3F00
|
||||
#define ASCFSTAT_TXFFLOFF 8
|
||||
|
||||
#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT);
|
||||
|
||||
typedef struct /* incaAsc_t */
|
||||
{
|
||||
volatile unsigned long asc_clc; /*0x0000*/
|
||||
volatile unsigned long asc_pisel; /*0x0004*/
|
||||
volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/
|
||||
volatile unsigned long asc_con; /*0x0010*/
|
||||
volatile unsigned long asc_bg; /*0x0014*/
|
||||
volatile unsigned long asc_fdv; /*0x0018*/
|
||||
volatile unsigned long asc_pmw; /* not used */ /*0x001C*/
|
||||
volatile unsigned long asc_tbuf; /*0x0020*/
|
||||
volatile unsigned long asc_rbuf; /*0x0024*/
|
||||
volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/
|
||||
volatile unsigned long asc_abcon; /*0x0030*/
|
||||
volatile unsigned long asc_abstat; /* not used */ /*0x0034*/
|
||||
volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/
|
||||
volatile unsigned long asc_rxfcon; /*0x0040*/
|
||||
volatile unsigned long asc_txfcon; /*0x0044*/
|
||||
volatile unsigned long asc_fstat; /*0x0048*/
|
||||
volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/
|
||||
volatile unsigned long asc_whbcon; /*0x0050*/
|
||||
volatile unsigned long asc_whbabcon; /*0x0054*/
|
||||
volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/
|
||||
|
||||
} incaAsc_t;
|
||||
|
||||
#endif /* __INCincaAscSioh */
|
||||
|
350
cpu/mips/start.S
Normal file
350
cpu/mips/start.S
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Startup Code for MIPS32 CPU-core
|
||||
*
|
||||
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
|
||||
#define RVECENT(f,n) \
|
||||
b f; nop
|
||||
#define XVECENT(f,bev) \
|
||||
b f ; \
|
||||
li k0,bev
|
||||
|
||||
.set noreorder
|
||||
|
||||
.globl _start
|
||||
.text
|
||||
_start:
|
||||
RVECENT(reset,0) /* U-boot entry point */
|
||||
RVECENT(reset,1) /* software reboot */
|
||||
#ifdef CONFIG_INCA_IP
|
||||
.word 0x000020C4 /* EBU init code, fetched during booting */
|
||||
.word 0x00000000 /* phase of the flash */
|
||||
#else
|
||||
RVECENT(romReserved,2)
|
||||
#endif
|
||||
RVECENT(romReserved,3)
|
||||
RVECENT(romReserved,4)
|
||||
RVECENT(romReserved,5)
|
||||
RVECENT(romReserved,6)
|
||||
RVECENT(romReserved,7)
|
||||
RVECENT(romReserved,8)
|
||||
RVECENT(romReserved,9)
|
||||
RVECENT(romReserved,10)
|
||||
RVECENT(romReserved,11)
|
||||
RVECENT(romReserved,12)
|
||||
RVECENT(romReserved,13)
|
||||
RVECENT(romReserved,14)
|
||||
RVECENT(romReserved,15)
|
||||
RVECENT(romReserved,16)
|
||||
RVECENT(romReserved,17)
|
||||
RVECENT(romReserved,18)
|
||||
RVECENT(romReserved,19)
|
||||
RVECENT(romReserved,20)
|
||||
RVECENT(romReserved,21)
|
||||
RVECENT(romReserved,22)
|
||||
RVECENT(romReserved,23)
|
||||
RVECENT(romReserved,24)
|
||||
RVECENT(romReserved,25)
|
||||
RVECENT(romReserved,26)
|
||||
RVECENT(romReserved,27)
|
||||
RVECENT(romReserved,28)
|
||||
RVECENT(romReserved,29)
|
||||
RVECENT(romReserved,30)
|
||||
RVECENT(romReserved,31)
|
||||
RVECENT(romReserved,32)
|
||||
RVECENT(romReserved,33)
|
||||
RVECENT(romReserved,34)
|
||||
RVECENT(romReserved,35)
|
||||
RVECENT(romReserved,36)
|
||||
RVECENT(romReserved,37)
|
||||
RVECENT(romReserved,38)
|
||||
RVECENT(romReserved,39)
|
||||
RVECENT(romReserved,40)
|
||||
RVECENT(romReserved,41)
|
||||
RVECENT(romReserved,42)
|
||||
RVECENT(romReserved,43)
|
||||
RVECENT(romReserved,44)
|
||||
RVECENT(romReserved,45)
|
||||
RVECENT(romReserved,46)
|
||||
RVECENT(romReserved,47)
|
||||
RVECENT(romReserved,48)
|
||||
RVECENT(romReserved,49)
|
||||
RVECENT(romReserved,50)
|
||||
RVECENT(romReserved,51)
|
||||
RVECENT(romReserved,52)
|
||||
RVECENT(romReserved,53)
|
||||
RVECENT(romReserved,54)
|
||||
RVECENT(romReserved,55)
|
||||
RVECENT(romReserved,56)
|
||||
RVECENT(romReserved,57)
|
||||
RVECENT(romReserved,58)
|
||||
RVECENT(romReserved,59)
|
||||
RVECENT(romReserved,60)
|
||||
RVECENT(romReserved,61)
|
||||
RVECENT(romReserved,62)
|
||||
RVECENT(romReserved,63)
|
||||
XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
|
||||
RVECENT(romReserved,65)
|
||||
RVECENT(romReserved,66)
|
||||
RVECENT(romReserved,67)
|
||||
RVECENT(romReserved,68)
|
||||
RVECENT(romReserved,69)
|
||||
RVECENT(romReserved,70)
|
||||
RVECENT(romReserved,71)
|
||||
RVECENT(romReserved,72)
|
||||
RVECENT(romReserved,73)
|
||||
RVECENT(romReserved,74)
|
||||
RVECENT(romReserved,75)
|
||||
RVECENT(romReserved,76)
|
||||
RVECENT(romReserved,77)
|
||||
RVECENT(romReserved,78)
|
||||
RVECENT(romReserved,79)
|
||||
XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
|
||||
RVECENT(romReserved,81)
|
||||
RVECENT(romReserved,82)
|
||||
RVECENT(romReserved,83)
|
||||
RVECENT(romReserved,84)
|
||||
RVECENT(romReserved,85)
|
||||
RVECENT(romReserved,86)
|
||||
RVECENT(romReserved,87)
|
||||
RVECENT(romReserved,88)
|
||||
RVECENT(romReserved,89)
|
||||
RVECENT(romReserved,90)
|
||||
RVECENT(romReserved,91)
|
||||
RVECENT(romReserved,92)
|
||||
RVECENT(romReserved,93)
|
||||
RVECENT(romReserved,94)
|
||||
RVECENT(romReserved,95)
|
||||
XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
|
||||
RVECENT(romReserved,97)
|
||||
RVECENT(romReserved,98)
|
||||
RVECENT(romReserved,99)
|
||||
RVECENT(romReserved,100)
|
||||
RVECENT(romReserved,101)
|
||||
RVECENT(romReserved,102)
|
||||
RVECENT(romReserved,103)
|
||||
RVECENT(romReserved,104)
|
||||
RVECENT(romReserved,105)
|
||||
RVECENT(romReserved,106)
|
||||
RVECENT(romReserved,107)
|
||||
RVECENT(romReserved,108)
|
||||
RVECENT(romReserved,109)
|
||||
RVECENT(romReserved,110)
|
||||
RVECENT(romReserved,111)
|
||||
XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
|
||||
RVECENT(romReserved,113)
|
||||
RVECENT(romReserved,114)
|
||||
RVECENT(romReserved,115)
|
||||
RVECENT(romReserved,116)
|
||||
RVECENT(romReserved,116)
|
||||
RVECENT(romReserved,118)
|
||||
RVECENT(romReserved,119)
|
||||
RVECENT(romReserved,120)
|
||||
RVECENT(romReserved,121)
|
||||
RVECENT(romReserved,122)
|
||||
RVECENT(romReserved,123)
|
||||
RVECENT(romReserved,124)
|
||||
RVECENT(romReserved,125)
|
||||
RVECENT(romReserved,126)
|
||||
RVECENT(romReserved,127)
|
||||
|
||||
/* We hope there are no more reserved vectors!
|
||||
* 128 * 8 == 1024 == 0x400
|
||||
* so this is address R_VEC+0x400 == 0xbfc00400
|
||||
*/
|
||||
.align 4
|
||||
reset:
|
||||
|
||||
/* Clear watch registers.
|
||||
*/
|
||||
mtc0 zero, CP0_WATCHLO
|
||||
mtc0 zero, CP0_WATCHHI
|
||||
|
||||
/* STATUS register */
|
||||
mfc0 k0, CP0_STATUS
|
||||
li k1, ~ST0_IE
|
||||
and k0, k1
|
||||
mtc0 k0, CP0_STATUS
|
||||
|
||||
/* CAUSE register */
|
||||
mtc0 zero, CP0_CAUSE
|
||||
|
||||
/* Init Timer */
|
||||
mtc0 zero, CP0_COUNT
|
||||
mtc0 zero, CP0_COMPARE
|
||||
|
||||
/* CONFIG0 register */
|
||||
li t0, CONF_CM_UNCACHED
|
||||
mtc0 t0, CP0_CONFIG
|
||||
|
||||
#ifdef CONFIG_INCA_IP
|
||||
/* Disable INCA-IP Watchdog.
|
||||
*/
|
||||
bal disable_incaip_wdt
|
||||
nop
|
||||
#endif
|
||||
|
||||
/* Initialize any external memory.
|
||||
*/
|
||||
bal memsetup
|
||||
nop
|
||||
|
||||
/* Initialize caches...
|
||||
*/
|
||||
bal mips_cache_reset
|
||||
nop
|
||||
|
||||
/* ... and enable them.
|
||||
*/
|
||||
li t0, CONF_CM_CACHABLE_NONCOHERENT
|
||||
mtc0 t0, CP0_CONFIG
|
||||
|
||||
|
||||
/* Set up temporary stack.
|
||||
*/
|
||||
li a0, CFG_INIT_SP_OFFSET
|
||||
bal mips_cache_lock
|
||||
nop
|
||||
|
||||
li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
|
||||
la sp, 0(t0)
|
||||
|
||||
/* Initialize GOT pointer.
|
||||
*/
|
||||
bal 1f
|
||||
nop
|
||||
.word _GLOBAL_OFFSET_TABLE_ - 1f + 4
|
||||
1:
|
||||
move gp, ra
|
||||
lw t1, 0(ra)
|
||||
add gp, t1
|
||||
la t9, board_init_f
|
||||
j t9
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* void relocate_code (addr_sp, gd, addr_moni)
|
||||
*
|
||||
* This "function" does not return, instead it continues in RAM
|
||||
* after relocating the monitor code.
|
||||
*
|
||||
* a0 = addr_sp
|
||||
* a1 = gd
|
||||
* a2 = destination address
|
||||
*/
|
||||
.globl relocate_code
|
||||
.ent relocate_code
|
||||
relocate_code:
|
||||
move sp, a0 /* Set new stack pointer */
|
||||
|
||||
/*
|
||||
* Fix GOT pointer:
|
||||
*
|
||||
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
|
||||
*/
|
||||
move t6, gp
|
||||
sub gp, CFG_MONITOR_BASE
|
||||
add gp, a2 /* gp now adjusted */
|
||||
sub t6, gp, t6 /* t6 <-- relocation offset */
|
||||
|
||||
li t0, CFG_MONITOR_BASE
|
||||
add t2, t0, CFG_MONITOR_LEN
|
||||
move t1, a2
|
||||
|
||||
/*
|
||||
* t0 = source address
|
||||
* t1 = target address
|
||||
* t2 = source end address
|
||||
*/
|
||||
1:
|
||||
lw t3, 0(t0)
|
||||
sw t3, 0(t1)
|
||||
addu t0, 4
|
||||
ble t0, t2, 1b
|
||||
addu t1, 4 /* delay slot */
|
||||
|
||||
/* If caches were enabled, we would have to flush them here.
|
||||
*/
|
||||
|
||||
/* Jump to where we've relocated ourselves.
|
||||
*/
|
||||
addi t0, a2, in_ram - _start
|
||||
j t0
|
||||
nop
|
||||
|
||||
.word uboot_end_data
|
||||
.word uboot_end
|
||||
.word num_got_entries
|
||||
|
||||
in_ram:
|
||||
/* Now we want to update GOT.
|
||||
*/
|
||||
lw t3, -4(t0) /* t3 <-- num_got_entries */
|
||||
addi t4, gp, 8 /* Skipping first two entries. */
|
||||
li t2, 2
|
||||
1:
|
||||
lw t1, 0(t4)
|
||||
beqz t1, 2f
|
||||
add t1, t6
|
||||
sw t1, 0(t4)
|
||||
2:
|
||||
addi t2, 1
|
||||
blt t2, t3, 1b
|
||||
addi t4, 4 /* delay slot */
|
||||
|
||||
/* Clear BSS.
|
||||
*/
|
||||
lw t1, -12(t0) /* t1 <-- uboot_end_data */
|
||||
lw t2, -8(t0) /* t2 <-- uboot_end */
|
||||
add t1, t6 /* adjust pointers */
|
||||
add t2, t6
|
||||
|
||||
sub t1, 4
|
||||
1: addi t1, 4
|
||||
bltl t1, t2, 1b
|
||||
sw zero, 0(t1) /* delay slot */
|
||||
|
||||
move a0, a1
|
||||
la t9, board_init_r
|
||||
j t9
|
||||
move a1, a2 /* delay slot */
|
||||
|
||||
.end relocate_code
|
||||
|
||||
|
||||
|
||||
/* Exception handlers.
|
||||
*/
|
||||
romReserved:
|
||||
b romReserved
|
||||
|
||||
romExcHandle:
|
||||
b romExcHandle
|
||||
|
2431
include/asm-mips/inca-ip.h
Normal file
2431
include/asm-mips/inca-ip.h
Normal file
File diff suppressed because it is too large
Load diff
107
include/configs/incaip.h
Normal file
107
include/configs/incaip.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the configuration parameters for the INCA-IP board.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#define CONFIG_MIPS32 1 /* MIPS 4Kc CPU core */
|
||||
#define CONFIG_INCA_IP 1 /* on a INCA-IP Board */
|
||||
|
||||
/* allowed values: 100000000 and 150000000 */
|
||||
#define CPU_CLOCK_RATE 150000000 /* 150 MHz clock for the MIPS core */
|
||||
|
||||
#define CONFIG_BAUDRATE 115200
|
||||
|
||||
#define CFG_SDRAM_BASE 0x80000000
|
||||
|
||||
#define CFG_MALLOC_LEN 128*1024
|
||||
|
||||
#define CFG_BOOTPARAMS_LEN 128*1024
|
||||
|
||||
/* valid baudrates */
|
||||
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
|
||||
|
||||
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_ELF)
|
||||
#include <cmd_confdefs.h>
|
||||
|
||||
/*
|
||||
* Miscellaneous configurable options
|
||||
*/
|
||||
#define CFG_LONGHELP /* undef to save memory */
|
||||
#define CFG_PROMPT "INCA-IP # " /* Monitor Command Prompt */
|
||||
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
|
||||
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
|
||||
#define CFG_HZ (CPU_CLOCK_RATE/2)
|
||||
#define CFG_MAXARGS 16 /* max number of command args*/
|
||||
|
||||
#define CFG_LOAD_ADDR 0x80100000 /* default load address */
|
||||
|
||||
#define CFG_MEMTEST_START 0x80200000
|
||||
#define CFG_MEMTEST_END 0x80800000
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* FLASH and environment organization
|
||||
*/
|
||||
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
|
||||
#define CFG_MAX_FLASH_SECT (128) /* max number of sectors on one chip */
|
||||
|
||||
#define PHYS_FLASH_1 0xb0000000 /* Flash Bank #1 */
|
||||
#define PHYS_FLASH_2 0xb0800000 /* Flash Bank #2 */
|
||||
|
||||
/* The following #defines are needed to get flash environment right */
|
||||
#define CFG_MONITOR_BASE TEXT_BASE
|
||||
#define CFG_MONITOR_LEN (192 << 10)
|
||||
|
||||
#define CFG_INIT_SP_OFFSET 0x400000
|
||||
|
||||
#define CFG_FLASH_BASE PHYS_FLASH_1
|
||||
|
||||
/* timeout values are in ticks */
|
||||
#define CFG_FLASH_ERASE_TOUT (2 * CFG_HZ) /* Timeout for Flash Erase */
|
||||
#define CFG_FLASH_WRITE_TOUT (2 * CFG_HZ) /* Timeout for Flash Write */
|
||||
|
||||
#define CFG_ENV_IS_IN_FLASH 1
|
||||
|
||||
/* Address and size of Primary Environment Sector */
|
||||
#define CFG_ENV_ADDR 0xB0030000
|
||||
#define CFG_ENV_SIZE 0x10000
|
||||
|
||||
#define CONFIG_FLASH_16BIT
|
||||
|
||||
#define CONFIG_NR_DRAM_BANKS 1
|
||||
|
||||
#define CONFIG_INCA_IP_SWITCH
|
||||
#define CONFIG_NET_MULTI
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Cache Configuration
|
||||
*/
|
||||
#define CFG_DCACHE_SIZE 4096
|
||||
#define CFG_ICACHE_SIZE 4096
|
||||
#define CFG_CACHELINE_SIZE 16
|
||||
|
||||
#endif /* __CONFIG_H */
|
44
lib_mips/Makefile
Normal file
44
lib_mips/Makefile
Normal file
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# (C) Copyright 2003
|
||||
# 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$(ARCH).a
|
||||
|
||||
AOBJS =
|
||||
|
||||
COBJS = board.o time.o mips_linux.o
|
||||
|
||||
OBJS = $(AOBJS) $(COBJS)
|
||||
|
||||
$(LIB): .depend $(OBJS)
|
||||
$(AR) crv $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
403
lib_mips/board.c
Normal file
403
lib_mips/board.c
Normal file
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <devices.h>
|
||||
#include <syscall.h>
|
||||
#include <version.h>
|
||||
#include <net.h>
|
||||
#include <environment.h>
|
||||
|
||||
#if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < CFG_MONITOR_BASE) || \
|
||||
(CFG_ENV_ADDR >= (CFG_MONITOR_BASE + CFG_MONITOR_LEN)) ) || \
|
||||
defined(CFG_ENV_IS_IN_NVRAM)
|
||||
#define TOTAL_MALLOC_LEN (CFG_MALLOC_LEN + CFG_ENV_SIZE)
|
||||
#else
|
||||
#define TOTAL_MALLOC_LEN CFG_MALLOC_LEN
|
||||
#endif
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
extern int timer_init(void);
|
||||
|
||||
const char version_string[] =
|
||||
U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
|
||||
|
||||
static char *failed = "*** failed ***\n";
|
||||
|
||||
/*
|
||||
* Begin and End of memory area for malloc(), and current "brk"
|
||||
*/
|
||||
static ulong mem_malloc_start;
|
||||
static ulong mem_malloc_end;
|
||||
static ulong mem_malloc_brk;
|
||||
|
||||
|
||||
/*
|
||||
* The Malloc area is immediately below the monitor copy in DRAM
|
||||
*/
|
||||
static void mem_malloc_init (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
ulong dest_addr = CFG_MONITOR_BASE + gd->reloc_off;
|
||||
|
||||
mem_malloc_end = dest_addr;
|
||||
mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN;
|
||||
mem_malloc_brk = mem_malloc_start;
|
||||
|
||||
memset ((void *) mem_malloc_start,
|
||||
0,
|
||||
mem_malloc_end - mem_malloc_start);
|
||||
}
|
||||
|
||||
void *sbrk (ptrdiff_t increment)
|
||||
{
|
||||
ulong old = mem_malloc_brk;
|
||||
ulong new = old + increment;
|
||||
|
||||
if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
|
||||
return (NULL);
|
||||
}
|
||||
mem_malloc_brk = new;
|
||||
return ((void *) old);
|
||||
}
|
||||
|
||||
|
||||
static int init_func_ram (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_BOARD_TYPES
|
||||
int board_type = gd->board_type;
|
||||
#else
|
||||
int board_type = 0; /* use dummy arg */
|
||||
#endif
|
||||
puts ("DRAM: ");
|
||||
|
||||
if ((gd->ram_size = initdram (board_type)) > 0) {
|
||||
print_size (gd->ram_size, "\n");
|
||||
return (0);
|
||||
}
|
||||
puts (failed);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int display_banner(void)
|
||||
{
|
||||
|
||||
printf ("\n\n%s\n\n", version_string);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void display_flash_config(ulong size)
|
||||
{
|
||||
puts ("Flash: ");
|
||||
print_size (size, "\n");
|
||||
}
|
||||
|
||||
|
||||
static int init_baudrate (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
uchar tmp[64]; /* long enough for environment variables */
|
||||
int i = getenv_r ("baudrate", tmp, sizeof (tmp));
|
||||
|
||||
gd->baudrate = (i > 0)
|
||||
? (int) simple_strtoul (tmp, NULL, 10)
|
||||
: CONFIG_BAUDRATE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Breath some life into the board...
|
||||
*
|
||||
* The first part of initialization is running from Flash memory;
|
||||
* its main purpose is to initialize the RAM so that we
|
||||
* can relocate the monitor code to RAM.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All attempts to come up with a "common" initialization sequence
|
||||
* that works for all boards and architectures failed: some of the
|
||||
* requirements are just _too_ different. To get rid of the resulting
|
||||
* mess of board dependend #ifdef'ed code we now make the whole
|
||||
* initialization sequence configurable to the user.
|
||||
*
|
||||
* The requirements for any new initalization function is simple: it
|
||||
* receives a pointer to the "global data" structure as it's only
|
||||
* argument, and returns an integer return code, where 0 means
|
||||
* "continue" and != 0 means "fatal error, hang the system".
|
||||
*/
|
||||
typedef int (init_fnc_t) (void);
|
||||
|
||||
init_fnc_t *init_sequence[] = {
|
||||
timer_init,
|
||||
env_init, /* initialize environment */
|
||||
init_baudrate, /* initialze baudrate settings */
|
||||
serial_init, /* serial communications setup */
|
||||
console_init_f,
|
||||
display_banner, /* say that we are here */
|
||||
init_func_ram,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
void board_init_f(ulong bootflag)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
gd_t gd_data, *id;
|
||||
bd_t *bd;
|
||||
init_fnc_t **init_fnc_ptr;
|
||||
ulong addr, addr_sp, len = CFG_MONITOR_LEN;
|
||||
|
||||
/* Pointer is writable since we allocated a register for it.
|
||||
*/
|
||||
gd = &gd_data;
|
||||
memset (gd, 0, sizeof (gd_t));
|
||||
|
||||
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
||||
if ((*init_fnc_ptr)() != 0) {
|
||||
hang ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have DRAM mapped and working, we can
|
||||
* relocate the code and continue running from DRAM.
|
||||
*/
|
||||
addr = CFG_SDRAM_BASE + gd->ram_size;
|
||||
|
||||
/* We can reserve some RAM "on top" here.
|
||||
*/
|
||||
|
||||
/* round down to next 4 kB limit.
|
||||
*/
|
||||
addr &= ~(4096 - 1);
|
||||
#ifdef DEBUG
|
||||
printf ("Top of RAM usable for U-Boot at: %08lx\n", addr);
|
||||
#endif
|
||||
|
||||
/* Reserve memory for U-Boot code, data & bss
|
||||
* round down to next 4 kB limit
|
||||
*/
|
||||
addr -= len;
|
||||
addr &= ~(4096 - 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
|
||||
#endif
|
||||
|
||||
/* Reserve memory for malloc() arena.
|
||||
*/
|
||||
addr_sp = addr - TOTAL_MALLOC_LEN;
|
||||
#ifdef DEBUG
|
||||
printf ("Reserving %dk for malloc() at: %08lx\n",
|
||||
TOTAL_MALLOC_LEN >> 10, addr_sp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (permanently) allocate a Board Info struct
|
||||
* and a permanent copy of the "global" data
|
||||
*/
|
||||
addr_sp -= sizeof(bd_t);
|
||||
bd = (bd_t *)addr_sp;
|
||||
gd->bd = bd;
|
||||
#ifdef DEBUG
|
||||
printf ("Reserving %d Bytes for Board Info at: %08lx\n",
|
||||
sizeof(bd_t), addr_sp);
|
||||
#endif
|
||||
addr_sp -= sizeof(gd_t);
|
||||
id = (gd_t *)addr_sp;
|
||||
#ifdef DEBUG
|
||||
printf ("Reserving %d Bytes for Global Data at: %08lx\n",
|
||||
sizeof (gd_t), addr_sp);
|
||||
#endif
|
||||
|
||||
/* Reserve memory for boot params.
|
||||
*/
|
||||
addr_sp -= CFG_BOOTPARAMS_LEN;
|
||||
bd->bi_boot_params = addr_sp;
|
||||
#ifdef DEBUG
|
||||
printf ("Reserving %dk for malloc() at: %08lx\n",
|
||||
CFG_BOOTPARAMS_LEN >> 10, addr_sp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Finally, we set up a new (bigger) stack.
|
||||
*
|
||||
* Leave some safety gap for SP, force alignment on 16 byte boundary
|
||||
* Clear initial stack frame
|
||||
*/
|
||||
addr_sp -= 16;
|
||||
addr_sp &= ~0xF;
|
||||
*((ulong *) addr_sp)-- = 0;
|
||||
*((ulong *) addr_sp)-- = 0;
|
||||
#ifdef DEBUG
|
||||
printf ("Stack Pointer at: %08lx\n", addr_sp);
|
||||
#endif
|
||||
/*
|
||||
* Save local variables to board info struct
|
||||
*/
|
||||
bd->bi_memstart = CFG_SDRAM_BASE; /* start of DRAM memory */
|
||||
bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */
|
||||
bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
|
||||
|
||||
memcpy (id, gd, sizeof (gd_t));
|
||||
relocate_code (addr_sp, id, addr);
|
||||
|
||||
/* NOTREACHED - relocate_code() does not return */
|
||||
}
|
||||
/************************************************************************
|
||||
*
|
||||
* This is the next part if the initialization sequence: we are now
|
||||
* running from RAM and have a "normal" C environment, i. e. global
|
||||
* data can be written, BSS has been cleared, the stack size in not
|
||||
* that critical any more, etc.
|
||||
*
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
void board_init_r (gd_t *id, ulong dest_addr)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
cmd_tbl_t *cmdtp;
|
||||
ulong size;
|
||||
extern void malloc_bin_reloc (void);
|
||||
#ifndef CFG_ENV_IS_NOWHERE
|
||||
extern char * env_name_spec;
|
||||
#endif
|
||||
char *s, *e;
|
||||
bd_t *bd;
|
||||
int i;
|
||||
|
||||
gd = id;
|
||||
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
|
||||
#endif
|
||||
|
||||
gd->reloc_off = dest_addr - CFG_MONITOR_BASE;
|
||||
|
||||
/*
|
||||
* We have to relocate the command table manually
|
||||
*/
|
||||
for (cmdtp = &cmd_tbl[0]; cmdtp->name; cmdtp++) {
|
||||
ulong addr;
|
||||
|
||||
addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
|
||||
#if 0
|
||||
printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
|
||||
cmdtp->name, (ulong) (cmdtp->cmd), addr);
|
||||
#endif
|
||||
cmdtp->cmd =
|
||||
(int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
|
||||
|
||||
addr = (ulong)(cmdtp->name) + gd->reloc_off;
|
||||
cmdtp->name = (char *)addr;
|
||||
|
||||
if (cmdtp->usage) {
|
||||
addr = (ulong)(cmdtp->usage) + gd->reloc_off;
|
||||
cmdtp->usage = (char *)addr;
|
||||
}
|
||||
#ifdef CFG_LONGHELP
|
||||
if (cmdtp->help) {
|
||||
addr = (ulong)(cmdtp->help) + gd->reloc_off;
|
||||
cmdtp->help = (char *)addr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* there are some other pointer constants we must deal with */
|
||||
#ifndef CFG_ENV_IS_NOWHERE
|
||||
env_name_spec += gd->reloc_off;
|
||||
#endif
|
||||
|
||||
/* configure available FLASH banks */
|
||||
size = flash_init();
|
||||
display_flash_config (size);
|
||||
|
||||
bd = gd->bd;
|
||||
bd->bi_flashstart = CFG_FLASH_BASE;
|
||||
bd->bi_flashsize = size;
|
||||
#if CFG_MONITOR_BASE == CFG_FLASH_BASE
|
||||
bd->bi_flashoffset = CFG_MONITOR_LEN; /* reserved area for U-Boot */
|
||||
#else
|
||||
bd->bi_flashoffset = 0;
|
||||
#endif
|
||||
|
||||
/* initialize malloc() area */
|
||||
mem_malloc_init();
|
||||
malloc_bin_reloc();
|
||||
|
||||
/* relocate environment function pointers etc. */
|
||||
env_relocate();
|
||||
|
||||
/* board MAC address */
|
||||
s = getenv ("ethaddr");
|
||||
for (i = 0; i < 6; ++i) {
|
||||
bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
|
||||
if (s)
|
||||
s = (*e) ? e + 1 : e;
|
||||
}
|
||||
|
||||
/* IP Address */
|
||||
bd->bi_ip_addr = getenv_IPaddr("ipaddr");
|
||||
|
||||
/** leave this here (after malloc(), environment and PCI are working) **/
|
||||
/* Initialize devices */
|
||||
devices_init ();
|
||||
|
||||
/* allocate syscalls table (console_init_r will fill it in */
|
||||
syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
|
||||
|
||||
/* Initialize the console (after the relocation and devices init) */
|
||||
console_init_r ();
|
||||
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
|
||||
puts ("Net: ");
|
||||
eth_initialize(gd->bd);
|
||||
#endif
|
||||
|
||||
/* main_loop() can return to retry autoboot, if so just run it again. */
|
||||
for (;;) {
|
||||
main_loop ();
|
||||
}
|
||||
|
||||
/* NOTREACHED - no way out of command loop except booting */
|
||||
}
|
||||
|
||||
void hang (void)
|
||||
{
|
||||
puts ("### ERROR ### Please RESET the board ###\n");
|
||||
for (;;);
|
||||
}
|
||||
|
276
lib_mips/mips_linux.c
Normal file
276
lib_mips/mips_linux.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
#include <command.h>
|
||||
#include <cmd_boot.h>
|
||||
#include <image.h>
|
||||
#include <zlib.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#define LINUX_MAX_ENVS 256
|
||||
#define LINUX_MAX_ARGS 256
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||
#else
|
||||
# define SHOW_BOOT_PROGRESS(arg)
|
||||
#endif
|
||||
|
||||
extern image_header_t header; /* from cmd_bootm.c */
|
||||
|
||||
static int linux_argc;
|
||||
static char ** linux_argv;
|
||||
|
||||
static char ** linux_env;
|
||||
static char * linux_env_p;
|
||||
static int linux_env_idx;
|
||||
|
||||
static void linux_params_init (ulong start, char * commandline);
|
||||
static void linux_env_set (char * env_name, char * env_val);
|
||||
|
||||
|
||||
void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
|
||||
ulong addr, ulong *len_ptr, int verify)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
ulong len = 0, checksum;
|
||||
ulong initrd_start, initrd_end;
|
||||
ulong data;
|
||||
void (*theKernel)(int, char **, char **, int *);
|
||||
image_header_t *hdr = &header;
|
||||
char *commandline = getenv("bootargs");
|
||||
char env_buf[12];
|
||||
|
||||
theKernel = (void (*)(int, char **, char **, int *))ntohl(hdr->ih_ep);
|
||||
|
||||
/*
|
||||
* Check if there is an initrd image
|
||||
*/
|
||||
if (argc >= 3) {
|
||||
SHOW_BOOT_PROGRESS (9);
|
||||
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memcpy (&header, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf ("Bad Magic Number\n");
|
||||
SHOW_BOOT_PROGRESS (-10);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
data = (ulong)&header;
|
||||
len = sizeof(image_header_t);
|
||||
|
||||
checksum = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (char *)data, len) != checksum) {
|
||||
printf ("Bad Header Checksum\n");
|
||||
SHOW_BOOT_PROGRESS (-11);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (10);
|
||||
|
||||
print_image_hdr (hdr);
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = ntohl(hdr->ih_size);
|
||||
|
||||
if (verify) {
|
||||
ulong csum = 0;
|
||||
|
||||
printf (" Verifying Checksum ... ");
|
||||
csum = crc32 (0, (char *)data, len);
|
||||
if (csum != ntohl(hdr->ih_dcrc)) {
|
||||
printf ("Bad Data CRC\n");
|
||||
SHOW_BOOT_PROGRESS (-12);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
printf ("OK\n");
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (11);
|
||||
|
||||
if ((hdr->ih_os != IH_OS_LINUX) ||
|
||||
(hdr->ih_arch != IH_CPU_MIPS) ||
|
||||
(hdr->ih_type != IH_TYPE_RAMDISK) ) {
|
||||
printf ("No Linux MIPS Ramdisk Image\n");
|
||||
SHOW_BOOT_PROGRESS (-13);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check if we have a multifile image
|
||||
*/
|
||||
} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
|
||||
ulong tail = ntohl(len_ptr[0]) % 4;
|
||||
int i;
|
||||
|
||||
SHOW_BOOT_PROGRESS (13);
|
||||
|
||||
/* skip kernel length and terminator */
|
||||
data = (ulong)(&len_ptr[2]);
|
||||
/* skip any additional image length fields */
|
||||
for (i=1; len_ptr[i]; ++i)
|
||||
data += 4;
|
||||
/* add kernel length, and align */
|
||||
data += ntohl(len_ptr[0]);
|
||||
if (tail) {
|
||||
data += 4 - tail;
|
||||
}
|
||||
|
||||
len = ntohl(len_ptr[1]);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* no initrd image
|
||||
*/
|
||||
SHOW_BOOT_PROGRESS (14);
|
||||
|
||||
data = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!data) {
|
||||
printf ("No initrd\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data) {
|
||||
initrd_start = data;
|
||||
initrd_end = initrd_start + len;
|
||||
} else {
|
||||
initrd_start = 0;
|
||||
initrd_end = 0;
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (15);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("## Transferring control to Linux (at address %08lx) ...\n",
|
||||
(ulong)theKernel);
|
||||
#endif
|
||||
|
||||
linux_params_init (PHYSADDR(gd->bd->bi_boot_params), commandline);
|
||||
|
||||
sprintf (env_buf, "%lu", gd->ram_size >> 20);
|
||||
linux_env_set ("memsize", env_buf);
|
||||
|
||||
sprintf (env_buf, "0x%08X", (uint)PHYSADDR(initrd_start));
|
||||
linux_env_set ("initrd_start", env_buf);
|
||||
|
||||
sprintf (env_buf, "0x%X", (uint)(initrd_end - initrd_start));
|
||||
linux_env_set ("initrd_size", env_buf);
|
||||
|
||||
sprintf (env_buf, "0x%08X", (uint)(gd->bd->bi_flashstart));
|
||||
linux_env_set ("flash_start", env_buf);
|
||||
|
||||
sprintf (env_buf, "0x%X", (uint)(gd->bd->bi_flashsize));
|
||||
linux_env_set ("flash_size", env_buf);
|
||||
|
||||
/* we assume that the kernel is in place */
|
||||
printf("\nStarting kernel ...\n\n");
|
||||
|
||||
theKernel(linux_argc, linux_argv, linux_env, 0);
|
||||
}
|
||||
|
||||
static void linux_params_init (ulong start, char * line)
|
||||
{
|
||||
char * next, * quote, * argp;
|
||||
|
||||
linux_argc = 1;
|
||||
linux_argv = (char **) start;
|
||||
linux_argv[0] = 0;
|
||||
argp = (char *)(linux_argv + LINUX_MAX_ARGS);
|
||||
|
||||
next = line;
|
||||
|
||||
while (line && *line && linux_argc < LINUX_MAX_ARGS)
|
||||
{
|
||||
quote = strchr (line, '"');
|
||||
next = strchr (line, ' ');
|
||||
|
||||
while (next != NULL && quote != NULL && quote < next)
|
||||
{
|
||||
/* we found a left quote before the next blank
|
||||
* now we have to find the matching right quote
|
||||
*/
|
||||
next = strchr (quote + 1, '"');
|
||||
if (next != NULL)
|
||||
{
|
||||
quote = strchr (next + 1, '"');
|
||||
next = strchr (next + 1, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
next = line + strlen (line);
|
||||
}
|
||||
|
||||
linux_argv [linux_argc] = argp;
|
||||
memcpy (argp, line, next - line);
|
||||
argp [next - line] = 0;
|
||||
|
||||
argp += next - line + 1;
|
||||
linux_argc ++;
|
||||
|
||||
if (*next) next ++;
|
||||
|
||||
line = next;
|
||||
}
|
||||
|
||||
linux_env = (char **)(((ulong)argp + 15) & ~15);
|
||||
linux_env [0] = 0;
|
||||
linux_env_p = (char *)(linux_env + LINUX_MAX_ENVS);
|
||||
linux_env_idx = 0;
|
||||
}
|
||||
|
||||
static void linux_env_set (char * env_name, char * env_val)
|
||||
{
|
||||
if (linux_env_idx < LINUX_MAX_ENVS - 1)
|
||||
{
|
||||
linux_env [linux_env_idx] = linux_env_p;
|
||||
|
||||
strcpy (linux_env_p, env_name);
|
||||
linux_env_p += strlen (env_name);
|
||||
|
||||
strcpy (linux_env_p, "=");
|
||||
linux_env_p += 1;
|
||||
|
||||
strcpy (linux_env_p, env_val);
|
||||
linux_env_p += strlen (env_val);
|
||||
|
||||
linux_env_p ++;
|
||||
linux_env [++ linux_env_idx] = 0;
|
||||
}
|
||||
}
|
103
lib_mips/time.c
Normal file
103
lib_mips/time.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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 <common.h>
|
||||
|
||||
|
||||
static inline void mips_compare_set(u32 v)
|
||||
{
|
||||
asm volatile ("mtc0 %0, $11" : : "r" (v));
|
||||
}
|
||||
|
||||
static inline void mips_count_set(u32 v)
|
||||
{
|
||||
asm volatile ("mtc0 %0, $9" : : "r" (v));
|
||||
}
|
||||
|
||||
|
||||
static inline u32 mips_count_get(void)
|
||||
{
|
||||
u32 count;
|
||||
|
||||
asm volatile ("mfc0 %0, $9" : "=r" (count) :);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer without interrupts
|
||||
*/
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
mips_compare_set(0);
|
||||
mips_count_set(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
mips_count_set(0);
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return mips_count_get() - base;
|
||||
}
|
||||
|
||||
void set_timer(ulong t)
|
||||
{
|
||||
mips_count_set(t);
|
||||
}
|
||||
|
||||
void udelay (unsigned long usec)
|
||||
{
|
||||
ulong tmo;
|
||||
ulong start = get_timer(0);
|
||||
|
||||
tmo = usec * CFG_HZ / 1000;
|
||||
tmo /= 1000;
|
||||
|
||||
while ((ulong)((mips_count_get() - start)) < tmo)
|
||||
/*NOP*/;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (read timebase as long long).
|
||||
* On MIPS it just returns the timer value.
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
return mips_count_get();
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (timebase clock frequency).
|
||||
* On MIPS it returns the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return CFG_HZ;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue