* Add support for Purple Board (MIPS64 5Kc) * Add support for MIPS64 5Kc CPUsmaster
parent
3e38691e8f
commit
60fbe25424
@ -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 sconsole.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 |
||||
|
||||
#########################################################################
|
@ -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
|
||||
#
|
||||
|
||||
#
|
||||
# Purple board with MIPS 5Kc CPU core
|
||||
#
|
||||
|
||||
# ROM version
|
||||
TEXT_BASE = 0xB0000000
|
||||
|
||||
# RAM version
|
||||
#TEXT_BASE = 0x80100000
|
@ -0,0 +1,596 @@ |
||||
/*
|
||||
* (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 */ |
||||
|
||||
typedef unsigned long FLASH_PORT_WIDTH; |
||||
typedef volatile unsigned long FLASH_PORT_WIDTHV; |
||||
|
||||
#define FLASH_ID_MASK 0xFFFFFFFF |
||||
|
||||
#define FPW FLASH_PORT_WIDTH |
||||
#define FPWV FLASH_PORT_WIDTHV |
||||
|
||||
#define ORMASK(size) ((-size) & OR_AM_MSK) |
||||
|
||||
#define FLASH29_REG_ADRS(reg) ((FPWV *)PHYS_FLASH_1 + (reg)) |
||||
|
||||
/* FLASH29 command register addresses */ |
||||
|
||||
#define FLASH29_REG_FIRST_CYCLE FLASH29_REG_ADRS (0x1555) |
||||
#define FLASH29_REG_SECOND_CYCLE FLASH29_REG_ADRS (0x2aaa) |
||||
#define FLASH29_REG_THIRD_CYCLE FLASH29_REG_ADRS (0x3555) |
||||
#define FLASH29_REG_FOURTH_CYCLE FLASH29_REG_ADRS (0x4555) |
||||
#define FLASH29_REG_FIFTH_CYCLE FLASH29_REG_ADRS (0x5aaa) |
||||
#define FLASH29_REG_SIXTH_CYCLE FLASH29_REG_ADRS (0x6555) |
||||
|
||||
/* FLASH29 command definitions */ |
||||
|
||||
#define FLASH29_CMD_FIRST 0xaaaaaaaa |
||||
#define FLASH29_CMD_SECOND 0x55555555 |
||||
#define FLASH29_CMD_FOURTH 0xaaaaaaaa |
||||
#define FLASH29_CMD_FIFTH 0x55555555 |
||||
#define FLASH29_CMD_SIXTH 0x10101010 |
||||
|
||||
#define FLASH29_CMD_SECTOR 0x30303030 |
||||
#define FLASH29_CMD_PROGRAM 0xa0a0a0a0 |
||||
#define FLASH29_CMD_CHIP_ERASE 0x80808080 |
||||
#define FLASH29_CMD_READ_RESET 0xf0f0f0f0 |
||||
#define FLASH29_CMD_AUTOSELECT 0x90909090 |
||||
#define FLASH29_CMD_READ 0x70707070 |
||||
|
||||
#define IN_RAM_CMD_READ 0x1 |
||||
#define IN_RAM_CMD_WRITE 0x2 |
||||
|
||||
#define FLASH_WRITE_CMD ((ulong)(flash_write_cmd) & 0x7)+0xbf008000 |
||||
#define FLASH_READ_CMD ((ulong)(flash_read_cmd) & 0x7)+0xbf008000 |
||||
|
||||
typedef void (*FUNCPTR_CP)(ulong *source, ulong *destination, ulong nlongs); |
||||
typedef void (*FUNCPTR_RD)(int cmd, FPWV * pFA, char * string, int strLen); |
||||
typedef void (*FUNCPTR_WR)(int cmd, FPWV * pFA, FPW value); |
||||
|
||||
static ulong flash_get_size(FPWV *addr, flash_info_t *info); |
||||
static int write_word(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); |
||||
|
||||
static void load_cmd(ulong cmd); |
||||
static ulong in_ram_cmd = 0; |
||||
|
||||
|
||||
/******************************************************************************
|
||||
* |
||||
* Don't change the program architecture |
||||
* This architecture assure the program |
||||
* can be relocated to scratch ram |
||||
*/ |
||||
static void flash_read_cmd(int cmd, FPWV * pFA, char * string, int strLen) |
||||
{
|
||||
int i,j; |
||||
FPW temp,temp1;
|
||||
FPWV *str; |
||||
|
||||
str = (FPWV *)string; |
||||
|
||||
j= strLen/4; |
||||
|
||||
if(cmd == FLASH29_CMD_AUTOSELECT) |
||||
{ |
||||
*(FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_FIRST; |
||||
*(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND; |
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_AUTOSELECT; |
||||
} |
||||
|
||||
if(cmd == FLASH29_CMD_READ) |
||||
{
|
||||
i = 0;
|
||||
while(i<j)
|
||||
{ |
||||
temp = *pFA++; |
||||
temp1 = *(int *)0xa0000000; |
||||
*(int *)0xbf0081f8 = temp1 + temp; |
||||
*str++ = temp; |
||||
i++; |
||||
}
|
||||
} |
||||
|
||||
if(cmd == FLASH29_CMD_READ_RESET)
|
||||
{ |
||||
*(FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_FIRST; |
||||
*(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND; |
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_READ_RESET; |
||||
}
|
||||
|
||||
*(int *)0xbf0081f8 = *(int *)0xa0000000; /* dummy read switch back to sdram interface */
|
||||
} |
||||
|
||||
/******************************************************************************
|
||||
* |
||||
* Don't change the program architecture |
||||
* This architecture assure the program |
||||
* can be relocated to scratch ram |
||||
*/ |
||||
static void flash_write_cmd(int cmd, FPWV * pFA, FPW value) |
||||
{
|
||||
*(FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_FIRST; |
||||
*(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND; |
||||
|
||||
if (cmd == FLASH29_CMD_SECTOR) |
||||
{ |
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_CHIP_ERASE; |
||||
*(FLASH29_REG_FOURTH_CYCLE) = FLASH29_CMD_FOURTH; |
||||
*(FLASH29_REG_FIFTH_CYCLE) = FLASH29_CMD_FIFTH; |
||||
*pFA = FLASH29_CMD_SECTOR; |
||||
} |
||||
|
||||
if (cmd == FLASH29_CMD_SIXTH) |
||||
{
|
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_CHIP_ERASE; |
||||
*(FLASH29_REG_FOURTH_CYCLE) = FLASH29_CMD_FOURTH; |
||||
*(FLASH29_REG_FIFTH_CYCLE) = FLASH29_CMD_FIFTH; |
||||
*(FLASH29_REG_SIXTH_CYCLE) = FLASH29_CMD_SIXTH; |
||||
} |
||||
|
||||
if (cmd == FLASH29_CMD_PROGRAM) |
||||
{ |
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_PROGRAM; |
||||
*pFA = value; |
||||
} |
||||
|
||||
if (cmd == FLASH29_CMD_READ_RESET)
|
||||
{ |
||||
*(FLASH29_REG_THIRD_CYCLE) = FLASH29_CMD_READ_RESET; |
||||
}
|
||||
|
||||
*(int *)0xbf0081f8 = *(int *)0xa0000000; /* dummy read switch back to sdram interface */
|
||||
} |
||||
|
||||
static void load_cmd(ulong cmd) |
||||
{ |
||||
ulong *src; |
||||
ulong *dst; |
||||
FUNCPTR_CP absEntry; |
||||
ulong func; |
||||
|
||||
if (in_ram_cmd & cmd) return; |
||||
|
||||
if (cmd == IN_RAM_CMD_READ) |
||||
{ |
||||
func = (ulong)flash_read_cmd; |
||||
} |
||||
else |
||||
{ |
||||
func = (ulong)flash_write_cmd; |
||||
} |
||||
|
||||
src = (ulong *)(func & 0xfffffff8); |
||||
dst = (ulong *)0xbf008000; |
||||
absEntry = (FUNCPTR_CP)(0xbf0081d0); |
||||
absEntry(src,dst,0x38); |
||||
|
||||
in_ram_cmd = cmd; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* flash_init() |
||||
* |
||||
* sets up flash_info and returns size of FLASH (bytes) |
||||
*/ |
||||
unsigned long flash_init (void) |
||||
{ |
||||
unsigned long size = 0; |
||||
int i; |
||||
|
||||
load_cmd(IN_RAM_CMD_READ); |
||||
|
||||
/* Init: no FLASHes known */ |
||||
for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) { |
||||
ulong flashbase = PHYS_FLASH_1; |
||||
ulong * buscon = (ulong *) INCA_IP_EBU_EBU_BUSCON0; |
||||
|
||||
/* 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_get_offsets (ulong base, flash_info_t *info) |
||||
{ |
||||
int i; |
||||
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD |
||||
&& (info->flash_id & FLASH_TYPEMASK) == FLASH_AM160B) { |
||||
|
||||
int bootsect_size[4]; /* number of bytes/boot sector */ |
||||
int sect_size; /* number of bytes/regular sector */ |
||||
|
||||
bootsect_size[0] = 0x00008000; |
||||
bootsect_size[1] = 0x00004000; |
||||
bootsect_size[2] = 0x00004000; |
||||
bootsect_size[3] = 0x00010000; |
||||
sect_size = 0x00020000; |
||||
|
||||
/* set sector offsets for bottom boot block type */ |
||||
for (i = 0; i < info->sector_count; i++) { |
||||
info->start[i] = base; |
||||
base += i < 4 ? bootsect_size[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_AM160B: |
||||
fmt = "29LV160B%s (16 Mbit, %s)\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) |
||||
{ |
||||
FUNCPTR_RD absEntry; |
||||
FPW retValue;
|
||||
int flag; |
||||
|
||||
load_cmd(IN_RAM_CMD_READ); |
||||
absEntry = (FUNCPTR_RD)FLASH_READ_CMD; |
||||
|
||||
flag = disable_interrupts(); |
||||
absEntry(FLASH29_CMD_AUTOSELECT,0,0,0); |
||||
if (flag) enable_interrupts(); |
||||
|
||||
udelay(100); |
||||
|
||||
flag = disable_interrupts(); |
||||
absEntry(FLASH29_CMD_READ, addr + 1, (char *)&retValue, sizeof(retValue)); |
||||
absEntry(FLASH29_CMD_READ_RESET,0,0,0); |
||||
if (flag) enable_interrupts(); |
||||
|
||||
udelay(100); |
||||
|
||||
switch (retValue) { |
||||
|
||||
case (FPW)AMD_ID_LV160B: |
||||
info->flash_id += FLASH_AM160B; |
||||
info->sector_count = 35; |
||||
info->size = 0x00400000; |
||||
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); |
||||
|
||||
return (info->size); |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
|
||||
int flash_erase (flash_info_t *info, int s_first, int s_last) |
||||
{ |
||||
FPWV *addr; |
||||
int flag, prot, sect; |
||||
ulong start, now, last; |
||||
int rcode = 0; |
||||
FUNCPTR_WR absEntry; |
||||
|
||||
load_cmd(IN_RAM_CMD_WRITE); |
||||
absEntry = (FUNCPTR_WR)FLASH_WRITE_CMD; |
||||
|
||||
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_AM160B: |
||||
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]); |
||||
absEntry(FLASH29_CMD_SECTOR, addr, 0); |
||||
|
||||
/* re-enable interrupts if necessary */ |
||||
if (flag) |
||||
enable_interrupts(); |
||||
|
||||
start = get_timer(0); |
||||
|
||||
while ((now = get_timer(start)) <= CFG_FLASH_ERASE_TOUT) { |
||||
|
||||
/* show that we're waiting */ |
||||
if ((get_timer(last)) > CFG_HZ) {/* every second */ |
||||
putc ('.'); |
||||
last = get_timer(0); |
||||
} |
||||
} |
||||
|
||||
flag = disable_interrupts(); |
||||
absEntry(FLASH29_CMD_READ_RESET,0,0); |
||||
if (flag) |
||||
enable_interrupts(); |
||||
} |
||||
|
||||
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++; |
||||
} |
||||
|
||||
res = write_word(info, (FPWV *)addr, data); |
||||
} |
||||
|
||||
return (res); |
||||
} |
||||
|
||||
static int write_word (flash_info_t *info, FPWV *dest, FPW data) |
||||
{ |
||||
int res = 0; /* result, assume success */ |
||||
FUNCPTR_WR absEntry; |
||||
int flag; |
||||
|
||||
/* Check if Flash is (sufficiently) erased */ |
||||
if ((*dest & data) != data) { |
||||
return (2); |
||||
} |
||||
|
||||
if (info->start[0] != PHYS_FLASH_1) |
||||
{ |
||||
return (3); |
||||
} |
||||
|
||||
load_cmd(IN_RAM_CMD_WRITE); |
||||
absEntry = (FUNCPTR_WR)FLASH_WRITE_CMD; |
||||
|
||||
flag = disable_interrupts(); |
||||
absEntry(FLASH29_CMD_PROGRAM,dest,data); |
||||
if (flag) enable_interrupts(); |
||||
|
||||
udelay(100); |
||||
|
||||
flag = disable_interrupts(); |
||||
absEntry(FLASH29_CMD_READ_RESET,0,0); |
||||
if (flag) enable_interrupts(); |
||||
|
||||
return (res); |
||||
} |
@ -0,0 +1,35 @@ |
||||
/* |
||||
* Memory sub-system initialization code for PURPLE 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> |
||||
|
||||
|
||||
.globl memsetup
|
||||
memsetup: |
||||
|
||||
j ra |
||||
nop |
||||
|
@ -0,0 +1,197 @@ |
||||
/*
|
||||
* (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> |
||||
#include <asm/regdef.h> |
||||
#include <asm/mipsregs.h> |
||||
#include <asm/addrspace.h> |
||||
#include <asm/cacheops.h> |
||||
|
||||
#include "sconsole.h" |
||||
|
||||
#define cache_unroll(base,op) \ |
||||
__asm__ __volatile__(" \
|
||||
.set noreorder; \
|
||||
.set mips3; \
|
||||
cache %1, (%0); \
|
||||
.set mips0; \
|
||||
.set reorder" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op)); |
||||
|
||||
typedef void (*FUNCPTR)(ulong *source, ulong *destination, ulong nlongs); |
||||
|
||||
extern void asc_serial_init (void); |
||||
extern void asc_serial_putc (char); |
||||
extern void asc_serial_puts (const char *); |
||||
extern int asc_serial_getc (void); |
||||
extern int asc_serial_tstc (void); |
||||
extern void asc_serial_setbrg (void); |
||||
|
||||
|
||||
long int initdram(int board_type) |
||||
{ |
||||
/* The only supported number of SDRAM banks is 4.
|
||||
*/ |
||||
#define CFG_NB 4 |
||||
|
||||
ulong cfgpb0 = *INCA_IP_SDRAM_MC_CFGPB0; |
||||
ulong cfgdw = *INCA_IP_SDRAM_MC_CFGDW; |
||||
int cols = cfgpb0 & 0xF; |
||||
int rows = (cfgpb0 & 0xF0) >> 4; |
||||
int dw = cfgdw & 0xF; |
||||
ulong size = (1 << (rows + cols)) * (1 << (dw - 1)) * CFG_NB; |
||||
|
||||
return size; |
||||
} |
||||
|
||||
int checkboard (void) |
||||
{ |
||||
|
||||
unsigned long chipid = *(unsigned long *)0xB800C800; |
||||
|
||||
printf ("Board: Purple PLB 2800 chip version %ld, ", chipid & 0xF); |
||||
|
||||
printf("CPU Speed %d MHz\n", CPU_CLOCK_RATE/1000000); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int misc_init_r (void) |
||||
{ |
||||
asc_serial_init (); |
||||
|
||||
sconsole_putc = asc_serial_putc; |
||||
sconsole_puts = asc_serial_puts; |
||||
sconsole_getc = asc_serial_getc; |
||||
sconsole_tstc = asc_serial_tstc; |
||||
sconsole_setbrg = asc_serial_setbrg; |
||||
|
||||
sconsole_flush (); |
||||
return (0); |
||||
} |
||||
|
||||
/*******************************************************************************
|
||||
* |
||||
* copydwords - copy one buffer to another a long at a time |
||||
* |
||||
* This routine copies the first <nlongs> longs from <source> to <destination>. |
||||
*/ |
||||
static void copydwords (ulong *source, ulong *destination, ulong nlongs) |
||||
{ |
||||
ulong temp,temp1; |
||||
ulong *dstend = destination + nlongs; |
||||
|
||||
while (destination < dstend) |
||||
{ |
||||
temp = *source++; |
||||
/* dummy read from sdram */ |
||||
temp1 = *(ulong *)0xa0000000; |
||||
/* avoid optimization from compliler */ |
||||
*(ulong *)0xbf0081f8 = temp1 + temp; |
||||
*destination++ = temp; |
||||
|
||||
}
|
||||
} |
||||
|
||||
/*******************************************************************************
|
||||
* |
||||
* copyLongs - copy one buffer to another a long at a time |
||||
* |
||||
* This routine copies the first <nlongs> longs from <source> to <destination>. |
||||
*/ |
||||
static void copyLongs (ulong *source, ulong *destination, ulong nlongs) |
||||
{ |
||||
FUNCPTR absEntry; |
||||
|
||||
absEntry = (FUNCPTR)(0xbf008000+((ulong)copydwords & 0x7)); |
||||
absEntry(source, destination, nlongs); |
||||
} |
||||
|
||||
/*******************************************************************************
|
||||
* |
||||
* programLoad - load program into ram |
||||
* |
||||
* This routine load copydwords into ram |
||||
* |
||||
*/ |
||||
static void programLoad(void) |
||||
{ |
||||
FUNCPTR absEntry; |
||||
ulong *src,*dst; |
||||
|
||||
src = (ulong *)(TEXT_BASE + 0x428); |
||||
dst = (ulong *)0xbf0081d0; |
||||
|
||||
absEntry = (FUNCPTR)(TEXT_BASE + 0x400);
|
||||
absEntry(src,dst,0x6);
|
||||
|
||||
src = (ulong *)((ulong)copydwords & 0xfffffff8); |
||||
dst = (ulong *)0xbf008000; |
||||
|
||||
absEntry(src,dst,0x38); |
||||
} |
||||
|
||||
/*******************************************************************************
|
||||
* |
||||
* copy_code - copy u-boot image from flash to RAM |
||||
* |
||||
* This routine is needed to solve flash problems on this board |
||||
* |
||||
*/ |
||||
void copy_code (ulong dest_addr) |
||||
{ |
||||
unsigned long start; |
||||
unsigned long end; |
||||
|
||||
/* load copydwords into ram
|
||||
*/ |
||||
programLoad(); |
||||
|
||||
/* copy u-boot code
|
||||
*/ |
||||
copyLongs((ulong *)CFG_MONITOR_BASE, |
||||
(ulong *)dest_addr, |
||||
(CFG_MONITOR_LEN + 3) / 4); |
||||
|
||||
|
||||
/* flush caches
|
||||
*/ |
||||
|
||||
start = KSEG0; |
||||
end = start + CFG_DCACHE_SIZE; |
||||
while(start < end) { |
||||
cache_unroll(start,Index_Writeback_Inv_D); |
||||
start += CFG_CACHELINE_SIZE; |
||||
} |
||||
|
||||
start = KSEG0; |
||||
end = start + CFG_ICACHE_SIZE; |
||||
while(start < end) { |
||||
cache_unroll(start,Index_Invalidate_I); |
||||
start += CFG_CACHELINE_SIZE; |
||||
} |
||||
} |
@ -0,0 +1,125 @@ |
||||
/*
|
||||
* (C) Copyright 2002 |
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <config.h> |
||||
#include <common.h> |
||||
|
||||
#include "sconsole.h" |
||||
|
||||
void (*sconsole_putc) (char) = 0; |
||||
void (*sconsole_puts) (const char *) = 0; |
||||
int (*sconsole_getc) (void) = 0; |
||||
int (*sconsole_tstc) (void) = 0; |
||||
void (*sconsole_setbrg) (void) = 0; |
||||
|
||||
int serial_init (void) |
||||
{ |
||||
sconsole_buffer_t *sb = SCONSOLE_BUFFER; |
||||
|
||||
sb->pos = 0; |
||||
sb->size = 0; |
||||
sb->max_size = CFG_SCONSOLE_SIZE - sizeof (sconsole_buffer_t); |
||||
|
||||
return (0); |
||||
} |
||||
|
||||
void serial_putc (char c) |
||||
{ |
||||
if (sconsole_putc) { |
||||
(*sconsole_putc) (c); |
||||
} else { |
||||
sconsole_buffer_t *sb = SCONSOLE_BUFFER; |
||||
|
||||
if (c) { |
||||
sb->data[sb->pos++] = c; |
||||
if (sb->pos == sb->max_size) { |
||||
sb->pos = 0; |
||||
} |
||||
if (sb->size < sb->max_size) { |
||||
sb->size++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void serial_puts (const char *s) |
||||
{ |
||||
if (sconsole_puts) { |
||||
(*sconsole_puts) (s); |
||||
} else { |
||||
sconsole_buffer_t *sb = SCONSOLE_BUFFER; |
||||
|
||||
while (*s) { |
||||
sb->data[sb->pos++] = *s++; |
||||
if (sb->pos == sb->max_size) { |
||||
sb->pos = 0; |
||||
} |
||||
if (sb->size < sb->max_size) { |
||||
sb->size++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
int serial_getc (void) |
||||
{ |
||||
if (sconsole_getc) { |
||||
return (*sconsole_getc) (); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
int serial_tstc (void) |
||||
{ |
||||
if (sconsole_tstc) { |
||||
return (*sconsole_tstc) (); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
void serial_setbrg (void) |
||||
{ |
||||
if (sconsole_setbrg) { |
||||
(*sconsole_setbrg) (); |
||||
} |
||||
} |
||||
|
||||
void sconsole_flush (void) |
||||
{ |
||||
if (sconsole_putc) { |
||||
sconsole_buffer_t *sb = SCONSOLE_BUFFER; |
||||
unsigned int end = sb->pos < sb->size |
||||
? sb->pos + sb->max_size - sb->size |
||||
: sb->pos - sb->size; |
||||
|
||||
while (sb->size) { |
||||
(*sconsole_putc) (sb->data[end++]); |
||||
if (end == sb->max_size) { |
||||
end = 0; |
||||
} |
||||
sb->size--; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* (C) Copyright 2002 |
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _SCONSOLE_H_ |
||||
#define _SCONSOLE_H_ |
||||
|
||||
#include <config.h> |
||||
|
||||
typedef struct sconsole_buffer_s |
||||
{ |
||||
unsigned long size; |
||||
unsigned long max_size; |
||||
unsigned long pos; |
||||
char data [1]; |
||||
} sconsole_buffer_t; |
||||
|
||||
#define SCONSOLE_BUFFER ((sconsole_buffer_t *) CFG_SCONSOLE_ADDR) |
||||
|
||||
extern void (* sconsole_putc) (char); |
||||
extern void (* sconsole_puts) (const char *); |
||||
extern int (* sconsole_getc) (void); |
||||
extern int (* sconsole_tstc) (void); |
||||
extern void (* sconsole_setbrg) (void); |
||||
|
||||
extern void sconsole_flush (void); |
||||
|
||||
#endif |
@ -0,0 +1,74 @@ |
||||
/* |
||||
* (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 : |
||||
{ |
||||
cpu/mips/start.o (.text) |
||||
board/purple/memsetup.o (.text) |
||||
cpu/mips/cache.o (.text) |
||||
common/main.o (.text) |
||||
common/dlmalloc.o (.text) |
||||
common/cmd_boot.o (.text) |
||||
lib_generic/zlib.o (.text) |
||||
. = DEFINED(env_offset) ? env_offset : .; |
||||
common/environment.o (.ppcenv) |
||||
|
||||
*(.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 = .; |
||||
} |
@ -0,0 +1,52 @@ |
||||
Installation Instructions: |
||||
-------------------------- |
||||
|
||||
1. Put the s2 switch into the following position: |
||||
|
||||
1 0 |
||||
------ |
||||
|x | |
||||
| x| |
||||
|x | |
||||
| X| |
||||
------ |
||||
|
||||
2. Connect to the serial console and to the BDI. Power on. On the |
||||
serial line, you should see: |
||||
|
||||
PURPLE@1.2> |
||||
|
||||
3. Type '8'. No echo will be displayed. In response, you should get: |
||||
|
||||
7A(pass) |
||||
|
||||
4. From BDI, enter command: |
||||
|
||||
mmw 0xb800d860 0x0042c7ff |
||||
|
||||
5. Then, from BDI: |
||||
|
||||
erase 0xB0000000 |
||||
erase 0xB0008000 |
||||
erase 0xB000C000 |
||||
erase 0xB0010000 |
||||
erase 0xB0020000 |
||||
|
||||
prog 0xB0000000 <u-boot.bin> bin |
||||
|
||||
6. Power off. Restore the original S2 switch position. Power on. |
||||
U-Boot should come up. |
||||
|
||||
|
||||
|
||||
Implementation Notes: |
||||
--------------------- |
||||
|
||||
Due to the RAM/flash bus arbitration problem the suggested workaround |
||||
had to be implemented. It works okay. On the downside is that you |
||||
can't really check whether 'erase' is complete by polling flash as it |
||||
is usually done. Instead, the flash driver simply waits for a given |
||||
time and assumes that erase then has passed. This behaviour is |
||||
identical to what the VxWorks driver does; also, the same timeout (6 |
||||
seconds) was chosen. Note that this timeout applies for each errase |
||||
operation, i. e. per erased sector. |
@ -0,0 +1,396 @@ |
||||
/*
|
||||
* PLB2800 internal switch ethernet driver. |
||||
* |
||||
* (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> |
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ |
||||
&& defined(CONFIG_PLB2800_ETHER) |
||||
|
||||
#include <malloc.h> |
||||
#include <net.h> |
||||
#include <asm/addrspace.h> |
||||
|
||||
|
||||
#define NUM_RX_DESC PKTBUFSRX |
||||
#define TOUT_LOOP 1000000 |
||||
|
||||
#define LONG_REF(addr) (*((volatile unsigned long*)addr)) |
||||
|
||||
#define CMAC_CRX_CTRL LONG_REF(0xb800c870) |
||||
#define CMAC_CTX_CTRL LONG_REF(0xb800c874) |
||||
#define SYS_MAC_ADDR_0 LONG_REF(0xb800c878) |
||||
#define SYS_MAC_ADDR_1 LONG_REF(0xb800c87c) |
||||
#define MIPS_H_MASK LONG_REF(0xB800C810) |
||||
|
||||
#define MA_LEARN LONG_REF(0xb8008004) |
||||
#define DA_LOOKUP LONG_REF(0xb8008008) |
||||
|
||||
#define CMAC_CRX_CTRL_PD 0x00000001 |
||||
#define CMAC_CRX_CTRL_CG 0x00000002 |
||||
#define CMAC_CRX_CTRL_PL_SHIFT 2 |
||||
#define CMAC_CRIT 0x0 |
||||
#define CMAC_NON_CRIT 0x1 |
||||
#define MBOX_STAT_ID_SHF 28 |
||||
#define MBOX_STAT_CP 0x80000000 |
||||
#define MBOX_STAT_MB 0x00000001 |
||||
#define EN_MA_LEARN 0x02000000 |
||||
#define EN_DA_LKUP 0x01000000 |
||||
#define MA_DEST_SHF 11 |
||||
#define DA_DEST_SHF 11 |
||||
#define DA_STATE_SHF 19 |
||||
#define TSTAMP_MS 0x00000000 |
||||
#define SW_H_MBOX4_MASK 0x08000000 |
||||
#define SW_H_MBOX3_MASK 0x04000000 |
||||
#define SW_H_MBOX2_MASK 0x02000000 |
||||
#define SW_H_MBOX1_MASK 0x01000000 |
||||
|
||||
typedef volatile struct { |
||||
unsigned int stat; |
||||
unsigned int cmd; |
||||
unsigned int cnt; |
||||
unsigned int adr; |
||||
} mailbox_t; |
||||
|
||||
#define MBOX_REG(mb) ((mailbox_t*)(0xb800c830+(mb<<4))) |
||||
|
||||
typedef volatile struct { |
||||
unsigned int word0; |
||||
unsigned int word1; |
||||
unsigned int word2; |
||||
} mbhdr_t; |
||||
|
||||
#define MBOX_MEM(mb) ((void*)(0xb800a000+((3-mb)<<11))) |
||||
|
||||
|
||||
static int plb2800_eth_init(struct eth_device *dev, bd_t * bis); |
||||
static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, |
||||
int length); |
||||
static int plb2800_eth_recv(struct eth_device *dev); |
||||
static void plb2800_eth_halt(struct eth_device *dev); |
||||
|
||||
static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr); |
||||
static unsigned char * plb2800_get_mac_addr(void); |
||||
|
||||
static int rx_new; |
||||
static int mac_addr_set = 0; |
||||
|
||||
|
||||
int plb2800_eth_initialize(bd_t * bis) |
||||
{ |
||||
struct eth_device *dev; |
||||
ulong temp; |
||||
|
||||
#ifdef DEBUG |
||||
printf("Entered plb2800_eth_initialize()\n"); |
||||
#endif |
||||
|
||||
if (!(dev = (struct eth_device *) malloc (sizeof *dev))) |
||||
{ |
||||
printf("Failed to allocate memory\n"); |
||||
return 0; |
||||
} |
||||
memset(dev, 0, sizeof(*dev)); |
||||
|
||||
sprintf(dev->name, "PLB2800 Switch"); |
||||
dev->init = plb2800_eth_init; |
||||
dev->halt = plb2800_eth_halt; |
||||
dev->send = plb2800_eth_send; |
||||
dev->recv = plb2800_eth_recv; |
||||
|
||||
eth_register(dev); |
||||
|
||||
/* bug fix */
|
||||
*(ulong *)0xb800e800 = 0x838;
|
||||
|
||||
/* Set MBOX ownership */ |
||||
temp = CMAC_CRIT << MBOX_STAT_ID_SHF; |
||||
MBOX_REG(0)->stat = temp; |
||||
MBOX_REG(1)->stat = temp; |
||||
|
||||
temp = CMAC_NON_CRIT << MBOX_STAT_ID_SHF;
|
||||
MBOX_REG(2)->stat = temp; |
||||
MBOX_REG(3)->stat = temp; |
||||
|
||||
plb2800_set_mac_addr(dev, plb2800_get_mac_addr()); |
||||
|
||||
/* Disable all Mbox interrupt */ |
||||
temp = MIPS_H_MASK; |
||||
temp &= ~ (SW_H_MBOX1_MASK | SW_H_MBOX2_MASK | SW_H_MBOX3_MASK | SW_H_MBOX4_MASK) ;
|
||||
MIPS_H_MASK = temp; |
||||
|
||||
#ifdef DEBUG |
||||
printf("Leaving plb2800_eth_initialize()\n"); |
||||
#endif |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static int plb2800_eth_init(struct eth_device *dev, bd_t * bis) |
||||
{ |
||||
#ifdef DEBUG |
||||
printf("Entering plb2800_eth_init()\n"); |
||||
#endif |
||||
|
||||
plb2800_set_mac_addr(dev, dev->enetaddr); |
||||
|
||||
rx_new = 0; |
||||
|
||||
#ifdef DEBUG |
||||
printf("Leaving plb2800_eth_init()\n"); |
||||
#endif |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, |
||||
int length) |
||||
{ |
||||
int i; |
||||
int res = -1; |
||||
u32 temp; |
||||
mailbox_t * mb = MBOX_REG(0); |
||||
char * mem = MBOX_MEM(0); |
||||
|
||||
#ifdef DEBUG |
||||
printf("Entered plb2800_eth_send()\n"); |
||||
#endif |
||||
|
||||
if (length <= 0) |
||||
{ |
||||
printf ("%s: bad packet size: %d\n", dev->name, length); |
||||
goto Done; |
||||
} |
||||
|
||||
if (length < 64) |
||||
{ |
||||
length = 64; |
||||
} |
||||
|
||||
temp = CMAC_CRX_CTRL_CG | ((length + 4) << CMAC_CRX_CTRL_PL_SHIFT); |
||||
|
||||
#ifdef DEBUG |
||||
printf("0 mb->stat = 0x%x\n", mb->stat); |
||||
#endif |
||||
|
||||
for(i = 0; mb->stat & (MBOX_STAT_CP | MBOX_STAT_MB); i++) |
||||
{ |
||||
if (i >= TOUT_LOOP) |
||||
{ |
||||
printf("%s: tx buffer not ready\n", dev->name); |
||||
printf("1 mb->stat = 0x%x\n", mb->stat); |
||||
goto Done; |
||||
} |
||||
} |
||||
|
||||
/* For some strange reason, memcpy doesn't work, here!
|
||||
*/ |
||||
do |
||||
{ |
||||
int words = (length >> 2) + 1; |
||||
unsigned int* dst = (unsigned int*)(mem); |
||||
unsigned int* src = (unsigned int*)(packet); |
||||
for (i = 0; i < words; i++) |
||||
{ |
||||
*dst = *src; |
||||
dst++; |
||||
src++; |
||||
}; |
||||
} while(0); |
||||
|
||||
CMAC_CRX_CTRL = temp; |
||||
mb->cmd = MBOX_STAT_CP; |
||||
|
||||
#ifdef DEBUG |
||||
printf("2 mb->stat = 0x%x\n", mb->stat); |
||||
#endif |
||||
|
||||
res = length; |
||||
Done: |
||||
|
||||
#ifdef DEBUG |
||||
printf("Leaving plb2800_eth_send()\n"); |
||||
#endif |
||||
|
||||
return res; |
||||
} |
||||
|
||||
|
||||
static int plb2800_eth_recv(struct eth_device *dev) |
||||
{ |
||||
int length = 0; |
||||
mailbox_t * mbox = MBOX_REG(3); |
||||
unsigned char * hdr = MBOX_MEM(3); |
||||
unsigned int stat; |
||||
|
||||
#ifdef DEBUG |
||||
printf("Entered plb2800_eth_recv()\n"); |
||||
#endif |
||||
|
||||
for (;;) |
||||
{ |
||||
stat = mbox->stat; |
||||
|
||||
if (!(stat & MBOX_STAT_CP)) |
||||
{ |
||||
break; |
||||
} |
||||
|
||||
length = ((*(hdr + 6) & 0x3f) << 8) + *(hdr + 7); |
||||
memcpy((void *)NetRxPackets[rx_new], hdr + 12, length); |
||||
|
||||
stat &= ~MBOX_STAT_CP; |
||||
mbox->stat = stat; |
||||
#ifdef DEBUG |
||||
{ |
||||
int i; |
||||
for (i=0;i<length - 4;i++) |
||||
{ |
||||
if (i % 16 == 0) printf("\n%04x: ", i); |
||||
printf("%02X ", NetRxPackets[rx_new][i]); |
||||
} |
||||
printf("\n"); |
||||
} |
||||
#endif |
||||
|
||||
if (length) |
||||
{ |
||||
#ifdef DEBUG |
||||
printf("Received %d bytes\n", length); |
||||
#endif |
||||
NetReceive((void*)(NetRxPackets[rx_new]), |
||||
length - 4); |
||||
} |
||||
else |
||||
{ |
||||
#if 1 |
||||
printf("Zero length!!!\n"); |
||||
#endif |
||||
} |
||||
|
||||
rx_new = (rx_new + 1) % NUM_RX_DESC; |
||||
} |
||||
|
||||
#ifdef DEBUG |
||||
printf("Leaving plb2800_eth_recv()\n"); |
||||
#endif |
||||
|
||||
return length; |
||||
} |
||||
|
||||
|
||||
static void plb2800_eth_halt(struct eth_device *dev) |
||||
{ |
||||
#ifdef DEBUG |
||||
printf("Entered plb2800_eth_halt()\n"); |
||||
#endif |
||||
|
||||
#ifdef DEBUG |
||||
printf("Leaving plb2800_eth_halt()\n"); |
||||
#endif |
||||
} |
||||
|
||||
static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr) |
||||
{ |
||||
char packet[60]; |
||||
ulong temp; |
||||
int ix; |
||||
|
||||
if (mac_addr_set || |
||||
NULL == addr || memcmp(addr, "\0\0\0\0\0\0", 6) == 0) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
/* send one packet through CPU port
|
||||
* in order to learn system MAC address |
||||
*/
|
||||
|
||||
/* Set DA_LOOKUP register */ |
||||
temp = EN_MA_LEARN | (0 << DA_STATE_SHF) | (63 << DA_DEST_SHF);
|
||||
DA_LOOKUP = temp; |
||||
|
||||
/* Set MA_LEARN register */ |
||||
temp = 50 << MA_DEST_SHF; /* static entry */ |
||||
MA_LEARN = temp; |
||||
|
||||
/* set destination address */ |
||||
for (ix=0;ix<6;ix++) |
||||
packet[ix] = 0xff; |
||||
|
||||
/* set source address = system MAC address */ |
||||
for (ix=0;ix<6;ix++) |
||||
packet[6+ix] = addr[ix]; |
||||
|
||||
/* set type field */ |
||||
packet[12]=0xaa; |
||||
packet[13]=0x55; |
||||
|
||||
/* set data field */ |
||||
for(ix=14;ix<60;ix++) |
||||
packet[ix] = 0x00; |
||||
|
||||
#ifdef DEBUG |
||||
for (ix=0;ix<6;ix++) |
||||
printf("mac_addr[%d]=%02X\n", ix, (unsigned char)packet[6+ix]); |
||||
#endif |
||||
|
||||
/* set one packet */ |
||||
plb2800_eth_send(dev, packet, sizeof(packet)); |
||||
|
||||
/* delay for a while */ |
||||
for(ix=0;ix<65535;ix++) |
||||
temp = ~temp; |
||||
|
||||
/* Set CMAC_CTX_CTRL register */
|
||||
temp = TSTAMP_MS; /* no autocast */ |
||||
CMAC_CTX_CTRL = temp; |
||||
|
||||
/* Set DA_LOOKUP register */ |
||||
temp = EN_DA_LKUP; |
||||
DA_LOOKUP = temp; |
||||
|
||||
mac_addr_set = 1; |
||||
} |
||||
|
||||
static unsigned char * plb2800_get_mac_addr(void) |
||||
{ |
||||
static unsigned char addr[6]; |
||||
char *tmp, *end; |
||||
int i; |
||||
|
||||
tmp = getenv ("ethaddr"); |
||||
if (NULL == tmp) return NULL; |
||||
|
||||
for (i=0; i<6; i++) { |
||||
addr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; |
||||
if (tmp) |
||||
tmp = (*end) ? end+1 : end; |
||||
} |
||||
|
||||
return addr; |
||||
} |
||||
|
||||
#endif /* CONFIG_PLB2800_ETHER */ |
@ -0,0 +1,156 @@ |
||||
/*
|
||||
* (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 PURPLE board. |
||||
*/ |
||||
|
||||
#ifndef __CONFIG_H |
||||
#define __CONFIG_H |
||||
|
||||
#define CONFIG_MIPS32 1 /* MIPS 5Kc CPU core */ |
||||
#define CONFIG_PURPLE 1 /* on a PURPLE Board */ |
||||
|
||||
#define CPU_CLOCK_RATE 125000000 /* 125 MHz clock for the MIPS core */ |
||||
#define ASC_CLOCK_RATE 62500000 /* 62.5 MHz ASC clock */ |
||||
|
||||
#define INFINEON_EBU_BOOTCFG 0xE0CC |
||||
|
||||
#define CONFIG_STACKSIZE (128 * 1024) |
||||
|
||||
#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ |
||||
|
||||
#define CONFIG_BAUDRATE 19200 |
||||
|
||||
/* valid baudrates */ |
||||
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } |
||||
|
||||
#define CONFIG_TIMESTAMP /* Print image info with timestamp */ |
||||
|
||||
#define CONFIG_PREBOOT "echo;" \ |
||||
"echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \
|
||||
"echo" |
||||
|
||||
#undef CONFIG_BOOTARGS |
||||
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \ |
||||
"nfsargs=setenv bootargs root=/dev/nfs rw " \
|
||||
"nfsroot=$(serverip):$(rootpath)\0" \
|
||||
"ramargs=setenv bootargs root=/dev/ram rw\0" \
|
||||
"addip=setenv bootargs $(bootargs) " \
|
||||
"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \
|
||||
":$(hostname):$(netdev):off\0" \
|
||||
"addmisc=setenv bootargs $(bootargs) " \
|
||||
"console=ttyS0,$(baudrate) " \
|
||||
"ethaddr=$(ethaddr) " \
|
||||
"panic=1\0" \
|
||||
"flash_nfs=run nfsargs addip addmisc;" \
|
||||
"bootm $(kernel_addr)\0" \
|
||||
"flash_self=run ramargs addip addmisc;" \
|
||||
"bootm $(kernel_addr) $(ramdisk_addr)\0" \
|
||||
"net_nfs=tftp 80500000 $(bootfile);" \
|
||||
"run nfsargs addip addmisc;bootm\0" \
|
||||
"rootpath=/opt/eldk/mips_5KC\0" \
|
||||
"bootfile=/tftpboot/purple/uImage\0" \
|
||||
"kernel_addr=B0040000\0" \
|
||||
"ramdisk_addr=B0100000\0" \
|
||||
"u-boot=/tftpboot/purple/u-boot.bin\0" \
|
||||
"load=tftp 80500000 $(u-boot)\0" \
|
||||
"update=protect off 1:0-4;era 1:0-4;" \
|
||||
"cp.b 80500000 B0000000 $(filesize)\0" \
|
||||
"" |
||||
#define CONFIG_BOOTCOMMAND "run flash_self" |
||||
|
||||
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_ELF) |
||||
#include <cmd_confdefs.h> |
||||
|
||||
#define CFG_SDRAM_BASE 0x80000000 |
||||
|
||||
#define CFG_INIT_SP_OFFSET 0x400000 |
||||
|
||||
#define CFG_MALLOC_LEN 128*1024 |
||||
|
||||
#define CFG_BOOTPARAMS_LEN 128*1024 |
||||
|
||||
/*
|
||||
* Miscellaneous configurable options |
||||
*/ |
||||
#define CFG_LONGHELP /* undef to save memory */ |
||||
#define CFG_PROMPT "PURPLE # " /* 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 0x80500000 /* default load address */ |
||||
|
||||
#define CFG_MEMTEST_START 0x80200000 |
||||
#define CFG_MEMTEST_END 0x80800000 |
||||
|
||||
#define CONFIG_MISC_INIT_R |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* FLASH and environment organization |
||||
*/ |
||||
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ |
||||
#define CFG_MAX_FLASH_SECT (35) /* max number of sectors on one chip */ |
||||
|
||||
#define PHYS_FLASH_1 0xb0000000 /* Flash Bank #1 */ |
||||
|
||||
/* The following #defines are needed to get flash environment right */ |
||||
#define CFG_MONITOR_BASE TEXT_BASE |
||||
#define CFG_MONITOR_LEN (192 << 10) |
||||
|
||||
#define CFG_FLASH_BASE PHYS_FLASH_1 |
||||
|
||||
/* timeout values are in ticks */ |
||||
#define CFG_FLASH_ERASE_TOUT (6 * CFG_HZ) /* Timeout for Flash Erase */ |
||||
#define CFG_FLASH_WRITE_TOUT (6 * CFG_HZ) /* Timeout for Flash Write */ |
||||
|
||||
#define CFG_ENV_IS_IN_FLASH 1 |
||||
|
||||
/* Address and size of Primary Environment Sector */ |
||||
#define CFG_ENV_ADDR 0xB0008000 |
||||
#define CFG_ENV_SIZE 0x4000 |
||||
|
||||
#define CONFIG_FLASH_32BIT |
||||
#define CONFIG_NR_DRAM_BANKS 1 |
||||
|
||||
#define CONFIG_PLB2800_ETHER |
||||
#define CONFIG_NET_MULTI |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Cache Configuration |
||||
*/ |
||||
#define CFG_DCACHE_SIZE 16384 |
||||
#define CFG_ICACHE_SIZE 16384 |
||||
#define CFG_CACHELINE_SIZE 32 |
||||
|
||||
/*
|
||||
* Temporary buffer for serial data until the real serial driver |
||||
* is initialised (memtest will destroy this buffer) |
||||
*/ |
||||
#define CFG_SCONSOLE_ADDR CFG_SDRAM_BASE |
||||
#define CFG_SCONSOLE_SIZE 0x0002000 |
||||
|
||||
#endif /* __CONFIG_H */ |
Loading…
Reference in new issue