* Add support for MIPS32 4Kc CPUs

* Add support for INCA-IP Board
This commit is contained in:
wdenk 2003-03-27 12:09:35 +00:00
parent ac6dbb85b7
commit c021880ac5
25 changed files with 5874 additions and 3 deletions

View File

@ -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:
======================================================================

View File

@ -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
View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

107
include/configs/incaip.h Normal file
View 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
View 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
View 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
View 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
View 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;
}