* Patch by Marc Singer, 29 May 2003:

Fixed rarp boot method for IA32 and other little-endian CPUs.

* Patch by Marc Singer, 28 May 2003:
  Added port I/O commands.

* Patch by Matthew McClintock, 28 May 2003
  - cpu/mpc824x/start.S: fix relocation code when booting from RAM
  - minor patches for utx8245

* Patch by Daniel Engstrm, 28 May 2003:
  x86 update

* Patch by Dave Ellis, 9 May 2003 + 27 May 2003:
  add nand flash support to SXNI855T configuration
  fix/extend nand flash support:
  - fix 'nand erase' command so does not erase bad blocks
  - fix 'nand write' command so does not write to bad blocks
  - fix nand_probe() so handles no flash detected properly
  - add doc/README.nand
  - add .jffs2 and .oob options to nand read/write
  - add 'nand bad' command to list bad blocks
  - add 'clean' option to 'nand erase' to write JFFS2 clean markers
  - make NAND read/write faster

* Patch by Rune Torgersen, 23 May 2003:
  Update for MPC8266ADS board
This commit is contained in:
wdenk 2003-05-31 18:35:21 +00:00
parent 3b57fe0a70
commit 7a8e9bed17
86 changed files with 9858 additions and 3239 deletions

View file

@ -2,6 +2,34 @@
Changes since U-Boot 0.3.1:
======================================================================
* Patch by Marc Singer, 29 May 2003:
Fixed rarp boot method for IA32 and other little-endian CPUs.
* Patch by Marc Singer, 28 May 2003:
Added port I/O commands.
* Patch by Matthew McClintock, 28 May 2003
- cpu/mpc824x/start.S: fix relocation code when booting from RAM
- minor patches for utx8245
* Patch by Daniel Engström, 28 May 2003:
x86 update
* Patch by Dave Ellis, 9 May 2003 + 27 May 2003:
add nand flash support to SXNI855T configuration
fix/extend nand flash support:
- fix 'nand erase' command so does not erase bad blocks
- fix 'nand write' command so does not write to bad blocks
- fix nand_probe() so handles no flash detected properly
- add doc/README.nand
- add .jffs2 and .oob options to nand read/write
- add 'nand bad' command to list bad blocks
- add 'clean' option to 'nand erase' to write JFFS2 clean markers
- make NAND read/write faster
* Patch by Rune Torgersen, 23 May 2003:
Update for MPC8266ADS board
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
instead CFG_MONITOR_LEN is now only used to determine _at_compile_
_time_ (!) if the environment is embedded within the U-Boot image,

11
MAKEALL
View file

@ -129,6 +129,15 @@ LIST_mips5kc="purple"
LIST_mips="${LIST_mips4kc} ${LIST_mips5kc}"
#########################################################################
## i386 Systems
#########################################################################
LIST_I486="sc520_cdp sc520_spunk sc520_spunk_rel"
LIST_x86="${LIST_I486}"
#-----------------------------------------------------------------------
#----- for now, just run PPC by default -----
[ $# = 0 ] && set $LIST_ppc
@ -150,7 +159,7 @@ build_target() {
for arg in $@
do
case "$arg" in
5xx|8xx|824x|8260|4xx|7xx|74xx|SA|ARM7|ARM9|ppc|arm|pxa|mips)
5xx|8xx|824x|8260|4xx|7xx|74xx|SA|ARM7|ARM9|ppc|arm|pxa|mips|I486|x86)
for target in `eval echo '$LIST_'${arg}`
do
build_target ${target}

View file

@ -60,7 +60,11 @@ ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
ifeq ($(ARCH),i386)
#CROSS_COMPILE = i386-elf-
ifeq ($(HOSTARCH),i386)
CROSS_COMPILE =
else
CROSS_COMPILE = i386-linux-
endif
endif
ifeq ($(ARCH),mips)
CROSS_COMPILE = mips_4KC-
@ -729,6 +733,12 @@ wepep250_config : unconfig
sc520_cdp_config : unconfig
@./mkconfig $(@:_config=) i386 i386 sc520_cdp
sc520_spunk_config : unconfig
@./mkconfig $(@:_config=) i386 i386 sc520_spunk
sc520_spunk_rel_config : unconfig
@./mkconfig $(@:_config=) i386 i386 sc520_spunk
#========================================================================
# MIPS
#========================================================================
@ -752,7 +762,8 @@ clean:
| xargs rm -f
rm -f examples/hello_world examples/timer \
examples/eepro100_eeprom examples/sched \
examples/mem_to_mem_idma2intr
examples/mem_to_mem_idma2intr examples/82559_eeprom
rm -f tools/img2srec tools/mkimage tools/envcrc tools/gen_eth_addr
rm -f tools/easylogo/easylogo tools/bmp_logo
rm -f tools/gdb/astest tools/gdb/gdbcont tools/gdb/gdbsend

View file

@ -36,6 +36,3 @@ getline(char *buf,int *num,int max_num)
line_pointer = line_pointer + *num;
len = len - *num;
}

View file

@ -489,10 +489,13 @@ long int initdram(int board_type)
* The appropriate BRx/ORx registers have already been set when we
* get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE.
*/
#if 1
memctl->memc_mptpr = CFG_MPTPR;
memctl->memc_psrt = psrt;
memctl->memc_br2 = CFG_BR2_PRELIM;
memctl->memc_or2 = or;
memctl->memc_psdmr = psdmr | PSDMR_OP_PREA;
*ramaddr = c;
@ -530,41 +533,7 @@ long int initdram(int board_type)
memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN;
*ramaddr = c;
}
#endif
/*
printf("memctl->memc_mptpr = 0x%08x\n", CFG_MPTPR);
printf("memctl->memc_psrt = 0x%08x\n", psrt);
printf("memctl->memc_psdmr = 0x%08x\n", psdmr | PSDMR_OP_PREA);
printf("ramaddr = 0x%08x\n", ramaddr);
printf("memctl->memc_psdmr = 0x%08x\n", psdmr | PSDMR_OP_CBRR);
printf("memctl->memc_psdmr = 0x%08x\n", psdmr | PSDMR_OP_MRW);
printf("memctl->memc_psdmr = 0x%08x\n", psdmr | PSDMR_OP_NORM | PSDMR_RFEN);
immap->im_siu_conf.sc_ppc_acr = 0x00000002;
immap->im_siu_conf.sc_ppc_alrh = 0x01267893;
immap->im_siu_conf.sc_tescr1 = 0x00004000;
*/
#if 0
/* init sdram dimm */
ramaddr = (uchar *)CFG_SDRAM_BASE;
memctl->memc_psrt = 0x00000010;
immap->im_memctl.memc_or2 = 0xFF000CA0;
immap->im_memctl.memc_br2 = 0x00000041;
memctl->memc_psdmr = 0x296EB452;
*ramaddr = c;
memctl->memc_psdmr = 0x096EB452;
for (i = 0; i < 8; i++)
*ramaddr = c;
memctl->memc_psdmr = 0x196EB452;
*ramaddr = c;
memctl->memc_psdmr = 0x416EB452;
*ramaddr = c;
#endif
/* print info */
printf("SDRAM configuration read from SPD\n");
printf("\tSize per side = %dMB\n", sdram_size >> 20);
@ -576,6 +545,7 @@ long int initdram(int board_type)
/*return (16 * 1024 * 1024);*/
}
#ifdef CONFIG_PCI
struct pci_controller hose;

View file

@ -22,4 +22,4 @@
#
TEXT_BASE = 0x387e0000
TEXT_BASE = 0x387c0000

View file

@ -1,4 +1,7 @@
/*
* (C) Copyright 2002, 2003
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
@ -23,31 +26,23 @@
*/
#include <common.h>
#include <asm/io.h>
#include <pci.h>
#include <asm/ic/sc520.h>
ulong myflush(void);
#define PROBE_BUFFER_SIZE 1024
static unsigned char buffer[PROBE_BUFFER_SIZE];
#define SC520_MAX_FLASH_BANKS 3
#define SC520_FLASH_BANK0_BASE 0x38000000 /* BOOTCS */
#define SC520_FLASH_BANK1_BASE 0x30000000 /* ROMCS0 */
#define SC520_FLASH_BANK2_BASE 0x28000000 /* ROMCS1 */
#define SC520_FLASH_BANKSIZE 0x8000000
#define FLASH_BANK_SIZE 0x400000 /* 4 MB */
#define MAIN_SECT_SIZE 0x20000 /* 128 KB */
#define AMD29LV016B_SIZE 0x200000
#define AMD29LV016B_SECTORS 32
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
#define CMD_READ_ARRAY 0x00F000F0
#define CMD_UNLOCK1 0x00AA00AA
#define CMD_UNLOCK2 0x00550055
#define CMD_ERASE_SETUP 0x00800080
#define CMD_ERASE_CONFIRM 0x00300030
#define CMD_PROGRAM 0x00A000A0
#define CMD_UNLOCK_BYPASS 0x00200020
#define MEM_FLASH_ADDR1 (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
#define MEM_FLASH_ADDR2 (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
#define BIT_ERASE_DONE 0x00800080
#define BIT_RDY_MASK 0x00800080
#define BIT_PROGRAM_ERROR 0x00200020
#define BIT_TIMEOUT 0x80000000 /* our flag */
flash_info_t flash_info[SC520_MAX_FLASH_BANKS];
#define READY 1
#define ERR 2
@ -56,394 +51,592 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
/*-----------------------------------------------------------------------
*/
static u32 _probe_flash(u32 addr, u32 bw, int il)
{
u32 result=0;
/* First do an unlock cycle for the benefit of
* devices that need it */
switch (bw) {
case 1:
*(volatile u8*)(addr+0x5555) = 0xaa;
*(volatile u8*)(addr+0x2aaa) = 0x55;
*(volatile u8*)(addr+0x5555) = 0x90;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+2);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0x5555), 0xf0;
break;
case 2:
*(volatile u16*)(addr+0xaaaa) = 0xaaaa;
*(volatile u16*)(addr+0x5554) = 0x5555;
/* Issue identification command */
if (il == 2) {
*(volatile u16*)(addr+0xaaaa) = 0x9090;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+2);
/* Return device to data mode */
*(volatile u16*)addr = 0xffff;
*(volatile u16*)(addr+0xaaaa), 0xf0f0;
} else {
*(volatile u8*)(addr+0xaaaa) = 0x90;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+2);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0xaaaa), 0xf0;
}
break;
case 4:
*(volatile u32*)(addr+0x5554) = 0xaaaaaaaa;
*(volatile u32*)(addr+0xaaa8) = 0x55555555;
switch (il) {
case 1:
/* Issue identification command */
*(volatile u8*)(addr+0x5554) = 0x90;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+4);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0x5554), 0xf0;
break;
case 2:
/* Issue identification command */
*(volatile u32*)(addr + 0x5554) = 0x00900090;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+4);
/* Return device to data mode */
*(volatile u32*)addr = 0x00ff00ff;
*(volatile u32*)(addr+0x5554), 0x00f000f0;
break;
case 4:
/* Issue identification command */
*(volatile u32*)(addr+0x5554) = 0x90909090;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+4);
/* Return device to data mode */
*(volatile u32*)addr = 0xffffffff;
*(volatile u32*)(addr+0x5554), 0xf0f0f0f0;
break;
}
break;
}
return result;
}
extern int _probe_flash_end;
asm ("_probe_flash_end:\n"
".long 0\n");
static int identify_flash(unsigned address, int width)
{
int is;
int device;
int vendor;
int size;
unsigned res;
u32 (*_probe_flash_ptr)(u32 a, u32 bw, int il);
size = (unsigned)&_probe_flash_end - (unsigned)_probe_flash;
if (size > PROBE_BUFFER_SIZE) {
printf("_probe_flash() routine too large (%d) %p - %p\n",
size, &_probe_flash_end, _probe_flash);
return 0;
}
memcpy(buffer, _probe_flash, size);
_probe_flash_ptr = (void*)buffer;
is = disable_interrupts();
res = _probe_flash_ptr(address, width, 1);
if (is) {
enable_interrupts();
}
vendor = res >> 16;
device = res & 0xffff;
return res;
}
ulong flash_init(void)
{
int i, j;
ulong size = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
{
ulong flashbase = 0;
flash_info[i].flash_id =
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV160B & FLASH_TYPEMASK);
flash_info[i].size = FLASH_BANK_SIZE;
flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
if (i == 0)
flashbase = PHYS_FLASH_1;
else
panic("configured to many flash banks!\n");
for (j = 0; j < flash_info[i].sector_count; j++)
{
if (j <= 3)
{
/* 1st one is 32 KB */
if (j == 0)
{
flash_info[i].start[j] = flashbase + 0;
int i, j;
ulong size = 0;
for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) {
unsigned id;
ulong flashbase = 0;
int sectsize = 0;
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
switch (i) {
case 0:
flashbase = SC520_FLASH_BANK0_BASE;
break;
case 1:
flashbase = SC520_FLASH_BANK1_BASE;
break;
case 2:
flashbase = SC520_FLASH_BANK2_BASE;
break;
default:
panic("configured to many flash banks!\n");
}
/* 2nd and 3rd are both 16 KB */
if ((j == 1) || (j == 2))
{
flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000;
id = identify_flash(flashbase, 4);
switch (id & 0x00ff00ff) {
case 0x000100c8:
/* 29LV016B/29LV017B */
flash_info[i].flash_id =
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV016B & FLASH_TYPEMASK);
flash_info[i].size = AMD29LV016B_SIZE*4;
flash_info[i].sector_count = AMD29LV016B_SECTORS;
sectsize = (AMD29LV016B_SIZE*4)/AMD29LV016B_SECTORS;
printf("Bank %d: 4 x AMD 29LV017B\n", i);
break;
default:
printf("Bank %d have unknown flash %08x\n", i, id);
flash_info[i].flash_id = FLASH_UNKNOWN;
continue;
}
/* 4th 64 KB */
if (j == 3)
{
flash_info[i].start[j] = flashbase + 0x10000;
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] = flashbase + j * sectsize;
}
}
else
{
flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
}
size += flash_info[i].size;
flash_protect(FLAG_PROTECT_CLEAR,
flash_info[i].start[0],
flash_info[i].start[0] + flash_info[i].size - 1,
&flash_info[i]);
}
size += flash_info[i].size;
}
/*
* Protect monitor and environment sectors
*/
flash_protect(FLAG_PROTECT_SET,
i386boot_start-CFG_FLASH_BASE,
i386boot_end-CFG_FLASH_BASE,
&flash_info[0]);
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
return size;
/*
* Protect monitor and environment sectors
*/
flash_protect(FLAG_PROTECT_SET,
i386boot_start,
i386boot_end,
&flash_info[0]);
#ifdef CFG_ENV_ADDR
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
#endif
return size;
}
/*-----------------------------------------------------------------------
*/
void flash_print_info (flash_info_t *info)
void flash_print_info(flash_info_t *info)
{
int i;
switch (info->flash_id & FLASH_VENDMASK)
{
case (AMD_MANUFACT & FLASH_VENDMASK):
printf("AMD: ");
break;
default:
printf("Unknown Vendor ");
break;
}
switch (info->flash_id & FLASH_TYPEMASK)
{
case (AMD_ID_LV160B & FLASH_TYPEMASK):
printf("2x Amd29F160BB (16Mbit)\n");
break;
default:
printf("Unknown Chip Type\n");
goto Done;
break;
}
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 ");
int i;
switch (info->flash_id & FLASH_VENDMASK) {
case (AMD_MANUFACT & FLASH_VENDMASK):
printf("AMD: ");
switch (info->flash_id & FLASH_TYPEMASK) {
case (AMD_ID_LV016B & FLASH_TYPEMASK):
printf("4x AMD29LV017B (4x16Mbit)\n");
break;
default:
printf("Unknown Chip Type\n");
goto done;
break;
}
break;
default:
printf("Unknown Vendor ");
break;
}
printf (" %08lX%s", info->start[i],
info->protect[i] ? " (RO)" : " ");
}
printf ("\n");
Done:
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");
done:
}
/*-----------------------------------------------------------------------
*/
int flash_erase (flash_info_t *info, int s_first, int s_last)
/* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
#define __udelay(delay) \
{ \
unsigned micro; \
unsigned milli=0; \
\
micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
\
for (;;) { \
\
milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
\
if ((delay) <= (micro + (milli * 1000))) { \
break; \
} \
} \
} while (0)
static u32 _amd_erase_flash(u32 addr, u32 sector)
{
ulong result;
int iflag, prot, sect;
int rc = ERR_OK;
int chip1, chip2;
/* first look for protection bits */
if (info->flash_id == FLASH_UNKNOWN)
return ERR_UNKNOWN_FLASH_TYPE;
if ((s_first < 0) || (s_first > s_last)) {
return ERR_INVAL;
}
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot)
return ERR_PROTECTED;
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
iflag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
{
printf("Erasing sector %2d ... ", sect);
/* arm simple, non interrupt dependent timer */
reset_timer();
if (info->protect[sect] == 0)
{ /* not protected */
vu_long *addr = (vu_long *)(info->start[sect]);
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
*addr = CMD_ERASE_CONFIRM;
/* wait until flash is ready */
chip1 = chip2 = 0;
do
{
result = *addr;
/* check timeout */
if (get_timer(0) > CFG_FLASH_ERASE_TOUT)
{
MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
chip1 = TMO;
break;
unsigned elapsed;
/* Issue erase */
*(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
*(volatile u32*)(addr + 0xaaa8) = 0x55555555;
*(volatile u32*)(addr + 0x5554) = 0x80808080;
/* And one unlock */
*(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
*(volatile u32*)(addr + 0xaaa8) = 0x55555555;
/* Sector erase command comes last */
*(volatile u32*)(addr + sector) = 0x30303030;
elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
elapsed = 0;
__udelay(50);
while (((*(volatile u32*)(addr + sector)) & 0x80808080) != 0x80808080) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_ERASE_TOUT/CFG_HZ) * 1000)) {
*(volatile u32*)(addr) = 0xf0f0f0f0;
return 1;
}
if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
chip1 = READY;
if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
chip1 = ERR;
if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
chip2 = READY;
if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
chip2 = ERR;
} while (!chip1 || !chip2);
MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
if (chip1 == ERR || chip2 == ERR)
{
rc = ERR_PROG_ERROR;
goto outahere;
}
if (chip1 == TMO)
{
rc = ERR_TIMOUT;
goto outahere;
}
printf("ok.\n");
}
else /* it was protected */
{
printf("protected!\n");
*(volatile u32*)(addr) = 0xf0f0f0f0;
return 0;
}
extern int _amd_erase_flash_end;
asm ("_amd_erase_flash_end:\n"
".long 0\n");
int flash_erase(flash_info_t *info, int s_first, int s_last)
{
u32 (*_erase_flash_ptr)(u32 a, u32 so);
int prot;
int sect;
unsigned size;
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;
}
if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_amd_erase_flash_end - (unsigned)_amd_erase_flash;
if (size > PROBE_BUFFER_SIZE) {
printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
size, &_amd_erase_flash_end, _amd_erase_flash);
return 0;
}
memcpy(buffer, _amd_erase_flash, size);
_erase_flash_ptr = (void*)buffer;
} else {
printf ("Can't erase unknown flash type - aborted\n");
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");
}
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
int res;
int flag;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
res = _erase_flash_ptr(info->start[0], info->start[sect]-info->start[0]);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (res) {
printf("Erase timed out, sector %d\n", sect);
return res;
}
putc('.');
}
}
}
if (ctrlc())
printf("User Interrupt!\n");
outahere:
/* allow flash to settle - wait 10 ms */
udelay(10000);
if (iflag)
enable_interrupts();
return rc;
return 0;
}
/*-----------------------------------------------------------------------
* Copy memory to flash
* Write a word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
static int _amd_write_word(unsigned start, unsigned dest, unsigned data)
{
vu_long *addr = (vu_long *)dest;
ulong result;
int rc = ERR_OK;
int iflag;
int chip1, chip2;
/*
* Check if Flash is (sufficiently) erased
*/
result = *addr;
if ((result & data) != data)
return ERR_NOT_ERASED;
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
iflag = disable_interrupts();
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
*addr = CMD_PROGRAM;
*addr = data;
/* arm simple, non interrupt dependent timer */
reset_timer();
/* wait until flash is ready */
chip1 = chip2 = 0;
do
{
result = *addr;
/* check timeout */
if (get_timer(0) > CFG_FLASH_ERASE_TOUT)
{
chip1 = ERR | TMO;
break;
volatile u32 *addr2 = (u32*)start;
volatile u32 *dest2 = (u32*)dest;
volatile u32 *data2 = (u32*)&data;
unsigned elapsed;
/* Check if Flash is (sufficiently) erased */
if ((*((volatile u32*)dest) & (u32)data) != (u32)data) {
return 2;
}
if (!chip1 && ((result & 0x80) == (data & 0x80)))
chip1 = READY;
if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
{
result = *addr;
if ((result & 0x80) == (data & 0x80))
chip1 = READY;
else
chip1 = ERR;
addr2[0x5554] = 0xAAAAAAAA;
addr2[0xaaa8] = 0x55555555;
addr2[0x5554] = 0xA0A0A0A0;
dest2[0] = data;
elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
elapsed = 0;
/* data polling for D7 */
while ((dest2[0] & 0x80808080) != (data2[0] & 0x80808080)) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_WRITE_TOUT/CFG_HZ) * 1000)) {
addr2[0] = 0xf0f0f0f0;
return 1;
}
}
if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
chip2 = READY;
if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR))
{
result = *addr;
if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
chip2 = READY;
else
chip2 = ERR;
}
} while (!chip1 || !chip2);
*addr = CMD_READ_ARRAY;
if (chip1 == ERR || chip2 == ERR || *addr != data)
rc = ERR_PROG_ERROR;
if (iflag)
enable_interrupts();
return rc;
addr2[0] = 0xf0f0f0f0;
return 0;
}
extern int _amd_write_word_end;
asm ("_amd_write_word_end:\n"
".long 0\n");
/*-----------------------------------------------------------------------
* Copy memory to flash.
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
* 3 - Unsupported flash type
*/
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int l;
int i, rc;
ulong cp, wp, data;
int i, l, rc;
int flag;
u32 (*_write_word_ptr)(unsigned start, unsigned dest, unsigned data);
unsigned size;
if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_amd_write_word_end - (unsigned)_amd_write_word;
if (size > PROBE_BUFFER_SIZE) {
printf("_amd_write_word() routine too large (%d) %p - %p\n",
size, &_amd_write_word_end, _amd_write_word);
return 0;
}
memcpy(buffer, _amd_write_word, size);
_write_word_ptr = (void*)buffer;
} else {
printf ("Can't program unknown flash type - aborted\n");
return 3;
}
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
for (; i<4 && cnt>0; ++i) {
data |= *src++ << (8*i);
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (rc != 0) {
return rc;
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = 0;
for (i=0; i<4; ++i) {
data |= *src++ << (8*i);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (rc != 0) {
return rc;
}
wp += 4;
cnt -= 4;
}
if (cnt == 0) {
return 0;
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data |= *src++ << (8*i);
--cnt;
}
for (; i<4 && cnt>0; ++i) {
data = (data >> 8) | (*src++ << 24);
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
for (; i<4; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = *((vu_long*)src);
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
src += 4;
wp += 4;
cnt -= 4;
}
if (cnt == 0) {
return ERR_OK;
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data = (data >> 8) | (*src++ << 24);
--cnt;
}
for (; i<4; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
}
return write_word(info, wp, data);
return rc;
}

458
board/sc520_cdp/flash_old.c Normal file
View file

@ -0,0 +1,458 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
ulong myflush(void);
#define SC520_MAX_FLASH_BANKS 3
#define SC520_FLASH_BANK0_BASE 0x38000000 /* BOOTCS */
#define SC520_FLASH_BANK1_BASE 0x30000000 /* ROMCS0 */
#define SC520_FLASH_BANK2_BASE 0x28000000 /* ROMCS1 */
#define SC520_FLASH_BANKSIZE 0x8000000
#define AMD29LV016_SIZE 0x200000
#define AMD29LV016_SECTORS 32
flash_info_t flash_info[SC520_MAX_FLASH_BANKS];
#define CMD_READ_ARRAY 0x00F000F0
#define CMD_UNLOCK1 0x00AA00AA
#define CMD_UNLOCK2 0x00550055
#define CMD_ERASE_SETUP 0x00800080
#define CMD_ERASE_CONFIRM 0x00300030
#define CMD_PROGRAM 0x00A000A0
#define CMD_UNLOCK_BYPASS 0x00200020
#define BIT_ERASE_DONE 0x00800080
#define BIT_RDY_MASK 0x00800080
#define BIT_PROGRAM_ERROR 0x00200020
#define BIT_TIMEOUT 0x80000000 /* our flag */
#define READY 1
#define ERR 2
#define TMO 4
/*-----------------------------------------------------------------------
*/
ulong flash_init(void)
{
int i, j;
ulong size = 0;
for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) {
ulong flashbase = 0;
int sectsize = 0;
if (i==0 || i==2) {
/* FixMe: this assumes that bank 0 and 2
* are mapped to the two 8Mb banks */
flash_info[i].flash_id =
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV016B & FLASH_TYPEMASK);
flash_info[i].size = AMD29LV016_SIZE*4;
flash_info[i].sector_count = AMD29LV016_SECTORS;
sectsize = (AMD29LV016_SIZE*4)/AMD29LV016_SECTORS;
} else {
/* FixMe: this assumes that bank1 is unmapped
* (or mapped to the same flash bank as BOOTCS) */
flash_info[i].flash_id = 0;
flash_info[i].size = 0;
flash_info[i].sector_count = 0;
sectsize=0;
}
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
switch (i) {
case 0:
flashbase = SC520_FLASH_BANK0_BASE;
break;
case 1:
flashbase = SC520_FLASH_BANK1_BASE;
break;
case 2:
flashbase = SC520_FLASH_BANK0_BASE;
break;
default:
panic("configured to many flash banks!\n");
}
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] = sectsize;
flash_info[i].start[j] = flashbase + j * sectsize;
}
size += flash_info[i].size;
}
/*
* Protect monitor and environment sectors
*/
flash_protect(FLAG_PROTECT_SET,
i386boot_start-SC520_FLASH_BANK0_BASE,
i386boot_end-SC520_FLASH_BANK0_BASE,
&flash_info[0]);
#ifdef CFG_ENV_ADDR
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
#endif
return size;
}
/*-----------------------------------------------------------------------
*/
void flash_print_info(flash_info_t *info)
{
int i;
switch (info->flash_id & FLASH_VENDMASK) {
case (AMD_MANUFACT & FLASH_VENDMASK):
printf("AMD: ");
break;
default:
printf("Unknown Vendor ");
break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case (AMD_ID_LV016B & FLASH_TYPEMASK):
printf("4x Amd29LV016B (16Mbit)\n");
break;
default:
printf("Unknown Chip Type\n");
goto done;
break;
}
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");
done:
}
/*-----------------------------------------------------------------------
*/
int flash_erase(flash_info_t *info, int s_first, int s_last)
{
ulong result;
int iflag, prot, sect;
int rc = ERR_OK;
int chip1, chip2;
/* first look for protection bits */
if (info->flash_id == FLASH_UNKNOWN) {
return ERR_UNKNOWN_FLASH_TYPE;
}
if ((s_first < 0) || (s_first > s_last)) {
return ERR_INVAL;
}
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
return ERR_PROTECTED;
}
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
iflag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
printf("Erasing sector %2d ... ", sect);
/* arm simple, non interrupt dependent timer */
reset_timer();
if (info->protect[sect] == 0) {
/* not protected */
ulong addr = info->start[sect];
writel(CMD_UNLOCK1, addr + 1);
writel(CMD_UNLOCK2, addr + 2);
writel(CMD_ERASE_SETUP, addr + 1);
writel(CMD_UNLOCK1, addr + 1);
writel(CMD_UNLOCK2, addr + 2);
writel(CMD_ERASE_CONFIRM, addr);
/* wait until flash is ready */
chip1 = chip2 = 0;
do {
result = readl(addr);
/* check timeout */
if (get_timer(0) > CFG_FLASH_ERASE_TOUT) {
writel(CMD_READ_ARRAY, addr + 1);
chip1 = TMO;
break;
}
if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) {
chip1 = READY;
}
if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR) {
chip1 = ERR;
}
if (!chip2 && (result >> 16) & BIT_ERASE_DONE) {
chip2 = READY;
}
if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR) {
chip2 = ERR;
}
} while (!chip1 || !chip2);
writel(CMD_READ_ARRAY, addr + 1);
if (chip1 == ERR || chip2 == ERR) {
rc = ERR_PROG_ERROR;
goto outahere;
}
if (chip1 == TMO) {
rc = ERR_TIMOUT;
goto outahere;
}
printf("ok.\n");
} else { /* it was protected */
printf("protected!\n");
}
}
if (ctrlc()) {
printf("User Interrupt!\n");
}
outahere:
/* allow flash to settle - wait 10 ms */
udelay(10000);
if (iflag) {
enable_interrupts();
}
return rc;
}
/*-----------------------------------------------------------------------
* Copy memory to flash
*/
volatile static int write_word(flash_info_t *info, ulong dest, ulong data)
{
ulong addr = dest;
ulong result;
int rc = ERR_OK;
int iflag;
int chip1, chip2;
/*
* Check if Flash is (sufficiently) erased
*/
result = readl(addr);
if ((result & data) != data) {
return ERR_NOT_ERASED;
}
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
iflag = disable_interrupts();
writel(CMD_UNLOCK1, addr + 1);
writel(CMD_UNLOCK2, addr + 2);
writel(CMD_UNLOCK_BYPASS, addr + 1);
writel(addr, CMD_PROGRAM);
writel(addr, data);
/* arm simple, non interrupt dependent timer */
reset_timer();
/* wait until flash is ready */
chip1 = chip2 = 0;
do {
result = readl(addr);
/* check timeout */
if (get_timer(0) > CFG_FLASH_ERASE_TOUT) {
chip1 = ERR | TMO;
break;
}
if (!chip1 && ((result & 0x80) == (data & 0x80))) {
chip1 = READY;
}
if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
result = readl(addr);
if ((result & 0x80) == (data & 0x80)) {
chip1 = READY;
} else {
chip1 = ERR;
}
}
if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16)))) {
chip2 = READY;
}
if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) {
result = readl(addr);
if ((result & (0x80 << 16)) == (data & (0x80 << 16))) {
chip2 = READY;
} else {
chip2 = ERR;
}
}
} while (!chip1 || !chip2);
writel(CMD_READ_ARRAY, addr);
if (chip1 == ERR || chip2 == ERR || readl(addr) != data) {
rc = ERR_PROG_ERROR;
}
if (iflag) {
enable_interrupts();
}
return rc;
}
/*-----------------------------------------------------------------------
* Copy memory to flash.
*/
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int l;
int i, rc;
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
}
for (; i<4 && cnt>0; ++i) {
data = (data >> 8) | (*src++ << 24);
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
}
if ((rc = write_word(info, wp, data)) != 0) {
return rc;
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = *((vu_long*)src);
if ((rc = write_word(info, wp, data)) != 0) {
return rc;
}
src += 4;
wp += 4;
cnt -= 4;
}
if (cnt == 0) {
return ERR_OK;
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data = (data >> 8) | (*src++ << 24);
--cnt;
}
for (; i<4; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 24);
}
return write_word(info, wp, data);
}

View file

@ -1,4 +1,5 @@
/*
*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
*
@ -24,109 +25,162 @@
#include <common.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/ic/sc520.h>
#include <asm/ic/ali512x.h>
#include <ssi.h>
#undef SC520_CDP_DEBUG
#ifdef SC520_CDP_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif
/* ------------------------------------------------------------------------- */
/*
* Theory:
* We first set up all IRQs to be non-pci, edge triggered,
* when we later enumerate the pci bus and pci_sc520_fixup_irq() gets
* called we reallocate irqs to the pci bus with sc520_pci_set_irq()
* as needed. Whe choose the irqs to gram from a configurable list
* inside pci_sc520_fixup_irq() (If this list contains stupid irq's
* such as 0 thngas will not work)
*/
static void irq_init(void)
{
/* disable global interrupt mode */
write_mmcr_byte(SC520_PICICR, 0x40);
/* set irq0-7 to edge */
/* set all irqs to edge */
write_mmcr_byte(SC520_MPICMODE, 0x00);
/* set irq9-12 to level, all the other (8, 13-15) are edge */
write_mmcr_byte(SC520_SL1PICMODE, 0x1e);
/* set irq16-24 (unused slave pic2) to level */
write_mmcr_byte(SC520_SL2PICMODE, 0xff);
write_mmcr_byte(SC520_SL1PICMODE, 0x00);
write_mmcr_byte(SC520_SL2PICMODE, 0x00);
/* active low polarity on PIC interrupt pins,
active high polarity on all other irq pins */
write_mmcr_word(SC520_INTPINPOL, 0);
* active high polarity on all other irq pins */
write_mmcr_word(SC520_INTPINPOL, 0x0000);
/* set irq number mapping */
write_mmcr_byte(SC520_GPTMR0MAP,0); /* disable GP timer 0 INT */
write_mmcr_byte(SC520_GPTMR1MAP,0); /* disable GP timer 1 INT */
write_mmcr_byte(SC520_GPTMR2MAP,0); /* disable GP timer 2 INT */
write_mmcr_byte(SC520_PIT0MAP,0x1); /* Set PIT timer 0 INT to IRQ0 */
write_mmcr_byte(SC520_PIT1MAP,0); /* diable PIT timer 1 INT */
write_mmcr_byte(SC520_PIT2MAP,0); /* diable PIT timer 2 INT */
write_mmcr_byte(SC520_PCIINTAMAP,0x4); /* Set PCI INT A to IRQ9 */
write_mmcr_byte(SC520_PCIINTBMAP,0x5); /* Set PCI INT B to IRQ10 */
write_mmcr_byte(SC520_PCIINTCMAP,0x6); /* Set PCI INT C to IRQ11 */
write_mmcr_byte(SC520_PCIINTDMAP,0x7); /* Set PCI INT D to IRQ12 */
write_mmcr_byte(SC520_DMABCINTMAP,0); /* disable DMA INT */
write_mmcr_byte(SC520_SSIMAP,0); /* disable Synchronius serial INT */
write_mmcr_byte(SC520_WDTMAP,0); /* disable Watchdor INT */
write_mmcr_byte(SC520_RTCMAP,0x3); /* Set RTC int to 8 */
write_mmcr_byte(SC520_WPVMAP,0); /* disable write protect INT */
write_mmcr_byte(SC520_ICEMAP,0x2); /* Set ICE Debug Serielport INT to IRQ1 */
write_mmcr_byte(SC520_FERRMAP,0x8); /* Set FP error INT to IRQ13 */
write_mmcr_byte(SC520_GP0IMAP,6); /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */
write_mmcr_byte(SC520_GP1IMAP,2); /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */
write_mmcr_byte(SC520_GP2IMAP,7); /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */
write_mmcr_byte(SC520_GPTMR0MAP, SC520_IRQ_DISABLED); /* disable GP timer 0 INT */
write_mmcr_byte(SC520_GPTMR1MAP, SC520_IRQ_DISABLED); /* disable GP timer 1 INT */
write_mmcr_byte(SC520_GPTMR2MAP, SC520_IRQ_DISABLED); /* disable GP timer 2 INT */
write_mmcr_byte(SC520_PIT0MAP, SC520_IRQ0); /* Set PIT timer 0 INT to IRQ0 */
write_mmcr_byte(SC520_PIT1MAP, SC520_IRQ_DISABLED); /* disable PIT timer 1 INT */
write_mmcr_byte(SC520_PIT2MAP, SC520_IRQ_DISABLED); /* disable PIT timer 2 INT */
write_mmcr_byte(SC520_PCIINTAMAP, SC520_IRQ_DISABLED); /* disable PCI INT A */
write_mmcr_byte(SC520_PCIINTBMAP, SC520_IRQ_DISABLED); /* disable PCI INT B */
write_mmcr_byte(SC520_PCIINTCMAP, SC520_IRQ_DISABLED); /* disable PCI INT C */
write_mmcr_byte(SC520_PCIINTDMAP, SC520_IRQ_DISABLED); /* disable PCI INT D */
write_mmcr_byte(SC520_DMABCINTMAP, SC520_IRQ_DISABLED); /* disable DMA INT */
write_mmcr_byte(SC520_SSIMAP, SC520_IRQ_DISABLED); /* disable Synchronius serial INT */
write_mmcr_byte(SC520_WDTMAP, SC520_IRQ_DISABLED); /* disable Watchdog INT */
write_mmcr_byte(SC520_RTCMAP, SC520_IRQ8); /* Set RTC int to 8 */
write_mmcr_byte(SC520_WPVMAP, SC520_IRQ_DISABLED); /* disable write protect INT */
write_mmcr_byte(SC520_ICEMAP, SC520_IRQ1); /* Set ICE Debug Serielport INT to IRQ1 */
write_mmcr_byte(SC520_FERRMAP,SC520_IRQ13); /* Set FP error INT to IRQ13 */
if (CFG_USE_SIO_UART) {
write_mmcr_byte(SC520_UART1MAP,0); /* disable internal UART1 INT */
write_mmcr_byte(SC520_UART2MAP,0); /* disable internal UART2 INT */
write_mmcr_byte(SC520_GP3IMAP,11); /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */
write_mmcr_byte(SC520_GP4IMAP,12); /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */
write_mmcr_byte(SC520_UART1MAP, SC520_IRQ_DISABLED); /* disable internal UART1 INT */
write_mmcr_byte(SC520_UART2MAP, SC520_IRQ_DISABLED); /* disable internal UART2 INT */
write_mmcr_byte(SC520_GP3IMAP, SC520_IRQ3); /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */
write_mmcr_byte(SC520_GP4IMAP, SC520_IRQ4); /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */
} else {
write_mmcr_byte(SC520_UART1MAP,12); /* Set internal UART2 INT to IRQ4 */
write_mmcr_byte(SC520_UART2MAP,11); /* Set internal UART2 INT to IRQ3 */
write_mmcr_byte(SC520_GP3IMAP,0); /* disable GPIRQ3 (ISA IRQ3) */
write_mmcr_byte(SC520_GP4IMAP,0); /* disable GPIRQ4 (ISA IRQ4) */
write_mmcr_byte(SC520_UART1MAP, SC520_IRQ4); /* Set internal UART2 INT to IRQ4 */
write_mmcr_byte(SC520_UART2MAP, SC520_IRQ3); /* Set internal UART2 INT to IRQ3 */
write_mmcr_byte(SC520_GP3IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ3 (ISA IRQ3) */
write_mmcr_byte(SC520_GP4IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ4 (ISA IRQ4) */
}
write_mmcr_byte(SC520_GP5IMAP,13); /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */
write_mmcr_byte(SC520_GP6IMAP,21); /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */
write_mmcr_byte(SC520_GP7IMAP,22); /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */
write_mmcr_byte(SC520_GP8IMAP,3); /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */
write_mmcr_byte(SC520_GP9IMAP,4); /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */
write_mmcr_byte(SC520_GP10IMAP,9); /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */
write_mmcr_word(SC520_PCIHOSTMAP,0x11f); /* Map PCI hostbridge INT to NMI */
write_mmcr_word(SC520_ECCMAP,0x100); /* Map SDRAM ECC failure INT to NMI */
write_mmcr_byte(SC520_GP1IMAP, SC520_IRQ1); /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */
write_mmcr_byte(SC520_GP5IMAP, SC520_IRQ5); /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */
write_mmcr_byte(SC520_GP6IMAP, SC520_IRQ6); /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */
write_mmcr_byte(SC520_GP7IMAP, SC520_IRQ7); /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */
write_mmcr_byte(SC520_GP8IMAP, SC520_IRQ8); /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */
write_mmcr_byte(SC520_GP9IMAP, SC520_IRQ9); /* Set GPIRQ9 (ISA IRQ2) to IRQ9 */
write_mmcr_byte(SC520_GP0IMAP, SC520_IRQ11); /* Set GPIRQ0 (ISA IRQ11) to IRQ10 */
write_mmcr_byte(SC520_GP2IMAP, SC520_IRQ12); /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */
write_mmcr_byte(SC520_GP10IMAP,SC520_IRQ14); /* Set GPIRQ10 (ISA IRQ14) to IRQ14 */
write_mmcr_word(SC520_PCIHOSTMAP, 0x11f); /* Map PCI hostbridge INT to NMI */
write_mmcr_word(SC520_ECCMAP, 0x100); /* Map SDRAM ECC failure INT to NMI */
}
/* PCI stuff */
static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
char pin;
int irq;
/* a configurable lists of irqs to steal
* when we need one (a board with more pci interrupt pins
* would use a larger table */
static int irq_list[] = {
CFG_FIRST_PCI_IRQ,
CFG_SECOND_PCI_IRQ,
CFG_THIRD_PCI_IRQ,
CFG_FORTH_PCI_IRQ
};
static int next_irq_index=0;
char tmp_pin;
int pin;
pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &tmp_pin);
pin = tmp_pin;
pin-=1; /* pci config space use 1-based numbering */
if (-1 == pin) {
return; /* device use no irq */
}
pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
irq = pin-1;
/* map device number + pin to a pin on the sc520 */
switch (PCI_DEV(dev)) {
case 20:
pin+=SC520_PCI_INTA;
break;
case 19:
irq+=1;
pin+=SC520_PCI_INTB;
break;
case 18:
irq+=2;
pin+=SC520_PCI_INTC;
break;
case 17:
irq+=3;
pin+=SC520_PCI_INTD;
break;
default:
return;
}
irq&=3; /* wrap around */
irq+=9; /* lowest IRQ is 9 */
pin&=3; /* wrap around */
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq);
#if 0
printf("fixup_irq: device %d pin %c irq %d\n",
PCI_DEV(dev), 'A' + pin -1, irq);
#endif
if (sc520_pci_ints[pin] == -1) {
/* re-route one interrupt for us */
if (next_irq_index > 3) {
return;
}
if (pci_sc520_set_irq(pin, irq_list[next_irq_index])) {
return;
}
next_irq_index++;
}
if (-1 != sc520_pci_ints[pin]) {
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
sc520_pci_ints[pin]);
}
PRINTF("fixup_irq: device %d pin %c irq %d\n",
PCI_DEV(dev), 'A' + pin, sc520_pci_ints[pin]);
}
static struct pci_controller sc520_cdp_hose = {
@ -162,8 +216,8 @@ void setup_ali_sio(int uart_primary)
/* SSI chip select pins */
ali512x_cio_function(14, 0, 0, 0); /* SSI_CS */
ali512x_cio_function(15, 0, 0, 0); /* SSI_MV */
ali512x_cio_function(16, 0, 1, 0); /* SSI_SPI# (inverted) */
ali512x_cio_function(15, 0, 0, 0); /* SSI_MV */
ali512x_cio_function(16, 0, 0, 0); /* SSI_SPI# */
/* Board REV pins */
ali512x_cio_function(20, 0, 0, 1);
@ -202,6 +256,7 @@ static void bus_init(void)
* we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */
/* SRAM = GPCS3 128k @ d0000-effff*/
write_mmcr_long(SC520_PAR2, 0x4e00400d);
@ -219,13 +274,15 @@ static void bus_init(void)
/* 680 LEDS */
write_mmcr_long(SC520_PAR15, 0x30000640);
write_mmcr_byte(SC520_ADDDECCTL, 0);
asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */
if (CFG_USE_SIO_UART) {
write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);
setup_ali_sio(1);
} else {
write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));
write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));
setup_ali_sio(0);
silence_uart(0x3e8);
silence_uart(0x2e8);
@ -233,8 +290,193 @@ static void bus_init(void)
}
/* GPCS usage
* GPCS0 PIO27 (NMI)
* GPCS1 ROMCS1
* GPCS2 ROMCS2
* GPCS3 SRAMCS PAR2
* GPCS4 unused PAR3
* GPCS5 unused PAR4
* GPCS6 IDE
* GPCS7 IDE
*/
/* par usage:
* PAR0 legacy_video
* PAR1 PCI ROM mapping
* PAR2 SRAM
* PAR3 IDE
* PAR4 IDE
* PAR5 legacy_video
* PAR6 legacy_video
* PAR7 legacy_video
* PAR8 legacy_video
* PAR9 legacy_video
* PAR10 legacy_video
* PAR11 ISAROM
* PAR12 BOOTCS
* PAR13 ROMCS1
* PAR14 ROMCS2
* PAR15 Port 0x680 LED display
*/
/*
* This function should map a chunk of size bytes
* of the system address space to the ISA bus
*
* The function will return the memory address
* as seen by the host (which may very will be the
* same as the bus address)
*/
u32 isa_map_rom(u32 bus_addr, int size)
{
u32 par;
PRINTF("isa_map_rom asked to map %d bytes at %x\n",
size, bus_addr);
par = size;
if (par < 0x80000) {
par = 0x80000;
}
par >>= 12;
par--;
par&=0x7f;
par <<= 18;
par |= (bus_addr>>12);
par |= 0x50000000;
PRINTF ("setting PAR11 to %x\n", par);
/* Map rom 0x10000 with PAR1 */
write_mmcr_long(SC520_PAR11, par);
return bus_addr;
}
/*
* this function removed any mapping created
* with pci_get_rom_window()
*/
void isa_unmap_rom(u32 addr)
{
PRINTF("isa_unmap_rom asked to unmap %x", addr);
if ((addr>>12) == (read_mmcr_long(SC520_PAR11)&0x3ffff)) {
write_mmcr_long(SC520_PAR11, 0);
PRINTF(" done\n");
return;
}
PRINTF(" not ours\n");
}
#ifdef CONFIG_PCI
#define PCI_ROM_TEMP_SPACE 0x10000
/*
* This function should map a chunk of size bytes
* of the system address space to the PCI bus,
* suitable to map PCI ROMS (bus address < 16M)
* the function will return the host memory address
* which should be converted into a bus address
* before used to configure the PCI rom address
* decoder
*/
u32 pci_get_rom_window(struct pci_controller *hose, int size)
{
u32 par;
par = size;
if (par < 0x80000) {
par = 0x80000;
}
par >>= 16;
par--;
par&=0x7ff;
par <<= 14;
par |= (PCI_ROM_TEMP_SPACE>>16);
par |= 0x72000000;
PRINTF ("setting PAR1 to %x\n", par);
/* Map rom 0x10000 with PAR1 */
write_mmcr_long(SC520_PAR1, par);
return PCI_ROM_TEMP_SPACE;
}
/*
* this function removed any mapping created
* with pci_get_rom_window()
*/
void pci_remove_rom_window(struct pci_controller *hose, u32 addr)
{
PRINTF("pci_remove_rom_window: %x", addr);
if (addr == PCI_ROM_TEMP_SPACE) {
write_mmcr_long(SC520_PAR1, 0);
PRINTF(" done\n");
return;
}
PRINTF(" not ours\n");
}
/*
* This function is called in order to provide acces to the
* legacy video I/O ports on the PCI bus.
* After this function accesses to I/O ports 0x3b0-0x3bb and
* 0x3c0-0x3df shuld result in transactions on the PCI bus.
*
*/
int pci_enable_legacy_video_ports(struct pci_controller *hose)
{
/* Map video memory to 0xa0000*/
write_mmcr_long(SC520_PAR0, 0x7200400a);
/* forward all I/O accesses to PCI */
write_mmcr_byte(SC520_ADDDECCTL,
read_mmcr_byte(SC520_ADDDECCTL) | IO_HOLE_DEST_PCI);
/* so we map away all io ports to pci (only way to access pci io
* below 0x400. But then we have to map back the portions that we dont
* use so that the generate cycles on the GPIO bus where the sio and
* ISA slots are connected, this requre the use of several PAR registers
*/
/* bring 0x100 - 0x1ef back to ISA using PAR5 */
write_mmcr_long(SC520_PAR5, 0x30ef0100);
/* IDE use 1f0-1f7 */
/* bring 0x1f8 - 0x2f7 back to ISA using PAR6 */
write_mmcr_long(SC520_PAR6, 0x30ff01f8);
/* com2 use 2f8-2ff */
/* bring 0x300 - 0x3af back to ISA using PAR7 */
write_mmcr_long(SC520_PAR7, 0x30af0300);
/* vga use 3b0-3bb */
/* bring 0x3bc - 0x3bf back to ISA using PAR8 */
write_mmcr_long(SC520_PAR8, 0x300303bc);
/* vga use 3c0-3df */
/* bring 0x3e0 - 0x3f5 back to ISA using PAR9 */
write_mmcr_long(SC520_PAR9, 0x301503e0);
/* ide use 3f6 */
/* bring 0x3f7 back to ISA using PAR10 */
write_mmcr_long(SC520_PAR10, 0x300003f7);
/* com1 use 3f8-3ff */
return 0;
}
#endif
/*
* Miscelaneous platform dependent initialisations
*/
@ -252,7 +494,6 @@ int board_init(void)
/* enter debug mode after next reset (only if jumper is also set) */
write_mmcr_byte(SC520_RESCFG, 0x08);
/* configure the software timer to 33.333MHz */
write_mmcr_byte(SC520_SWTMRCFG, 0);
gd->bus_clk = 33333000;
@ -288,3 +529,87 @@ int last_stage_init(void)
return 0;
}
void ssi_chip_select(int dev)
{
/* Spunk board: SPI EEPROM is active-low, MW EEPROM and AUX are active high */
switch (dev) {
case 1: /* SPI EEPROM */
ali512x_cio_out(16, 0);
break;
case 2: /* MW EEPROM */
ali512x_cio_out(15, 1);
break;
case 3: /* AUX */
ali512x_cio_out(14, 1);
break;
case 0:
ali512x_cio_out(16, 1);
ali512x_cio_out(15, 0);
ali512x_cio_out(14, 0);
break;
default:
printf("Illegal SSI device requested: %d\n", dev);
}
}
void spi_init_f(void)
{
#ifdef CONFIG_SC520_CDP_USE_SPI
spi_eeprom_probe(1);
#endif
#ifdef CONFIG_SC520_CDP_USE_MW
mw_eeprom_probe(2);
#endif
}
ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
{
int offset;
int i;
ssize_t res;
offset = 0;
for (i=0;i<alen;i++) {
offset <<= 8;
offset |= addr[i];
}
#ifdef CONFIG_SC520_CDP_USE_SPI
res = spi_eeprom_read(1, offset, buffer, len);
#endif
#ifdef CONFIG_SC520_CDP_USE_MW
res = mw_eeprom_read(2, offset, buffer, len);
#endif
return res;
}
ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
{
int offset;
int i;
ssize_t res;
offset = 0;
for (i=0;i<alen;i++) {
offset <<= 8;
offset |= addr[i];
}
#ifdef CONFIG_SC520_CDP_USE_SPI
res = spi_eeprom_write(1, offset, buffer, len);
#endif
#ifdef CONFIG_SC520_CDP_USE_MW
res = mw_eeprom_write(2, offset, buffer, len);
#endif
return res;
}

View file

@ -60,3 +60,25 @@ board_init16:
/* the return address is tored in bp */
jmp *%bp
.section .bios, "ax"
.code16
.globl realmode_reset
realmode_reset:
/* Alias MMCR to 0xdf000 */
movw $0xfffc, %dx
movl $0x800df0cb, %eax
outl %eax, %dx
/* Set ds to point to MMCR alias */
movw $0xdf00, %ax
movw %ax, %ds
/* issue software reset thorugh MMCR */
movl $0xd72, %edi
movb $0x01, %al
movb %al, (%di)
1: hlt
jmp 1

View file

@ -27,7 +27,7 @@ ENTRY(_start)
SECTIONS
{
. = 0x387e0000; /* Where bootcode in the flash is mapped */
. = 0x387c0000; /* Where bootcode in the flash is mapped */
.text : { *(.text); }
. = ALIGN(4);

View file

@ -0,0 +1,47 @@
#
# (C) Copyright 2002
# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
#
# 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 := sc520_spunk.o flash.o
SOBJS := sc520_spunk_asm.o sc520_spunk_asm16.o
$(LIB): $(OBJS) $(SOBJS)
$(AR) crv $@ $^
clean:
rm -f $(SOBJS) $(OBJS)
distclean: clean
rm -f $(LIB) core *.bak .depend
#########################################################################
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
-include .depend
#########################################################################

View file

@ -0,0 +1,25 @@
#
# (C) Copyright 2002
# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
#
# 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
#
TEXT_BASE = 0x387c0000

813
board/sc520_spunk/flash.c Normal file
View file

@ -0,0 +1,813 @@
/*
* (C) Copyright 2002, 2003
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <pci.h>
#include <asm/ic/sc520.h>
#define PROBE_BUFFER_SIZE 1024
static unsigned char buffer[PROBE_BUFFER_SIZE];
#define SC520_MAX_FLASH_BANKS 1
#define SC520_FLASH_BANK0_BASE 0x38000000 /* BOOTCS */
#define SC520_FLASH_BANKSIZE 0x8000000
#define A29LV641DH_SIZE 0x800000
#define A29LV641DH_SECTORS 128
#define A29LV641MH_SIZE 0x800000
#define A29LV641MH_SECTORS 128
#define I28F320J3A_SIZE 0x400000
#define I28F320J3A_SECTORS 32
#define I28F640J3A_SIZE 0x800000
#define I28F640J3A_SECTORS 64
#define I28F128J3A_SIZE 0x1000000
#define I28F128J3A_SECTORS 128
flash_info_t flash_info[SC520_MAX_FLASH_BANKS];
#define READY 1
#define ERR 2
#define TMO 4
/*-----------------------------------------------------------------------
*/
static u32 _probe_flash(u32 addr, u32 bw, int il)
{
u32 result=0;
/* First do an unlock cycle for the benefit of
* devices that need it */
switch (bw) {
case 1:
*(volatile u8*)(addr+0x5555) = 0xaa;
*(volatile u8*)(addr+0x2aaa) = 0x55;
*(volatile u8*)(addr+0x5555) = 0x90;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+2);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0x5555), 0xf0;
break;
case 2:
*(volatile u16*)(addr+0xaaaa) = 0xaaaa;
*(volatile u16*)(addr+0x5554) = 0x5555;
/* Issue identification command */
if (il == 2) {
*(volatile u16*)(addr+0xaaaa) = 0x9090;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+2);
/* Return device to data mode */
*(volatile u16*)addr = 0xffff;
*(volatile u16*)(addr+0xaaaa), 0xf0f0;
} else {
*(volatile u8*)(addr+0xaaaa) = 0x90;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+2);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0xaaaa), 0xf0;
}
break;
case 4:
*(volatile u32*)(addr+0x5554) = 0xaaaaaaaa;
*(volatile u32*)(addr+0xaaa8) = 0x55555555;
switch (il) {
case 1:
/* Issue identification command */
*(volatile u8*)(addr+0x5554) = 0x90;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+4);
/* Return device to data mode */
*(volatile u8*)addr = 0xff;
*(volatile u8*)(addr+0x5554), 0xf0;
break;
case 2:
/* Issue identification command */
*(volatile u32*)(addr + 0x5554) = 0x00900090;
/* Read vendor */
result = *(volatile u16*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u16*)(addr+4);
/* Return device to data mode */
*(volatile u32*)addr = 0x00ff00ff;
*(volatile u32*)(addr+0x5554), 0x00f000f0;
break;
case 4:
/* Issue identification command */
*(volatile u32*)(addr+0x5554) = 0x90909090;
/* Read vendor */
result = *(volatile u8*)addr;
result <<= 16;
/* Read device */
result |= *(volatile u8*)(addr+4);
/* Return device to data mode */
*(volatile u32*)addr = 0xffffffff;
*(volatile u32*)(addr+0x5554), 0xf0f0f0f0;
break;
}
break;
}
return result;
}
extern int _probe_flash_end;
asm ("_probe_flash_end:\n"
".long 0\n");
static int identify_flash(unsigned address, int width)
{
int is;
int device;
int vendor;
int size;
unsigned res;
u32 (*_probe_flash_ptr)(u32 a, u32 bw, int il);
size = (unsigned)&_probe_flash_end - (unsigned)_probe_flash;
if (size > PROBE_BUFFER_SIZE) {
printf("_probe_flash() routine too large (%d) %p - %p\n",
size, &_probe_flash_end, _probe_flash);
return 0;
}
memcpy(buffer, _probe_flash, size);
_probe_flash_ptr = (void*)buffer;
is = disable_interrupts();
res = _probe_flash_ptr(address, width, 1);
if (is) {
enable_interrupts();
}
vendor = res >> 16;
device = res & 0xffff;
return res;
}
ulong flash_init(void)
{
int i, j;
ulong size = 0;
for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) {
unsigned id;
ulong flashbase = 0;
int sectsize = 0;
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
switch (i) {
case 0:
flashbase = SC520_FLASH_BANK0_BASE;
break;
default:
panic("configured to many flash banks!\n");
}
id = identify_flash(flashbase, 2);
switch (id) {
case 0x000122d7:
/* 29LV641DH */
flash_info[i].flash_id =
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV640U & FLASH_TYPEMASK);
flash_info[i].size = A29LV641DH_SIZE;
flash_info[i].sector_count = A29LV641DH_SECTORS;
sectsize = A29LV641DH_SIZE/A29LV641DH_SECTORS;
printf("Bank %d: AMD 29LV641DH\n", i);
break;
case 0x0001227E:
/* 29LV641MH */
flash_info[i].flash_id =
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_DL640 & FLASH_TYPEMASK);
flash_info[i].size = A29LV641MH_SIZE;
flash_info[i].sector_count = A29LV641MH_SECTORS;
sectsize = A29LV641MH_SIZE/A29LV641MH_SECTORS;
printf("Bank %d: AMD 29LV641MH\n", i);
break;
case 0x00890016:
/* 28F320J3A */
flash_info[i].flash_id =
(INTEL_MANUFACT & FLASH_VENDMASK) |
(INTEL_ID_28F320J3A & FLASH_TYPEMASK);
flash_info[i].size = I28F320J3A_SIZE;
flash_info[i].sector_count = I28F320J3A_SECTORS;
sectsize = I28F320J3A_SIZE/I28F320J3A_SECTORS;
printf("Bank %d: Intel 28F320J3A\n", i);
break;
case 0x00890017:
/* 28F640J3A */
flash_info[i].flash_id =
(INTEL_MANUFACT & FLASH_VENDMASK) |
(INTEL_ID_28F640J3A & FLASH_TYPEMASK);
flash_info[i].size = I28F640J3A_SIZE;
flash_info[i].sector_count = I28F640J3A_SECTORS;
sectsize = I28F640J3A_SIZE/I28F640J3A_SECTORS;
printf("Bank %d: Intel 28F640J3A\n", i);
break;
case 0x00890018:
/* 28F128J3A */
flash_info[i].flash_id =
(INTEL_MANUFACT & FLASH_VENDMASK) |
(INTEL_ID_28F128J3A & FLASH_TYPEMASK);
flash_info[i].size = I28F128J3A_SIZE;
flash_info[i].sector_count = I28F128J3A_SECTORS;
sectsize = I28F128J3A_SIZE/I28F128J3A_SECTORS;
printf("Bank %d: Intel 28F128J3A\n", i);
break;
default:
printf("Bank %d have unknown flash %08x\n", i, id);
flash_info[i].flash_id = FLASH_UNKNOWN;
continue;
}
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] = flashbase + j * sectsize;
}
size += flash_info[i].size;
flash_protect(FLAG_PROTECT_CLEAR,
flash_info[i].start[0],
flash_info[i].start[0] + flash_info[i].size - 1,
&flash_info[i]);
}
/*
* Protect monitor and environment sectors
*/
flash_protect(FLAG_PROTECT_SET,
i386boot_start,
i386boot_end,
&flash_info[0]);
#ifdef CFG_ENV_ADDR
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
#endif
return size;
}
/*-----------------------------------------------------------------------
*/
void flash_print_info(flash_info_t *info)
{
int i;
switch (info->flash_id & FLASH_VENDMASK) {
case (INTEL_MANUFACT & FLASH_VENDMASK):
printf("INTEL: ");
switch (info->flash_id & FLASH_TYPEMASK) {
case (INTEL_ID_28F320J3A & FLASH_TYPEMASK):
printf("1x I28F320J3A (32Mbit)\n");
break;
case (INTEL_ID_28F640J3A & FLASH_TYPEMASK):
printf("1x I28F640J3A (64Mbit)\n");
break;
case (INTEL_ID_28F128J3A & FLASH_TYPEMASK):
printf("1x I28F128J3A (128Mbit)\n");
break;
default:
printf("Unknown Chip Type\n");
goto done;
break;
}
break;
case (AMD_MANUFACT & FLASH_VENDMASK):
printf("AMD: ");
switch (info->flash_id & FLASH_TYPEMASK) {
case (AMD_ID_LV640U & FLASH_TYPEMASK):
printf("1x AMD29LV641DH (64Mbit)\n");
break;
case (AMD_ID_DL640 & FLASH_TYPEMASK):
printf("1x AMD29LV641MH (64Mbit)\n");
break;
default:
printf("Unknown Chip Type\n");
goto done;
break;
}
break;
default:
printf("Unknown Vendor ");
break;
}
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");
done:
}
/*-----------------------------------------------------------------------
*/
static u32 _amd_erase_flash(u32 addr, u32 sector)
{
unsigned elapsed;
/* Issue erase */
*(volatile u16*)(addr + 0xaaaa) = 0x00AA;
*(volatile u16*)(addr + 0x5554) = 0x0055;
*(volatile u16*)(addr + 0xaaaa) = 0x0080;
/* And one unlock */
*(volatile u16*)(addr + 0xaaaa) = 0x00AA;
*(volatile u16*)(addr + 0x5554) = 0x0055;
/* Sector erase command comes last */
*(volatile u16*)(addr + sector) = 0x0030;
elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
elapsed = 0;
while (((*(volatile u16*)(addr + sector)) & 0x0080) != 0x0080) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_ERASE_TOUT/CFG_HZ) * 1000)) {
*(volatile u16*)(addr) = 0x00f0;
return 1;
}
}
*(volatile u16*)(addr) = 0x00f0;
return 0;
}
extern int _amd_erase_flash_end;
asm ("_amd_erase_flash_end:\n"
".long 0\n");
/* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
#define __udelay(delay) \
{ \
unsigned micro; \
unsigned milli=0; \
\
micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
\
for (;;) { \
\
milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
\
if ((delay) <= (micro + (milli * 1000))) { \
break; \
} \
} \
} while (0)
static u32 _intel_erase_flash(u32 addr, u32 sector)
{
unsigned elapsed;
*(volatile u16*)(addr + sector) = 0x0050; /* clear status register */
*(volatile u16*)(addr + sector) = 0x0020; /* erase setup */
*(volatile u16*)(addr + sector) = 0x00D0; /* erase confirm */
/* Wait at least 80us - let's wait 1 ms */
__udelay(1000);
elapsed = 0;
while (((*(volatile u16*)(addr + sector)) & 0x0080) != 0x0080) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_ERASE_TOUT/CFG_HZ) * 1000)) {
*(volatile u16*)(addr + sector) = 0x00B0; /* suspend erase */
*(volatile u16*)(addr + sector) = 0x00FF; /* reset to read mode */
return 1;
}
}
*(volatile u16*)(addr + sector) = 0x00FF; /* reset to read mode */
return 0;
}
extern int _intel_erase_flash_end;
asm ("_intel_erase_flash_end:\n"
".long 0\n");
int flash_erase(flash_info_t *info, int s_first, int s_last)
{
u32 (*_erase_flash_ptr)(u32 a, u32 so);
int prot;
int sect;
unsigned size;
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;
}
if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_amd_erase_flash_end - (unsigned)_amd_erase_flash;
if (size > PROBE_BUFFER_SIZE) {
printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
size, &_amd_erase_flash_end, _amd_erase_flash);
return 0;
}
memcpy(buffer, _amd_erase_flash, size);
_erase_flash_ptr = (void*)buffer;
} else if ((info->flash_id & FLASH_VENDMASK) == (INTEL_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_intel_erase_flash_end - (unsigned)_intel_erase_flash;
if (size > PROBE_BUFFER_SIZE) {
printf("_intel_erase_flash() routine too large (%d) %p - %p\n",
size, &_intel_erase_flash_end, _intel_erase_flash);
return 0;
}
memcpy(buffer, _intel_erase_flash, size);
_erase_flash_ptr = (void*)buffer;
} else {
printf ("Can't erase unknown flash type - aborted\n");
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");
}
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
int res;
int flag;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
res = _erase_flash_ptr(info->start[0], info->start[sect]-info->start[0]);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (res) {
printf("Erase timed out, sector %d\n", sect);
return res;
}
putc('.');
}
}
return 0;
}
/*-----------------------------------------------------------------------
* Write a word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
static int _amd_write_word(unsigned start, unsigned dest, unsigned data)
{
volatile u16 *addr2 = (u16*)start;
volatile u16 *dest2 = (u16*)dest;
volatile u16 *data2 = (u16*)&data;
int i;
unsigned elapsed;
/* Check if Flash is (sufficiently) erased */
if ((*((volatile u16*)dest) & (u16)data) != (u16)data) {
return 2;
}
for (i = 0; i < 2; i++) {
addr2[0x5555] = 0x00AA;
addr2[0x2aaa] = 0x0055;
addr2[0x5555] = 0x00A0;
dest2[i] = (data >> (i*16)) & 0xffff;
elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
elapsed = 0;
/* data polling for D7 */
while ((dest2[i] & 0x0080) != (data2[i] & 0x0080)) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_WRITE_TOUT/CFG_HZ) * 1000)) {
addr2[i] = 0x00f0;
return 1;
}
}
}
addr2[i] = 0x00f0;
return 0;
}
extern int _amd_write_word_end;
asm ("_amd_write_word_end:\n"
".long 0\n");
static int _intel_write_word(unsigned start, unsigned dest, unsigned data)
{
int i;
unsigned elapsed;
/* Check if Flash is (sufficiently) erased */
if ((*((volatile u16*)dest) & (u16)data) != (u16)data) {
return 2;
}
for (i = 0; i < 2; i++) {
*(volatile u16*)(dest+2*i) = 0x0040; /* write setup */
*(volatile u16*)(dest+2*i) = (data >> (i*16)) & 0xffff;
elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
elapsed = 0;
/* data polling for D7 */
while ((*(volatile u16*)dest & 0x0080) != 0x0080) {
elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
if (elapsed > ((CFG_FLASH_WRITE_TOUT/CFG_HZ) * 1000)) {
*(volatile u16*)dest = 0x00ff;
return 1;
}
}
}
*(volatile u16*)dest = 0x00ff;
return 0;
}
extern int _intel_write_word_end;
asm ("_intel_write_word_end:\n"
".long 0\n");
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
* 3 - Unsupported flash type
*/
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;
int flag;
u32 (*_write_word_ptr)(unsigned start, unsigned dest, unsigned data);
unsigned size;
if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_amd_write_word_end - (unsigned)_amd_write_word;
if (size > PROBE_BUFFER_SIZE) {
printf("_amd_write_word() routine too large (%d) %p - %p\n",
size, &_amd_write_word_end, _amd_write_word);
return 0;
}
memcpy(buffer, _amd_write_word, size);
_write_word_ptr = (void*)buffer;
} else if ((info->flash_id & FLASH_VENDMASK) == (INTEL_MANUFACT & FLASH_VENDMASK)) {
size = (unsigned)&_intel_write_word_end - (unsigned)_intel_write_word;
if (size > PROBE_BUFFER_SIZE) {
printf("_intel_write_word() routine too large (%d) %p - %p\n",
size, &_intel_write_word_end, _intel_write_word);
return 0;
}
memcpy(buffer, _intel_write_word, size);
_write_word_ptr = (void*)buffer;
} else {
printf ("Can't program unknown flash type - aborted\n");
return 3;
}
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
for (; i<4 && cnt>0; ++i) {
data |= *src++ << (8*i);
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (rc != 0) {
return rc;
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = 0;
for (i=0; i<4; ++i) {
data |= *src++ << (8*i);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
if (rc != 0) {
return rc;
}
wp += 4;
cnt -= 4;
}
if (cnt == 0) {
return 0;
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data |= *src++ << (8*i);
--cnt;
}
for (; i<4; ++i, ++cp) {
data |= (*(uchar *)cp) << (8*i);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
rc = _write_word_ptr(info->start[0], wp, data);
/* re-enable interrupts if necessary */
if (flag) {
enable_interrupts();
}
return rc;
}

View file

@ -0,0 +1,686 @@
/*
*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
*
* 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 <pci.h>
#include <ssi.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/ic/sc520.h>
/* ------------------------------------------------------------------------- */
/*
* Theory:
* We first set up all IRQs to be non-pci, edge triggered,
* when we later enumerate the pci bus and pci_sc520_fixup_irq() gets
* called we reallocate irqs to the pci bus with sc520_pci_set_irq()
* as needed. Whe choose the irqs to gram from a configurable list
* inside pci_sc520_fixup_irq() (If this list contains stupid irq's
* such as 0 thngas will not work)
*/
static void irq_init(void)
{
/* disable global interrupt mode */
write_mmcr_byte(SC520_PICICR, 0x40);
/* set all irqs to edge */
write_mmcr_byte(SC520_MPICMODE, 0x00);
write_mmcr_byte(SC520_SL1PICMODE, 0x00);
write_mmcr_byte(SC520_SL2PICMODE, 0x00);
/* active low polarity on PIC interrupt pins,
* active high polarity on all other irq pins */
write_mmcr_word(SC520_INTPINPOL, 0x0000);
/* set irq number mapping */
write_mmcr_byte(SC520_GPTMR0MAP, SC520_IRQ_DISABLED); /* disable GP timer 0 INT */
write_mmcr_byte(SC520_GPTMR1MAP, SC520_IRQ_DISABLED); /* disable GP timer 1 INT */
write_mmcr_byte(SC520_GPTMR2MAP, SC520_IRQ_DISABLED); /* disable GP timer 2 INT */
write_mmcr_byte(SC520_PIT0MAP, SC520_IRQ0); /* Set PIT timer 0 INT to IRQ0 */
write_mmcr_byte(SC520_PIT1MAP, SC520_IRQ_DISABLED); /* disable PIT timer 1 INT */
write_mmcr_byte(SC520_PIT2MAP, SC520_IRQ_DISABLED); /* disable PIT timer 2 INT */
write_mmcr_byte(SC520_PCIINTAMAP, SC520_IRQ_DISABLED); /* disable PCI INT A */
write_mmcr_byte(SC520_PCIINTBMAP, SC520_IRQ_DISABLED); /* disable PCI INT B */
write_mmcr_byte(SC520_PCIINTCMAP, SC520_IRQ_DISABLED); /* disable PCI INT C */
write_mmcr_byte(SC520_PCIINTDMAP, SC520_IRQ_DISABLED); /* disable PCI INT D */
write_mmcr_byte(SC520_DMABCINTMAP, SC520_IRQ_DISABLED); /* disable DMA INT */
write_mmcr_byte(SC520_SSIMAP, SC520_IRQ6); /* Set Synchronius serial INT to IRQ6*/
write_mmcr_byte(SC520_WDTMAP, SC520_IRQ_DISABLED); /* disable Watchdog INT */
write_mmcr_byte(SC520_RTCMAP, SC520_IRQ8); /* Set RTC int to 8 */
write_mmcr_byte(SC520_WPVMAP, SC520_IRQ_DISABLED); /* disable write protect INT */
write_mmcr_byte(SC520_ICEMAP, SC520_IRQ1); /* Set ICE Debug Serielport INT to IRQ1 */
write_mmcr_byte(SC520_FERRMAP,SC520_IRQ13); /* Set FP error INT to IRQ13 */
write_mmcr_byte(SC520_UART1MAP, SC520_IRQ4); /* Set internal UART2 INT to IRQ4 */
write_mmcr_byte(SC520_UART2MAP, SC520_IRQ3); /* Set internal UART2 INT to IRQ3 */
write_mmcr_byte(SC520_GP0IMAP, SC520_IRQ7); /* Set GPIRQ0 (PC-Card AUX IRQ) to IRQ7 */
write_mmcr_byte(SC520_GP1IMAP, SC520_IRQ14); /* Set GPIRQ1 (CF IRQ) to IRQ14 */
write_mmcr_byte(SC520_GP3IMAP, SC520_IRQ5); /* Set GPIRQ3 ( CAN IRQ ) ti IRQ5 */
write_mmcr_byte(SC520_GP4IMAP, SC520_IRQ_DISABLED); /* disbale GIRQ4 ( IRR IRQ ) */
write_mmcr_byte(SC520_GP5IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ5 */
write_mmcr_byte(SC520_GP6IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ6 */
write_mmcr_byte(SC520_GP7IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ7 */
write_mmcr_byte(SC520_GP8IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ8 */
write_mmcr_byte(SC520_GP9IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ9 */
write_mmcr_byte(SC520_GP2IMAP, SC520_IRQ_DISABLED); /* disable GPIRQ2 */
write_mmcr_byte(SC520_GP10IMAP,SC520_IRQ_DISABLED); /* disable GPIRQ10 */
write_mmcr_word(SC520_PCIHOSTMAP, 0x11f); /* Map PCI hostbridge INT to NMI */
write_mmcr_word(SC520_ECCMAP, 0x100); /* Map SDRAM ECC failure INT to NMI */
}
/* PCI stuff */
static void pci_sc520_spunk_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
int version = read_mmcr_byte(SC520_SYSINFO);
/* a configurable lists of irqs to steal
* when we need one (a board with more pci interrupt pins
* would use a larger table */
static int irq_list[] = {
CFG_FIRST_PCI_IRQ,
CFG_SECOND_PCI_IRQ,
CFG_THIRD_PCI_IRQ,
CFG_FORTH_PCI_IRQ
};
static int next_irq_index=0;
char tmp_pin;
int pin;
pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &tmp_pin);
pin = tmp_pin;
pin-=1; /* pci config space use 1-based numbering */
if (-1 == pin) {
return; /* device use no irq */
}
/* map device number + pin to a pin on the sc520 */
switch (PCI_DEV(dev)) {
case 6: /* ETH0 */
pin+=SC520_PCI_INTA;
break;
case 7: /* ETH1 */
pin+=SC520_PCI_INTB;
break;
case 8: /* Crypto */
pin+=SC520_PCI_INTC;
break;
case 9: /* PMC slot */
pin+=SC520_PCI_INTD;
break;
case 10: /* PC-Card */
if (version < 10) {
pin+=SC520_PCI_INTD;
} else {
pin+=SC520_PCI_INTC;
}
break;
default:
return;
}
pin&=3; /* wrap around */
if (sc520_pci_ints[pin] == -1) {
/* re-route one interrupt for us */
if (next_irq_index > 3) {
return;
}
if (pci_sc520_set_irq(pin, irq_list[next_irq_index])) {
return;
}
next_irq_index++;
}
if (-1 != sc520_pci_ints[pin]) {
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
sc520_pci_ints[pin]);
}
#if 0
printf("fixup_irq: device %d pin %c irq %d\n",
PCI_DEV(dev), 'A' + pin, sc520_pci_ints[pin]);
#endif
}
static void pci_sc520_spunk_configure_cardbus(struct pci_controller *hose,
pci_dev_t dev, struct pci_config_table *te)
{
u32 io_base;
u32 temp;
pciauto_config_device(hose, dev);
pci_hose_write_config_word(hose, dev, PCI_COMMAND, 0x07); /* enable device */
pci_hose_write_config_byte(hose, dev, 0x0c, 0x10); /* cacheline size */
pci_hose_write_config_byte(hose, dev, 0x0d, 0x40); /* latency timer */
pci_hose_write_config_byte(hose, dev, 0x1b, 0x40); /* cardbus latency timer */
pci_hose_write_config_word(hose, dev, PCI_BRIDGE_CONTROL, 0x0040); /* reset cardbus */
pci_hose_write_config_word(hose, dev, PCI_BRIDGE_CONTROL, 0x0080); /* route interrupts though ExCA */
pci_hose_write_config_word(hose, dev, 0x44, 0x3e0); /* map legacy I/O port to 0x3e0 */
pci_hose_read_config_dword(hose, dev, 0x80, &temp); /* System control */
pci_hose_write_config_dword(hose, dev, 0x80, temp | 0x60); /* System control: disable clockrun */
/* route MF0 to ~INT and MF3 to IRQ7
* reserve all others */
pci_hose_write_config_dword(hose, dev, 0x8c, 0x00007002);
pci_hose_write_config_byte(hose, dev, 0x91, 0x00); /* card control */
pci_hose_write_config_byte(hose, dev, 0x92, 0x62); /* device control */
if (te->device != 0xac56) {
pci_hose_write_config_byte(hose, dev, 0x93, 0x21); /* async interrupt enable */
pci_hose_write_config_word(hose, dev, 0xa8, 0x0000); /* reset GPIO */
pci_hose_write_config_word(hose, dev, 0xac, 0x0000); /* reset GPIO */
pci_hose_write_config_word(hose, dev, 0xaa, 0x0000); /* reset GPIO */
pci_hose_write_config_word(hose, dev, 0xae, 0x0000); /* reset GPIO */
} else {
pci_hose_write_config_byte(hose, dev, 0x93, 0x20); /* */
}
pci_hose_write_config_word(hose, dev, 0xa4, 0x8000); /* reset power management */
pci_hose_read_config_dword(hose, dev, PCI_BASE_ADDRESS_0, &io_base);
io_base &= ~0xfL;
writeb(0x07, io_base+0x803); /* route CSC irq though ExCA and enable IRQ7 */
writel(0, io_base+0x10); /* CLKRUN default */
writel(0, io_base+0x20); /* CLKRUN default */
}
static struct pci_config_table pci_sc520_spunk_config_table[] = {
{ 0x104c, 0xac50, PCI_ANY_ID, 0, 0x0a, 0, pci_sc520_spunk_configure_cardbus, { 0, 0, 0} },
{ 0x104c, 0xac56, PCI_ANY_ID, 0, 0x0a, 0, pci_sc520_spunk_configure_cardbus, { 0, 0, 0} },
{ 0, 0, 0, 0, 0, 0, NULL, {0,0,0}}
};
static struct pci_controller sc520_spunk_hose = {
fixup_irq: pci_sc520_spunk_fixup_irq,
config_table: pci_sc520_spunk_config_table,
first_busno: 0x00,
last_busno: 0xff,
};
void pci_init_board(void)
{
pci_sc520_init(&sc520_spunk_hose);
}
/* set up the ISA bus timing and system address mappings */
static void bus_init(void)
{
/* versions
* 0 Hyglo versions 0.95 and 0.96 (large baords)
* ?? Hyglo version 0.97 (small board)
* 10 Spunk board
*/
int version = read_mmcr_byte(SC520_SYSINFO);
if (version) {
/* set up the GP IO pins (for the Spunk board) */
write_mmcr_word(SC520_PIOPFS31_16, 0xfff0); /* set the GPIO pin function 31-16 reg */
write_mmcr_word(SC520_PIOPFS15_0, 0x000f); /* set the GPIO pin function 15-0 reg */
write_mmcr_word(SC520_PIODIR31_16, 0x000f); /* set the GPIO direction 31-16 reg */
write_mmcr_word(SC520_PIODIR15_0, 0x1ff0); /* set the GPIO direction 15-0 reg */
write_mmcr_byte(SC520_CSPFS, 0xc0); /* set the CS pin function reg */
write_mmcr_byte(SC520_CLKSEL, 0x70);
write_mmcr_word(SC520_PIOCLR31_16, 0x0003); /* reset SSI chip-selects */
write_mmcr_word(SC520_PIOSET31_16, 0x000c);
} else {
/* set up the GP IO pins (for the Hyglo board) */
write_mmcr_word(SC520_PIOPFS31_16, 0xffc0); /* set the GPIO pin function 31-16 reg */
write_mmcr_word(SC520_PIOPFS15_0, 0x1e7f); /* set the GPIO pin function 15-0 reg */
write_mmcr_word(SC520_PIODIR31_16, 0x003f); /* set the GPIO direction 31-16 reg */
write_mmcr_word(SC520_PIODIR15_0, 0xe180); /* set the GPIO direction 15-0 reg */
write_mmcr_byte(SC520_CSPFS, 0x00); /* set the CS pin function reg */
write_mmcr_byte(SC520_CLKSEL, 0x70);
write_mmcr_word(SC520_PIOCLR15_0, 0x0180); /* reset SSI chip-selects */
}
write_mmcr_byte(SC520_GPCSRT, 1); /* set the GP CS offset */
write_mmcr_byte(SC520_GPCSPW, 3); /* set the GP CS pulse width */
write_mmcr_byte(SC520_GPCSOFF, 1); /* set the GP CS offset */
write_mmcr_byte(SC520_GPRDW, 3); /* set the RD pulse width */
write_mmcr_byte(SC520_GPRDOFF, 1); /* set the GP RD offset */
write_mmcr_byte(SC520_GPWRW, 3); /* set the GP WR pulse width */
write_mmcr_byte(SC520_GPWROFF, 1); /* set the GP WR offset */
write_mmcr_word(SC520_BOOTCSCTL, 0x0407); /* set up timing of BOOTCS */
/* adjust the memory map:
* by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM
* and 256MB to 1G-128k (0x1000000 - 0x37ffffff) is mapped to PCI mmio
* we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */
/* bootcs */
write_mmcr_long(SC520_PAR12, 0x8bffe800);
/* IDE0 = GPCS6 1f0-1f7 */
write_mmcr_long(SC520_PAR3, 0x380801f0);
/* IDE1 = GPCS7 3f6 */
write_mmcr_long(SC520_PAR4, 0x3c0003f6);
asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */
write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));
}
/* par usage:
* PAR0 (legacy_video)
* PAR1 (PCI ROM mapping)
* PAR2
* PAR3 IDE
* PAR4 IDE
* PAR5 (legacy_video)
* PAR6
* PAR7 (legacy_video)
* PAR8 (legacy_video)
* PAR9 (legacy_video)
* PAR10
* PAR11 (ISAROM)
* PAR12 BOOTCS
* PAR13
* PAR14
* PAR15
*/
/*
* This function should map a chunk of size bytes
* of the system address space to the ISA bus
*
* The function will return the memory address
* as seen by the host (which may very will be the
* same as the bus address)
*/
u32 isa_map_rom(u32 bus_addr, int size)
{
u32 par;
printf("isa_map_rom asked to map %d bytes at %x\n",
size, bus_addr);
par = size;
if (par < 0x80000) {
par = 0x80000;
}
par >>= 12;
par--;
par&=0x7f;
par <<= 18;
par |= (bus_addr>>12);
par |= 0x50000000;
printf ("setting PAR11 to %x\n", par);
/* Map rom 0x10000 with PAR1 */
write_mmcr_long(SC520_PAR11, par);
return bus_addr;
}
/*
* this function removed any mapping created
* with pci_get_rom_window()
*/
void isa_unmap_rom(u32 addr)
{
printf("isa_unmap_rom asked to unmap %x", addr);
if ((addr>>12) == (read_mmcr_long(SC520_PAR11)&0x3ffff)) {
write_mmcr_long(SC520_PAR11, 0);
printf(" done\n");
return;
}
printf(" not ours\n");
}
#ifdef CONFIG_PCI
#define PCI_ROM_TEMP_SPACE 0x10000
/*
* This function should map a chunk of size bytes
* of the system address space to the PCI bus,
* suitable to map PCI ROMS (bus address < 16M)
* the function will return the host memory address
* which should be converted into a bus address
* before used to configure the PCI rom address
* decoder
*/
u32 pci_get_rom_window(struct pci_controller *hose, int size)
{
u32 par;
par = size;
if (par < 0x80000) {
par = 0x80000;
}
par >>= 16;
par--;
par&=0x7ff;
par <<= 14;
par |= (PCI_ROM_TEMP_SPACE>>16);
par |= 0x72000000;
printf ("setting PAR1 to %x\n", par);
/* Map rom 0x10000 with PAR1 */
write_mmcr_long(SC520_PAR1, par);
return PCI_ROM_TEMP_SPACE;
}
/*
* this function removed any mapping created
* with pci_get_rom_window()
*/
void pci_remove_rom_window(struct pci_controller *hose, u32 addr)
{
printf("pci_remove_rom_window: %x", addr);
if (addr == PCI_ROM_TEMP_SPACE) {
write_mmcr_long(SC520_PAR1, 0);
printf(" done\n");
return;
}
printf(" not ours\n");
}
/*
* This function is called in order to provide acces to the
* legacy video I/O ports on the PCI bus.
* After this function accesses to I/O ports 0x3b0-0x3bb and
* 0x3c0-0x3df shuld result in transactions on the PCI bus.
*
*/
int pci_enable_legacy_video_ports(struct pci_controller *hose)
{
/* Map video memory to 0xa0000*/
write_mmcr_long(SC520_PAR0, 0x7200400a);
/* forward all I/O accesses to PCI */
write_mmcr_byte(SC520_ADDDECCTL,
read_mmcr_byte(SC520_ADDDECCTL) | IO_HOLE_DEST_PCI);
/* so we map away all io ports to pci (only way to access pci io
* below 0x400. But then we have to map back the portions that we dont
* use so that the generate cycles on the GPIO bus where the sio and
* ISA slots are connected, this requre the use of several PAR registers
*/
/* bring 0x100 - 0x2f7 back to ISA using PAR5 */
write_mmcr_long(SC520_PAR5, 0x31f70100);
/* com2 use 2f8-2ff */
/* bring 0x300 - 0x3af back to ISA using PAR7 */
write_mmcr_long(SC520_PAR7, 0x30af0300);
/* vga use 3b0-3bb */
/* bring 0x3bc - 0x3bf back to ISA using PAR8 */
write_mmcr_long(SC520_PAR8, 0x300303bc);
/* vga use 3c0-3df */
/* bring 0x3e0 - 0x3f7 back to ISA using PAR9 */
write_mmcr_long(SC520_PAR9, 0x301703e0);
/* com1 use 3f8-3ff */
return 0;
}
#endif
/*
* Miscelaneous platform dependent initialisations
*/
int board_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
init_sc520();
bus_init();
irq_init();
/* max drive current on SDRAM */
write_mmcr_word(SC520_DSCTL, 0x0100);
/* enter debug mode after next reset (only if jumper is also set) */
write_mmcr_byte(SC520_RESCFG, 0x08);
/* configure the software timer to 33.000MHz */
write_mmcr_byte(SC520_SWTMRCFG, 1);
gd->bus_clk = 33000000;
return 0;
}
int dram_init(void)
{
init_sc520_dram();
return 0;
}
void show_boot_progress(int val)
{
int version = read_mmcr_byte(SC520_SYSINFO);
if (version == 0) {
/* PIO31-PIO16 Data */
write_mmcr_word(SC520_PIODATA31_16,
(read_mmcr_word(SC520_PIODATA31_16) & 0xffc0)| ((val&0x7e)>>1)); /* 0x1f8 >> 3 */
/* PIO0-PIO15 Data */
write_mmcr_word(SC520_PIODATA15_0,
(read_mmcr_word(SC520_PIODATA15_0) & 0x1fff)| ((val&0x7)<<13));
} else {
/* newer boards use PIO4-PIO12 */
/* PIO0-PIO15 Data */
#if 0
val = (val & 0x007) | ((val & 0x038) << 3) | ((val & 0x1c0) >> 3);
#else
val = (val & 0x007) | ((val & 0x07e) << 2);
#endif
write_mmcr_word(SC520_PIODATA15_0,
(read_mmcr_word(SC520_PIODATA15_0) & 0xe00f) | ((val&0x01ff)<<4));
}
}
int last_stage_init(void)
{
int version = read_mmcr_byte(SC520_SYSINFO);
printf("Omicron Ceti SC520 Spunk revision %x\n", version);
#if 0
if (version) {
int x, y;
printf("eeprom probe %d\n", spi_eeprom_probe(1));
spi_eeprom_read(1, 0, (u8*)&x, 2);
spi_eeprom_read(1, 1, (u8*)&y, 2);
printf("eeprom bytes %04x%04x\n", x, y);
x ^= 0xffff;
y ^= 0xffff;
spi_eeprom_write(1, 0, (u8*)&x, 2);
spi_eeprom_write(1, 1, (u8*)&y, 2);
spi_eeprom_read(1, 0, (u8*)&x, 2);
spi_eeprom_read(1, 1, (u8*)&y, 2);
printf("eeprom bytes %04x%04x\n", x, y);
} else {
int x, y;
printf("eeprom probe %d\n", mw_eeprom_probe(1));
mw_eeprom_read(1, 0, (u8*)&x, 2);
mw_eeprom_read(1, 1, (u8*)&y, 2);
printf("eeprom bytes %04x%04x\n", x, y);
x ^= 0xffff;
y ^= 0xffff;
mw_eeprom_write(1, 0, (u8*)&x, 2);
mw_eeprom_write(1, 1, (u8*)&y, 2);
mw_eeprom_read(1, 0, (u8*)&x, 2);
mw_eeprom_read(1, 1, (u8*)&y, 2);
printf("eeprom bytes %04x%04x\n", x, y);
}
#endif
ds1722_probe(2);
return 0;
}
void ssi_chip_select(int dev)
{
int version = read_mmcr_byte(SC520_SYSINFO);
if (version) {
/* Spunk board: EEPROM and CAN are actove-low, TEMP and AUX are active high */
switch (dev) {
case 1: /* EEPROM */
write_mmcr_word(SC520_PIOCLR31_16, 0x0004);
break;
case 2: /* Temp Probe */
write_mmcr_word(SC520_PIOSET31_16, 0x0002);
break;
case 3: /* CAN */
write_mmcr_word(SC520_PIOCLR31_16, 0x0008);
break;
case 4: /* AUX */
write_mmcr_word(SC520_PIOSET31_16, 0x0001);
break;
case 0:
write_mmcr_word(SC520_PIOCLR31_16, 0x0003);
write_mmcr_word(SC520_PIOSET31_16, 0x000c);
break;
default:
printf("Illegal SSI device requested: %d\n", dev);
}
} else {
/* Globox board: Both EEPROM and TEMP are active-high */
switch (dev) {
case 1: /* EEPROM */
write_mmcr_word(SC520_PIOSET15_0, 0x0100);
break;
case 2: /* Temp Probe */
write_mmcr_word(SC520_PIOSET15_0, 0x0080);
break;
case 0:
write_mmcr_word(SC520_PIOCLR15_0, 0x0180);
break;
default:
printf("Illegal SSI device requested: %d\n", dev);
}
}
}
void spi_init_f(void)
{
read_mmcr_byte(SC520_SYSINFO) ?
spi_eeprom_probe(1) :
mw_eeprom_probe(1);
}
ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
{
int offset;
int i;
offset = 0;
for (i=0;i<alen;i++) {
offset <<= 8;
offset |= addr[i];
}
return read_mmcr_byte(SC520_SYSINFO) ?
spi_eeprom_read(1, offset, buffer, len) :
mw_eeprom_read(1, offset, buffer, len);
}
ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
{
int offset;
int i;
offset = 0;
for (i=0;i<alen;i++) {
offset <<= 8;
offset |= addr[i];
}
return read_mmcr_byte(SC520_SYSINFO) ?
spi_eeprom_write(1, offset, buffer, len) :
mw_eeprom_write(1, offset, buffer, len);
}

View file

@ -0,0 +1,82 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
*
* 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
*/
/* now setup the General purpose bus to give us access to the LEDs.
* We can then use the leds to display status information.
*/
sc520_cdp_registers:
/* size offset value */
.word 1 ; .word 0x040 ; .long 0x00 /* SDRAM buffer control */
.word 2 ; .word 0xc08 ; .long 0x0001 /* GP CS offset */
.word 2 ; .word 0xc09 ; .long 0x0003 /* GP CS width */
.word 2 ; .word 0xc0a ; .long 0x0001 /* GP CS width */
.word 2 ; .word 0xc0b ; .long 0x0003 /* GP RD pulse width */
.word 2 ; .word 0xc0c ; .long 0x0001 /* GP RD offse */
.word 2 ; .word 0xc0d ; .long 0x0003 /* GP WR pulse width */
.word 2 ; .word 0xc0e ; .long 0x0001 /* GP WR offset */
.word 2 ; .word 0xc2c ; .long 0x003f /* GPIO directionreg 31-16 */
.word 2 ; .word 0xc2a ; .long 0xe000 /* GPIO directionreg 15-0 */
.word 2 ; .word 0xc22 ; .long 0xffc0 /* GPIO pin function 31-16 reg */
.word 2 ; .word 0xc20 ; .long 0x1fff /* GPIO pin function 15-0 reg */
.word 0 ; .word 0x000 ; .long 0x00
/* board early intialization */
.globl early_board_init
early_board_init:
movl $sc520_cdp_registers,%esi
init_loop:
movl $0xfffef000,%edi /* MMCR base to edi */
movw (%esi), %bx /* load size to bx */
cmpw $0, %bx /* if size is 0 we're done */
je done
xorl %edx,%edx
movw 2(%esi), %dx /* load MMCR offset to dx */
addl %edx, %edi /* add offset to base in edi */
movl 4(%esi), %eax /* load value in eax */
cmpw $1, %bx
je byte /* byte op? */
cmpw $2, %bx
je word /* word op? */
movl %eax, (%edi) /* must be long, then */
jmp next
byte: movb %al,(%edi)
jmp next
word: movw %ax,(%edi)
next: addl $8, %esi /* advance esi */
jmp init_loop
/* light all leds */
done: movl $0xfffefc32,%edx
movw $0000,(%edx)
jmp *%ebp /* return to caller */
.globl __show_boot_progress
__show_boot_progress:
movl $0xfffefc32,%edx
xorw $0xffff, %ax
movw %ax,(%edx)
jmp *%ebp

View file

@ -0,0 +1,84 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
*
* 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
*/
/*
* 16bit initialization code.
* This code have to map the area of the boot flash
* that is used by U-boot to its final destination.
*/
.text
.section .start16, "ax"
.code16
.globl board_init16
board_init16:
/* Alias MMCR to 0xdf000 */
movw $0xfffc, %dx
movl $0x800df0cb, %eax
outl %eax, %dx
/* Set ds to point to MMCR alias */
movw $0xdf00, %ax
movw %ax, %ds
/* Map the entire flash at 0x38000000
* (with BOOTCS and PAR14, use 0xabfff800 for ROMCS1) */
movl $0xc0, %edi
movl $0x8bfff800, %eax
movl %eax, (%di)
/* Disable SDRAM write buffer */
movw $0x40,%di
xorw %ax,%ax
movb %al, (%di)
/* Disabe MMCR alias */
movw $0xfffc, %dx
movl $0x000000cb, %eax
outl %eax, %dx
/* the return address is stored in bp */
jmp *%bp
.section .bios, "ax"
.code16
.globl realmode_reset
realmode_reset:
/* Alias MMCR to 0xdf000 */
movw $0xfffc, %dx
movl $0x800df0cb, %eax
outl %eax, %dx
/* Set ds to point to MMCR alias */
movw $0xdf00, %ax
movw %ax, %ds
/* issue software reset thorugh MMCR */
movl $0xd72, %edi
movb $0x01, %al
movb %al, (%di)
1: hlt
jmp 1

View file

@ -0,0 +1,85 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
*
* 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-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0x387c0000; /* Where bootcode in the flash is mapped */
.text : { *(.text); }
. = ALIGN(4);
.rodata : { *(.rodata) }
. = 0x400000; /* Ram data segment to use */
_i386boot_romdata_dest = ABSOLUTE(.);
.data : AT ( LOADADDR(.rodata) + SIZEOF(.rodata) ) { *(.data) }
_i386boot_romdata_start = LOADADDR(.data);
. = ALIGN(4);
.got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) }
_i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got);
. = ALIGN(4);
_i386boot_bss_start = ABSOLUTE(.);
.bss : { *(.bss) }
_i386boot_bss_size = SIZEOF(.bss);
/* 16bit realmode trampoline code */
.realmode 0x7c0 : AT ( LOADADDR(.got) + SIZEOF(.got) ) { *(.realmode) }
_i386boot_realmode = LOADADDR(.realmode);
_i386boot_realmode_size = SIZEOF(.realmode);
/* 16bit BIOS emulation code (just enough to boot Linux) */
.bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { *(.bios) }
_i386boot_bios = LOADADDR(.bios);
_i386boot_bios_size = SIZEOF(.bios);
/* The load addresses below assumes that the flash
* will be mapped so that 0x387f0000 == 0xffff0000
* at reset time
*
* The fe00 and ff00 offsets of the start32 and start16
* segments are arbitrary, the just have to be mapped
* at reset and the code have to fit.
* The fff0 offset of reset is important, however.
*/
. = 0xfffffe00;
.start32 : AT (0x387ffe00) { *(.start32); }
. = 0xff00;
.start16 : AT (0x387fff00) { *(.start16); }
. = 0xfff0;
.reset : AT (0x387ffff0) { *(.reset); }
_i386boot_end = (LOADADDR(.reset) + SIZEOF(.reset) );
}

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,11 @@
# include <status_led.h>
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <linux/mtd/nand.h>
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
#endif
#define ORMASK(size) ((-size) & OR_AM_MSK)
static long ram_size(ulong *, long);
@ -321,6 +326,17 @@ int misc_init_r (void)
return (0);
}
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
void nand_init(void)
{
nand_probe(CFG_DFLASH_BASE); /* see if any NAND flash present */
if (nand_dev_desc[0].ChipID != NAND_ChipID_UNKNOWN) {
puts("NAND: ");
print_size(nand_dev_desc[0].totlen, "\n");
}
}
#endif
/* ------------------------------------------------------------------------- */
/*

View file

@ -45,25 +45,19 @@
# endif
#endif
#define FLASH_BANK_SIZE 0x200000
#define FLASH_BANK_SIZE ((uint)(16 * 1024 * 1024)) /* max 16Mbyte */
#define MAIN_SECT_SIZE 0x10000
#define SECT_SIZE_32KB 0x8000
#define SECT_SIZE_8KB 0x2000
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
static int write_word (flash_info_t *info, ulong dest, ulong data);
static __inline__ unsigned long get_msr(void)
{ unsigned long msr;
__asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
return msr;
}
static __inline__ void set_msr(unsigned long msr)
{
__asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
}
static int write_word (flash_info_t * info, ulong dest, ulong data);
#if 0
static void write_via_fpu (vu_long * addr, ulong * data);
#endif
static __inline__ unsigned long get_msr (void);
static __inline__ void set_msr (unsigned long msr);
/*flash command address offsets*/
#define ADDR0 (0x555)
@ -77,285 +71,336 @@ static __inline__ void set_msr(unsigned long msr)
/*---------------------------------------------------------------------*/
unsigned long flash_init(void)
unsigned long flash_init (void)
{
int i, j;
ulong size = 0;
int i; /* flash bank counter */
int j; /* flash device sector counter */
int k; /* flash size calculation loop counter */
int N; /* pow(2,N) is flash size, but we don't have <math.h> */
ulong total_size = 0, device_size = 1;
unsigned char manuf_id, device_id;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
{
vu_char *addr = (vu_char *)(CFG_FLASH_BASE + i * FLASH_BANK_SIZE);
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
vu_char *addr = (vu_char *) (CFG_FLASH_BASE + i * FLASH_BANK_SIZE);
addr[0x555] = 0xAA; /* 3 cycles to read device info. See */
addr[0x2AA] = 0x55; /* AM29LV116D datasheet for list of */
addr[0x555] = 0x90; /* available commands. */
addr[0x555] = 0xAA; /* get manuf/device info command */
addr[0x2AA] = 0x55; /* 3-cycle command */
addr[0x555] = 0x90;
manuf_id = addr[0];
device_id = addr[1];
manuf_id = addr[0]; /* read back manuf/device info */
device_id = addr[1];
addr[0x55] = 0x98; /* CFI command */
N = addr[0x27]; /* read back device_size = pow(2,N) */
for (k = 0; k < N; k++) /* calculate device_size = pow(2,N) */
device_size *= 2;
flash_info[i].size = device_size;
flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
#if defined DEBUG_FLASH
printf("manuf_id = %x, device_id = %x\n", manuf_id, device_id);
printf ("manuf_id = %x, device_id = %x\n", manuf_id, device_id);
#endif
/* find out what kind of flash we are using */
if ((manuf_id == (uchar) (AMD_MANUFACT))
&& (device_id == AMD_ID_LV033C)) {
flash_info[i].flash_id =
((FLASH_MAN_AMD & FLASH_VENDMASK) << 16) |
(FLASH_AM033C & FLASH_TYPEMASK);
if ( (manuf_id == (uchar)(AMD_MANUFACT)) &&
( device_id == AMD_ID_LV116DT))
{
flash_info[i].flash_id = ((FLASH_MAN_AMD & FLASH_VENDMASK) << 16) |
(AMD_ID_LV116DT & FLASH_TYPEMASK);
} else {
flash_info[i].flash_id = FLASH_UNKNOWN;
addr[0] = (long)0xFFFFFFFF;
goto Done;
/* set individual sector start addresses */
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] =
(CFG_FLASH_BASE + i * FLASH_BANK_SIZE +
j * MAIN_SECT_SIZE);
}
}
else if ((manuf_id == (uchar) (AMD_MANUFACT)) &&
(device_id == AMD_ID_LV116DT)) {
flash_info[i].flash_id =
((FLASH_MAN_AMD & FLASH_VENDMASK) << 16) |
(FLASH_AM160T & FLASH_TYPEMASK);
/* set individual sector start addresses */
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] =
(CFG_FLASH_BASE + i * FLASH_BANK_SIZE +
j * MAIN_SECT_SIZE);
if (j < (CFG_MAX_FLASH_SECT - 3)) {
flash_info[i].start[j] =
(CFG_FLASH_BASE + i * FLASH_BANK_SIZE +
j * MAIN_SECT_SIZE);
} else if (j == (CFG_MAX_FLASH_SECT - 3)) {
flash_info[i].start[j] =
(flash_info[i].start[j - 1] + SECT_SIZE_32KB);
} else {
flash_info[i].start[j] =
(flash_info[i].start[j - 1] + SECT_SIZE_8KB);
}
}
}
else {
flash_info[i].flash_id = FLASH_UNKNOWN;
addr[0] = 0xFF;
goto Done;
}
#if defined DEBUG_FLASH
printf ("flash_id = 0x%08lX\n", flash_info[i].flash_id);
#endif
addr[0] = (long)0xFFFFFFFF;
addr[0] = 0xFF;
flash_info[i].size = FLASH_BANK_SIZE;
flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
for (j = 0; j < flash_info[i].sector_count; j++)
{
total_size += flash_info[i].size;
}
if (j < (CFG_MAX_FLASH_SECT - 3) )
flash_info[i].start[j] = CFG_FLASH_BASE + i * FLASH_BANK_SIZE +
j * MAIN_SECT_SIZE;
else if (j == (CFG_MAX_FLASH_SECT - 3) )
flash_info[i].start[j] = flash_info[i].start[j-1] + SECT_SIZE_32KB;
else
flash_info[i].start[j] = flash_info[i].start[j-1] + SECT_SIZE_8KB;
}
size += flash_info[i].size;
}
/* Protect monitor and environment sectors
*/
/* Protect monitor and environment sectors
*/
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE,
CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
flash_protect (FLAG_PROTECT_SET, CFG_MONITOR_BASE,
CFG_MONITOR_BASE + monitor_flash_len - 1,
&flash_info[0]);
#endif
#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
flash_protect (FLAG_PROTECT_SET, CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
#endif
Done:
return size;
Done:
return total_size;
}
/*-----------------------------------------------------------------------
*/
void flash_print_info(flash_info_t *info)
void flash_print_info (flash_info_t * info)
{
static const char unk[] = "Unknown";
const char *mfct = unk, *type = unk;
unsigned int i;
static const char unk[] = "Unknown";
const char *mfct = unk, *type = unk;
unsigned int i;
if(info->flash_id != FLASH_UNKNOWN)
{
switch(info->flash_id & FLASH_VENDMASK)
{
case FLASH_MAN_AMD: mfct = "AMD"; break;
case FLASH_MAN_FUJ: mfct = "FUJITSU"; break;
case FLASH_MAN_STM: mfct = "STM"; break;
case FLASH_MAN_SST: mfct = "SST"; break;
case FLASH_MAN_BM: mfct = "Bright Microelectonics"; break;
case FLASH_MAN_INTEL: mfct = "Intel"; break;
}
if (info->flash_id != FLASH_UNKNOWN) {
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_AMD:
mfct = "AMD";
break;
case FLASH_MAN_FUJ:
mfct = "FUJITSU";
break;
case FLASH_MAN_STM:
mfct = "STM";
break;
case FLASH_MAN_SST:
mfct = "SST";
break;
case FLASH_MAN_BM:
mfct = "Bright Microelectonics";
break;
case FLASH_MAN_INTEL:
mfct = "Intel";
break;
}
switch(info->flash_id & FLASH_TYPEMASK)
{
case FLASH_AM040: type = "AM29F040B (512K * 8, uniform sector size)"; break;
case FLASH_AM400B: type = "AM29LV400B (4 Mbit, bottom boot sect)"; break;
case FLASH_AM400T: type = "AM29LV400T (4 Mbit, top boot sector)"; break;
case FLASH_AM800B: type = "AM29LV800B (8 Mbit, bottom boot sect)"; break;
case FLASH_AM800T: type = "AM29LV800T (8 Mbit, top boot sector)"; break;
case FLASH_AM160T: type = "AM29LV160T (16 Mbit, top boot sector)"; break;
case FLASH_AM320B: type = "AM29LV320B (32 Mbit, bottom boot sect)"; break;
case FLASH_AM320T: type = "AM29LV320T (32 Mbit, top boot sector)"; break;
case FLASH_STM800AB: type = "M29W800AB (8 Mbit, bottom boot sect)"; break;
case FLASH_SST800A: type = "SST39LF/VF800 (8 Mbit, uniform sector size)"; break;
case FLASH_SST160A: type = "SST39LF/VF160 (16 Mbit, uniform sector size)"; break;
}
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_AM033C:
type = "AM29LV033C (32 Mbit, uniform sector size)";
break;
case FLASH_AM160T:
type = "AM29LV160T (16 Mbit, top boot sector)";
break;
case FLASH_AM040:
type = "AM29F040B (512K * 8, uniform sector size)";
break;
case FLASH_AM400B:
type = "AM29LV400B (4 Mbit, bottom boot sect)";
break;
case FLASH_AM400T:
type = "AM29LV400T (4 Mbit, top boot sector)";
break;
case FLASH_AM800B:
type = "AM29LV800B (8 Mbit, bottom boot sect)";
break;
case FLASH_AM800T:
type = "AM29LV800T (8 Mbit, top boot sector)";
break;
case FLASH_AM320B:
type = "AM29LV320B (32 Mbit, bottom boot sect)";
break;
case FLASH_AM320T:
type = "AM29LV320T (32 Mbit, top boot sector)";
break;
case FLASH_STM800AB:
type = "M29W800AB (8 Mbit, bottom boot sect)";
break;
case FLASH_SST800A:
type = "SST39LF/VF800 (8 Mbit, uniform sector size)";
break;
case FLASH_SST160A:
type = "SST39LF/VF160 (16 Mbit, uniform sector size)";
break;
}
}
printf(
"\n Brand: %s Type: %s\n"
" Size: %lu KB in %d Sectors\n",
mfct,
type,
info->size >> 10,
info->sector_count
);
printf ("\n Brand: %s Type: %s\n"
" Size: %lu KB in %d Sectors\n",
mfct, type, info->size >> 10, info->sector_count);
printf (" Sector Start Addresses:");
printf (" Sector Start Addresses:");
for (i = 0; i < info->sector_count; i++)
{
unsigned long size;
unsigned int erased;
unsigned long * flash = (unsigned long *) info->start[i];
for (i = 0; i < info->sector_count; i++) {
unsigned long size;
unsigned int erased;
unsigned long *flash = (unsigned long *) info->start[i];
/*
* Check if whole sector is erased
*/
size =
(i != (info->sector_count - 1)) ?
(info->start[i + 1] - info->start[i]) >> 2 :
(info->start[0] + info->size - info->start[i]) >> 2;
/*
* Check if whole sector is erased
*/
size = (i != (info->sector_count - 1)) ?
(info->start[i + 1] - info->start[i]) >> 2 :
(info->start[0] + info->size - info->start[i]) >> 2;
for(
flash = (unsigned long *) info->start[i], erased = 1;
(flash != (unsigned long *) info->start[i] + size) && erased;
flash++
)
erased = *flash == ~0x0UL;
for (flash = (unsigned long *) info->start[i], erased = 1;
(flash != (unsigned long *) info->start[i] + size) && erased;
flash++)
erased = *flash == ~0x0UL;
printf(
"%s %08lX %s %s",
(i % 5) ? "" : "\n ",
info->start[i],
erased ? "E" : " ",
info->protect[i] ? "RO" : " "
);
}
printf ("%s %08lX %s %s",
(i % 5) ? "" : "\n ",
info->start[i],
erased ? "E" : " ", info->protect[i] ? "RO" : " ");
}
puts("\n");
return;
puts ("\n");
return;
}
/*-----------------------------------------------------------------------
*/
int flash_erase (flash_info_t *info, int s_first, int s_last)
int flash_erase (flash_info_t * info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
int flag, prot, sect, l_sect;
ulong start, now, last;
unsigned char sh8b;
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
int flag, prot, sect, l_sect;
ulong start, now, last;
unsigned char sh8b;
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;
}
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;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
printf ("Can't erase unknown flash type - aborted\n");
return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
printf ("Can't erase unknown flash type - aborted\n");
return 1;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
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");
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!\n",
prot);
} else {
printf ("\n");
}
l_sect = -1;
l_sect = -1;
/* Check the ROM CS */
if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
sh8b = 3;
else
sh8b = 0;
/* Check the ROM CS */
if ((info->start[0] >= ROM_CS1_START)
&& (info->start[0] < ROM_CS0_START))
sh8b = 3;
else
sh8b = 0;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
flag = disable_interrupts ();
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00800080;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++)
{
if (info->protect[sect] == 0)
{ /* not protected */
addr = (FLASH_WORD_SIZE *)(info->start[0] + (
(info->start[sect] - info->start[0]) << sh8b));
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr = (FLASH_WORD_SIZE *) (info->start[0] + ((info->
start[sect] -
info->
start[0]) <<
sh8b));
if (info->flash_id & FLASH_MAN_SST)
{
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
addr[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
udelay(30000); /* wait 30 ms */
if (info->flash_id & FLASH_MAN_SST) {
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00800080;
addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
addr[0] = (FLASH_WORD_SIZE) 0x00500050; /* block erase */
udelay (30000); /* wait 30 ms */
} else {
addr[0] = (FLASH_WORD_SIZE) 0x00300030; /* sector erase */
}
else
addr[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
l_sect = sect;
}
}
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts ();
/* wait at least 80us - let's wait 1 ms */
udelay (1000);
/* wait at least 80us - let's wait 1 ms */
udelay (1000);
/*
* We wait for the last triggered sector
*/
if (l_sect < 0)
goto DONE;
/*
* We wait for the last triggered sector
*/
if (l_sect < 0)
goto DONE;
start = get_timer (0);
last = start;
addr = (FLASH_WORD_SIZE *)(info->start[0] + (
(info->start[l_sect] - info->start[0]) << sh8b));
while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
serial_putc ('.');
last = now;
}
}
start = get_timer (0);
last = start;
addr = (FLASH_WORD_SIZE *) (info->start[0] + ((info->start[l_sect] -
info->
start[0]) << sh8b));
while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
(FLASH_WORD_SIZE) 0x00800080) {
if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
serial_putc ('.');
last = now;
}
}
DONE:
/* reset to read mode */
addr = (FLASH_WORD_SIZE *)info->start[0];
addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
DONE:
/* reset to read mode */
addr = (FLASH_WORD_SIZE *) info->start[0];
addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
printf (" done\n");
return 0;
printf (" done\n");
return 0;
}
@ -366,68 +411,68 @@ DONE:
* 2 - Flash not erased
*/
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;
ulong cp, wp, data;
int i, l, rc;
wp = (addr & ~3); /* get lower word aligned address */
wp = (addr & ~3); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
for (; i<4 && cnt>0; ++i) {
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i = 0, cp = wp; i < l; ++i, ++cp) {
data = (data << 8) | (*(uchar *) cp);
}
for (; i < 4 && cnt > 0; ++i) {
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt == 0 && i < 4; ++i, ++cp) {
data = (data << 8) | (*(uchar *) cp);
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
}
if ((rc = write_word (info, wp, data)) != 0) {
return (rc);
}
wp += 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = 0;
for (i=0; i<4; ++i) {
data = (data << 8) | *src++;
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
cnt -= 4;
}
/*
* handle word aligned part
*/
while (cnt >= 4) {
data = 0;
for (i = 0; i < 4; ++i) {
data = (data << 8) | *src++;
}
if ((rc = write_word (info, wp, data)) != 0) {
return (rc);
}
wp += 4;
cnt -= 4;
}
if (cnt == 0) {
return (0);
}
if (cnt == 0) {
return (0);
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
data = (data << 8) | *src++;
--cnt;
}
for (; i<4; ++i, ++cp) {
data = (data << 8) | (*(uchar *)cp);
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
data = (data << 8) | *src++;
--cnt;
}
for (; i < 4; ++i, ++cp) {
data = (data << 8) | (*(uchar *) cp);
}
return (write_word(info, wp, data));
return (write_word (info, wp, data));
}
@ -437,55 +482,79 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
* 1 - write timeout
* 2 - Flash not erased
*/
static int write_word (flash_info_t *info, ulong dest, ulong data)
static int write_word (flash_info_t * info, ulong dest, ulong data)
{
volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) info->start[0];
volatile FLASH_WORD_SIZE *dest2;
volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
ulong start;
int flag;
int i;
unsigned char sh8b;
/* Check the ROM CS */
if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
sh8b = 3;
else
sh8b = 0;
/* Check the ROM CS */
if ((info->start[0] >= ROM_CS1_START)
&& (info->start[0] < ROM_CS0_START))
sh8b = 3;
else
sh8b = 0;
dest2 = (FLASH_WORD_SIZE *)(((dest - info->start[0]) << sh8b) +
info->start[0]);
dest2 = (FLASH_WORD_SIZE *) (((dest - info->start[0]) << sh8b) +
info->start[0]);
/* Check if Flash is (sufficiently) erased */
if ((*dest2 & (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
return (2);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Check if Flash is (sufficiently) erased */
if ((*dest2 & (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
return (2);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts ();
for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
{
addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00A000A0;
for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00AA00AA;
addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE) 0x00550055;
addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE) 0x00A000A0;
dest2[i << sh8b] = data2[i];
dest2[i << sh8b] = data2[i];
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts ();
/* data polling for D7 */
start = get_timer (0);
while ((dest2[i << sh8b] & (FLASH_WORD_SIZE)0x00800080) !=
(data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
}
/* data polling for D7 */
start = get_timer (0);
while ((dest2[i << sh8b] & (FLASH_WORD_SIZE) 0x00800080) !=
(data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
}
return (0);
return (0);
}
/*-----------------------------------------------------------------------
*/
#if 0
static void write_via_fpu (vu_long * addr, ulong * data)
{
__asm__ __volatile__ ("lfd 1, 0(%0)"::"r" (data));
__asm__ __volatile__ ("stfd 1, 0(%0)"::"r" (addr));
}
#endif
/*-----------------------------------------------------------------------
*/
static __inline__ unsigned long get_msr (void)
{
unsigned long msr;
__asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
return msr;
}
static __inline__ void set_msr (unsigned long msr)
{
__asm__ __volatile__ ("mtmsr %0"::"r" (msr));
}

View file

@ -30,6 +30,7 @@
#include <mpc824x.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/mmu.h>
#include <pci.h>
#define SAVE_SZ 32
@ -53,11 +54,18 @@ long int initdram(int board_type)
volatile ulong *addr;
ulong save[SAVE_SZ];
ulong val, ret = 0;
/*
write_bat(IBAT1, ((CFG_MAX_RAM_SIZE/2) | BATU_BL_256M | BATU_VS | BATU_VP),
( (CFG_MAX_RAM_SIZE/2)| BATL_PP_10 | BATL_MEMCOHERENCE));
for (i=0; i<SAVE_SZ; i++) {save[i] = 0;} /* clear table */
write_bat(DBAT1, ((CFG_MAX_RAM_SIZE/2) | BATU_BL_256M | BATU_VS | BATU_VP),
( (CFG_MAX_RAM_SIZE/2)| BATL_PP_10 | BATL_MEMCOHERENCE));
*/
for (i=0; i<SAVE_SZ; i++) {
save[i] = 0; /* clear table */
}
for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1)
{
for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
addr = (volatile ulong *)base + cnt;
save[i++] = *addr;
*addr = ~cnt;
@ -67,19 +75,16 @@ long int initdram(int board_type)
save[i] = *addr;
*addr = 0;
if (*addr != 0)
{
if (*addr != 0) {
*addr = save[i];
goto Done;
}
for (cnt = 1; cnt < CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1)
{
for (cnt = 1; cnt < CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) {
addr = (volatile ulong *)base + cnt;
val = *addr;
*addr = save[--i];
if (val != ~cnt)
{
if (val != ~cnt) {
ulong new_bank0_end = cnt * sizeof(long) - 1;
ulong mear1 = mpc824x_mpc107_getreg(MEAR1);
ulong emear1 = mpc824x_mpc107_getreg(EMEAR1);
@ -111,11 +116,11 @@ Done:
static struct pci_config_table pci_utx8245_config_table[] = {
#ifndef CONFIG_PCI_PNP
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0C, PCI_ANY_ID,
pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
PCI_ENET0_MEMADDR,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0B, PCI_ANY_ID,
pci_cfgfunc_config_device, { PCI_FIREWIRE_IOADDR,
PCI_FIREWIRE_MEMADDR,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
@ -133,6 +138,14 @@ static void pci_utx8245_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
else if (PCI_DEV(dev) == 12)
/* assign serial interrupt line 8 (int24) to Ethernet */
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 24);
else if (PCI_DEV(dev) == 14)
/* assign serial interrupt line 0 (int16) to PMC slot 0 */
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 16);
else if (PCI_DEV(dev) == 15)
/* assign serial interrupt line 1 (int17) to PMC slot 1 */
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 17);
}
static struct pci_controller utx8245_hose = {

View file

@ -36,7 +36,7 @@ COBJS = main.o altera.o bedbug.o \
cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \
cmd_net.o cmd_nvedit.o env_common.o \
env_flash.o env_eeprom.o env_nvram.o env_nowhere.o \
cmd_pci.o cmd_pcmcia.o \
cmd_pci.o cmd_pcmcia.o cmd_portio.o \
cmd_reginfo.o cmd_scsi.o cmd_vfd.o cmd_usb.o \
command.o console.o devices.o dlmalloc.o \
docecc.o environment.o flash.o fpga.o \

View file

@ -31,7 +31,8 @@
#include <command.h>
#include <cmd_mem.h>
#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C))
#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C\
| CMD_CMD_PORTIO))
int cmd_get_data_size(char* arg, int default_size)
{
/* Check for a size specification .b, .w or .l.

View file

@ -20,9 +20,9 @@
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <linux/mtd/nftl.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ids.h>
#include <jffs2/jffs2.h>
/*
* Definition of the out of band configuration structure
@ -33,14 +33,32 @@ struct nand_oob_config {
int eccvalid_pos; /* position of ECC valid flag inside oob -1 = inactive */
} oob_config = { {0}, 0, 0};
#define NAND_DEBUG
#undef ECC_DEBUG
#undef NAND_DEBUG
#undef PSYCHO_DEBUG
#undef NFTL_DEBUG
/* ****************** WARNING *********************
* When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
* erase (or at least attempt to erase) blocks that are marked
* bad. This can be very handy if you are _sure_ that the block
* is OK, say because you marked a good block bad to test bad
* block handling and you are done testing, or if you have
* accidentally marked blocks bad.
*
* Erasing factory marked bad blocks is a _bad_ idea. If the
* erase succeeds there is no reliable way to find them again,
* and attempting to program or erase bad blocks can affect
* the data in _other_ (good) blocks.
*/
#define ALLOW_ERASE_BAD_DEBUG 0
#define CONFIG_MTD_NAND_ECC /* enable ECC */
/* #define CONFIG_MTD_NAND_ECC_JFFS2 */
/* bits for nand_rw() `cmd'; or together as needed */
#define NANDRW_READ 0x01
#define NANDRW_WRITE 0x00
#define NANDRW_JFFS2 0x02
/*
* Function Prototypes
*/
@ -48,17 +66,22 @@ static void nand_print(struct nand_chip *nand);
static int nand_rw (struct nand_chip* nand, int cmd,
size_t start, size_t len,
size_t * retlen, u_char * buf);
static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len);
static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
size_t * retlen, u_char *buf, u_char *ecc_code);
static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
size_t * retlen, const u_char * buf, u_char * ecc_code);
static void nand_print_bad(struct nand_chip *nand);
static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
size_t * retlen, u_char * buf);
static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
size_t * retlen, const u_char * buf);
#ifdef CONFIG_MTD_NAND_ECC
static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
#endif
static struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
/* Current NAND Device */
static int curr_device = -1;
@ -96,6 +119,16 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
printf ("\nDevice %d: ", curr_device);
nand_print(&nand_dev_desc[curr_device]);
return 0;
} else if (strcmp(argv[1],"bad") == 0) {
if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
puts ("\nno devices available\n");
return 1;
}
printf ("\nDevice %d bad blocks:\n", curr_device);
nand_print_bad(&nand_dev_desc[curr_device]);
return 0;
}
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
@ -121,38 +154,86 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 0;
}
else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
struct nand_chip* nand = &nand_dev_desc[curr_device];
ulong off = 0;
ulong size = nand->totlen;
int ret;
printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
curr_device, off, size);
ret = nand_erase (nand, off, size, 1);
printf("%s\n", ret ? "ERROR" : "OK");
return ret;
}
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
default:
/* at least 4 args */
if (strcmp(argv[1],"read") == 0 || strcmp(argv[1],"write") == 0) {
if (strncmp(argv[1], "read", 4) == 0 ||
strncmp(argv[1], "write", 5) == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong off = simple_strtoul(argv[3], NULL, 16);
ulong size = simple_strtoul(argv[4], NULL, 16);
int cmd = (strcmp(argv[1],"read") == 0);
int cmd = (strncmp(argv[1], "read", 4) == 0) ?
NANDRW_READ : NANDRW_WRITE;
int ret, total;
char* cmdtail = strchr(argv[1], '.');
if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
/* read out-of-band data */
if (cmd & NANDRW_READ) {
ret = nand_read_oob(nand_dev_desc + curr_device,
off, size, &total,
(u_char*)addr);
}
else {
ret = nand_write_oob(nand_dev_desc + curr_device,
off, size, &total,
(u_char*)addr);
}
return ret;
}
else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
cmd |= NANDRW_JFFS2; /* skip bad blocks */
#ifdef SXNI855T
/* need ".e" same as ".j" for compatibility with older units */
else if (cmdtail && !strcmp(cmdtail, ".e"))
cmd |= NANDRW_JFFS2; /* skip bad blocks */
#endif
else if (cmdtail) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
cmd ? "read" : "write", curr_device, off, size);
(cmd & NANDRW_READ) ? "read" : "write",
curr_device, off, size);
ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
&total, (u_char*)addr);
printf ("%d bytes %s: %s\n", total, cmd ? "read" : "write",
printf ("%d bytes %s: %s\n", total,
(cmd & NANDRW_READ) ? "read" : "write",
ret ? "ERROR" : "OK");
return ret;
} else if (strcmp(argv[1],"erase") == 0) {
ulong off = simple_strtoul(argv[2], NULL, 16);
ulong size = simple_strtoul(argv[3], NULL, 16);
} else if (strcmp(argv[1],"erase") == 0 &&
(argc == 4 || strcmp("clean", argv[2]) == 0)) {
int clean = argc == 5;
ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
int ret;
printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
curr_device, off, size);
ret = nand_erase (nand_dev_desc + curr_device, off, size);
ret = nand_erase (nand_dev_desc + curr_device, off, size, clean);
printf("%s\n", ret ? "ERROR" : "OK");
@ -215,11 +296,11 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 1;
}
printf ("\nLoading from device %d: %s at 0x%lX (offset 0x%lX)\n",
printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
offset);
if (nand_rw (nand_dev_desc + dev, 1, offset,
if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset,
SECTORSIZE, NULL, (u_char *)addr)) {
printf ("** Read error on %d\n", dev);
SHOW_BOOT_PROGRESS (-1);
@ -240,7 +321,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 1;
}
if (nand_rw (nand_dev_desc + dev, 1, offset + SECTORSIZE, cnt,
if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt,
NULL, (u_char *)(addr+SECTORSIZE))) {
printf ("** Read error on %d\n", dev);
SHOW_BOOT_PROGRESS (-1);
@ -259,7 +340,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
do_bootm (cmdtp, 0, 1, local_args);
rcode = 1;
@ -267,23 +348,103 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return rcode;
}
/* returns 0 if block containing pos is OK:
* valid erase block and
* not marked bad, or no bad mark position is specified
* returns 1 if marked bad or otherwise invalid
*/
int check_block(struct nand_chip* nand, unsigned long pos)
{
int retlen;
uint8_t oob_data;
int page0 = pos & (-nand->erasesize);
int page1 = page0 + nand->oobblock;
int badpos = oob_config.badblock_pos;
if (pos >= nand->totlen)
return 1;
if (badpos < 0)
return 0; /* no way to check, assume OK */
/* Note - bad block marker can be on first or second page */
if (nand_read_oob(nand, page0 + badpos, 1, &retlen, &oob_data) ||
oob_data != 0xff ||
nand_read_oob(nand, page1 + badpos, 1, &retlen, &oob_data) ||
oob_data != 0xff)
return 1;
return 0;
}
/* print bad blocks in NAND flash */
static void nand_print_bad(struct nand_chip* nand)
{
unsigned long pos;
for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
if (check_block(nand, pos))
printf(" 0x%8.8lx\n", pos);
}
puts("\n");
}
/* cmd: 0: NANDRW_WRITE write, fail on bad block
* 1: NANDRW_READ read, fail on bad block
* 2: NANDRW_WRITE | NANDRW_JFFS2 write, skip bad blocks
* 3: NANDRW_READ | NANDRW_JFFS2 read, data all 0xff for bad blocks
*/
static int nand_rw (struct nand_chip* nand, int cmd,
size_t start, size_t len,
size_t * retlen, u_char * buf)
{
int noecc, ret = 0, n, total = 0;
char eccbuf[6];
/* eblk (once set) is the start of the erase block containing the
* data being processed.
*/
unsigned long eblk = ~0; /* force mismatch on first pass */
unsigned long erasesize = nand->erasesize;
while(len) {
while (len) {
if ((start & (-erasesize)) != eblk) {
/* have crossed into new erase block, deal with
* it if it is sure marked bad.
*/
eblk = start & (-erasesize); /* start of block */
if (check_block(nand, eblk)) {
if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
while (len > 0 &&
start - eblk < erasesize) {
*(buf++) = 0xff;
++start;
++total;
--len;
}
continue;
}
else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
/* skip bad block */
start += erasesize;
continue;
}
else {
ret = 1;
break;
}
}
}
/* The ECC will not be calculated correctly if
less than 512 is written or read */
noecc = (start != (start | 0x1ff) + 1) || (len < 0x200);
if (cmd)
ret = nand_read_ecc(nand, start, len,
if (cmd & NANDRW_READ)
ret = nand_read_ecc(nand, start,
min(len, eblk + erasesize - start),
&n, (u_char*)buf,
noecc ? NULL : eccbuf);
else
ret = nand_write_ecc(nand, start, len,
ret = nand_write_ecc(nand, start,
min(len, eblk + erasesize - start),
&n, (u_char*)buf,
noecc ? NULL : eccbuf);
@ -303,30 +464,18 @@ static int nand_rw (struct nand_chip* nand, int cmd,
static void nand_print(struct nand_chip *nand)
{
printf("%s at 0x%lX,\n"
"\t %d chip%s %s, size %d MB, \n"
"\t total size %ld MB, sector size %ld kB\n",
nand->name, nand->IO_ADDR, nand->numchips,
nand->numchips>1 ? "s" : "", nand->chips_name,
1 << (nand->chipshift - 20),
nand->totlen >> 20, nand->erasesize >> 10);
if (nand->nftl_found) {
struct NFTLrecord *nftl = &nand->nftl;
unsigned long bin_size, flash_size;
bin_size = nftl->nb_boot_blocks * nand->erasesize;
flash_size = (nftl->nb_blocks - nftl->nb_boot_blocks) * nand->erasesize;
printf("\t NFTL boot record:\n"
"\t Binary partition: size %ld%s\n"
"\t Flash disk partition: size %ld%s, offset 0x%lx\n",
bin_size > (1 << 20) ? bin_size >> 20 : bin_size >> 10,
bin_size > (1 << 20) ? "MB" : "kB",
flash_size > (1 << 20) ? flash_size >> 20 : flash_size >> 10,
flash_size > (1 << 20) ? "MB" : "kB", bin_size);
} else {
puts ("\t No NFTL boot record found.\n");
if (nand->numchips > 1) {
printf("%s at 0x%lx,\n"
"\t %d chips %s, size %d MB, \n"
"\t total size %ld MB, sector size %ld kB\n",
nand->name, nand->IO_ADDR, nand->numchips,
nand->chips_name, 1 << (nand->chipshift - 20),
nand->totlen >> 20, nand->erasesize >> 10);
}
else {
printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
print_size(nand->totlen, ", ");
print_size(nand->erasesize, " sector)\n");
}
}
@ -484,6 +633,7 @@ static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
nand->chipshift =
nand_flash_ids[i].chipshift;
nand->page256 = nand_flash_ids[i].page256;
nand->eccsize = 256;
if (nand->page256) {
nand->oobblock = 256;
nand->oobsize = 8;
@ -579,41 +729,12 @@ static void NanD_ScanChips(struct nand_chip *nand)
#endif
}
#ifdef CONFIG_MTD_NAND_ECC
/* we need to be fast here, 1 us per read translates to 1 second per meg */
static void nand_fast_copy (unsigned char *source, unsigned char *dest, long cntr)
static void NanD_ReadBuf(struct nand_chip *nand, u_char *data_buf, int cntr)
{
while (cntr > 16) {
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
cntr -= 16;
}
unsigned long nandptr = nand->IO_ADDR;
while (cntr > 0) {
*dest++ = *source++;
cntr--;
}
}
#endif
/* we need to be fast here, 1 us per read translates to 1 second per meg */
static void nand_fast_read(unsigned char *data_buf, int cntr, unsigned long nandptr)
{
while (cntr > 16) {
while (cntr >= 16) {
*data_buf++ = READ_NAND(nandptr);
*data_buf++ = READ_NAND(nandptr);
*data_buf++ = READ_NAND(nandptr);
@ -639,14 +760,6 @@ static void nand_fast_read(unsigned char *data_buf, int cntr, unsigned long nand
}
}
/* This routine is made available to other mtd code via
* inter_module_register. It must only be accessed through
* inter_module_get which will bump the use count of this module. The
* addresses passed back in mtd are valid as long as the use count of
* this module is non-zero, i.e. between inter_module_get and
* inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
*/
/*
* NAND read with ECC
*/
@ -661,7 +774,6 @@ static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
u_char *data_poi;
u_char ecc_calc[6];
#endif
unsigned long nandptr = nand->IO_ADDR;
/* Do not allow reads past end of device */
if ((start + len) > nand->totlen) {
@ -696,7 +808,7 @@ static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
NanD_Command(nand, NAND_CMD_READ0);
NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
/* Read in a page + oob data */
nand_fast_read(nand->data_buf, nand->oobblock + nand->oobsize, nandptr);
NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
/* copy data into cache, for read out of cache and if ecc fails */
if (nand->data_cache)
@ -719,7 +831,8 @@ static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
break;
case 1:
case 2: /* transfer ECC corrected data to cache */
memcpy (nand->data_cache, nand->data_buf, 256);
if (nand->data_cache)
memcpy (nand->data_cache, nand->data_buf, 256);
break;
}
}
@ -745,10 +858,10 @@ readdata:
data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
data_poi += col;
if ((*retlen + (nand->oobblock - col)) >= len) {
nand_fast_copy (data_poi, buf + *retlen, len - *retlen);
memcpy (buf + *retlen, data_poi, len - *retlen);
*retlen = len;
} else {
nand_fast_copy (data_poi, buf + *retlen, nand->oobblock - col);
memcpy (buf + *retlen, data_poi, nand->oobblock - col);
*retlen += nand->oobblock - col;
}
/* Set cache page address, invalidate, if ecc_failed */
@ -763,12 +876,12 @@ readdata:
NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
/* Read the data directly into the return buffer */
if ((*retlen + (nand->oobblock - col)) >= len) {
nand_fast_read(buf + *retlen, len - *retlen, nandptr);
NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
*retlen = len;
/* We're done */
continue;
} else {
nand_fast_read(buf + *retlen, nand->oobblock - col, nandptr);
NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col);
*retlen += nand->oobblock - col;
}
#endif
@ -847,6 +960,7 @@ static int nand_write_page (struct nand_chip *nand,
nand->data_buf[i] = 0xff;
/* Send command to begin auto page programming */
NanD_Command(nand, NAND_CMD_READ0);
NanD_Command(nand, NAND_CMD_SEQIN);
NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
@ -982,180 +1096,17 @@ out:
return ret;
}
#if 0 /* not used */
/* Read a buffer from NanD */
static void NanD_ReadBuf(struct nand_chip *nand, u_char * buf, int len)
{
unsigned long nandptr;
nandptr = nand->IO_ADDR;
for (; len > 0; len--)
*buf++ = READ_NAND(nandptr);
}
/* Write a buffer to NanD */
static void NanD_WriteBuf(struct nand_chip *nand, const u_char * buf, int len)
{
unsigned long nandptr;
int i;
nandptr = nand->IO_ADDR;
if (len <= 0)
return;
for (i = 0; i < len; i++)
WRITE_NAND(buf[i], nandptr);
}
/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
* various device information of the NFTL partition and Bad Unit Table. Update
* the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
* is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
/* read from the 16 bytes of oob data that correspond to a 512 byte
* page or 2 256-byte pages.
*/
static int find_boot_record(struct NFTLrecord *nftl)
{
struct nftl_uci1 h1;
struct nftl_oob oob;
unsigned int block, boot_record_count = 0;
int retlen;
u8 buf[SECTORSIZE];
struct NFTLMediaHeader *mh = &nftl->MediaHdr;
unsigned int i;
nftl->MediaUnit = BLOCK_NIL;
nftl->SpareMediaUnit = BLOCK_NIL;
/* search for a valid boot record */
for (block = 0; block < nftl->nb_blocks; block++) {
int ret;
/* Check for ANAND header first. Then can whinge if it's found but later
checks fail */
if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,
&retlen, buf, NULL))) {
static int warncount = 5;
if (warncount) {
printf("Block read at 0x%x failed\n", block * nftl->EraseSize);
if (!--warncount)
puts ("Further failures for this block will not be printed\n");
}
continue;
}
if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
/* ANAND\0 not found. Continue */
#ifdef PSYCHO_DEBUG
printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize);
#endif
continue;
}
#ifdef NFTL_DEBUG
printf("ANAND header found at 0x%x\n", block * nftl->EraseSize);
#endif
/* To be safer with BIOS, also use erase mark as discriminant */
if ((ret = nand_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
8, &retlen, (char *)&h1) < 0)) {
#ifdef NFTL_DEBUG
printf("ANAND header found at 0x%x, but OOB data read failed\n",
block * nftl->EraseSize);
#endif
continue;
}
/* OK, we like it. */
if (boot_record_count) {
/* We've already processed one. So we just check if
this one is the same as the first one we found */
if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {
#ifdef NFTL_DEBUG
printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n",
nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
#endif
/* if (debug) Print both side by side */
return -1;
}
if (boot_record_count == 1)
nftl->SpareMediaUnit = block;
boot_record_count++;
continue;
}
/* This is the first we've seen. Copy the media header structure into place */
memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
/* Do some sanity checks on it */
if (mh->UnitSizeFactor != 0xff) {
puts ("Sorry, we don't support UnitSizeFactor "
"of != 1 yet.\n");
return -1;
}
nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
printf ("NFTL Media Header sanity check failed:\n"
"nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
nftl->nb_boot_blocks, nftl->nb_blocks);
return -1;
}
nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {
printf ("NFTL Media Header sanity check failed:\n"
"numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",
nftl->numvunits,
nftl->nb_blocks,
nftl->nb_boot_blocks);
return -1;
}
nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
/* If we're not using the last sectors in the device for some reason,
reduce nb_blocks accordingly so we forget they're there */
nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
for (i = 0; i < nftl->nb_blocks; i++) {
if ((i & (SECTORSIZE - 1)) == 0) {
/* read one sector for every SECTORSIZE of blocks */
if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize +
i + SECTORSIZE, SECTORSIZE,
&retlen, buf, (char *)&oob)) < 0) {
puts ("Read of bad sector table failed\n");
return -1;
}
}
/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
if (buf[i & (SECTORSIZE - 1)] != 0xff)
nftl->ReplUnitTable[i] = BLOCK_RESERVED;
}
nftl->MediaUnit = block;
boot_record_count++;
} /* foreach (block) */
return boot_record_count?0:-1;
}
static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
size_t * retlen, u_char * buf)
size_t * retlen, u_char * buf)
{
int len256 = 0, ret;
unsigned long nandptr;
int len256 = 0;
struct Nand *mychip;
int ret = 0;
nandptr = nand->IO_ADDR;
mychip = &nand->chips[shr(ofs, nand->chipshift)];
mychip = &nand->chips[ofs >> nand->chipshift];
/* update address for 2M x 8bit devices. OOB starts on the second */
/* page to maintain compatibility with nand_read_ecc. */
@ -1166,6 +1117,7 @@ static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
ofs -= 0x8;
}
NAND_ENABLE_CE(nand); /* set pin low */
NanD_Command(nand, NAND_CMD_READOOB);
NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
@ -1188,14 +1140,20 @@ static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
* to wait until ready 11.4.1 and Toshiba TC58256FT nands */
ret = NanD_WaitReady(nand);
NAND_DISABLE_CE(nand); /* set pin high */
return ret;
}
/* write to the 16 bytes of oob data that correspond to a 512 byte
* page or 2 256-byte pages.
*/
static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
size_t * retlen, const u_char * buf)
{
int len256 = 0;
int i;
unsigned long nandptr = nand->IO_ADDR;
#ifdef PSYCHO_DEBUG
@ -1204,6 +1162,8 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
buf[8], buf[9], buf[14],buf[15]);
#endif
NAND_ENABLE_CE(nand); /* set pin low to enable chip */
/* Reset the chip */
NanD_Command(nand, NAND_CMD_RESET);
@ -1229,7 +1189,8 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
/* next OOB block, but it didn't work here. mf. */
if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
len256 = (ofs | 0x7) + 1 - ofs;
NanD_WriteBuf(nand, buf, len256);
for (i = 0; i < len256; i++)
WRITE_NAND(buf[i], nandptr);
NanD_Command(nand, NAND_CMD_PAGEPROG);
NanD_Command(nand, NAND_CMD_STATUS);
@ -1238,6 +1199,7 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
if (READ_NAND(nandptr) & 1) {
puts ("Error programming oob data\n");
/* There was an error */
NAND_DISABLE_CE(nand); /* set pin high */
*retlen = 0;
return -1;
}
@ -1245,7 +1207,8 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
}
NanD_WriteBuf(nand, &buf[len256], len - len256);
for (i = len256; i < len; i++)
WRITE_NAND(buf[i], nandptr);
NanD_Command(nand, NAND_CMD_PAGEPROG);
NanD_Command(nand, NAND_CMD_STATUS);
@ -1254,18 +1217,27 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
if (READ_NAND(nandptr) & 1) {
puts ("Error programming oob data\n");
/* There was an error */
NAND_DISABLE_CE(nand); /* set pin high */
*retlen = 0;
return -1;
}
NAND_DISABLE_CE(nand); /* set pin high */
*retlen = len;
return 0;
}
#endif
static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
{
/* This is defined as a structure so it will work on any system
* using native endian jffs2 (the default).
*/
static struct jffs2_unknown_node clean_marker = {
JFFS2_MAGIC_BITMASK,
JFFS2_NODETYPE_CLEANMARKER,
8 /* 8 bytes in this node */
};
unsigned long nandptr;
struct Nand *mychip;
int ret = 0;
@ -1289,9 +1261,6 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
goto out;
}
/* Select the NAND device */
NAND_ENABLE_CE(nand); /* set pin low */
/* Check the WP bit */
NanD_Command(nand, NAND_CMD_STATUS);
if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
@ -1305,18 +1274,49 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len)
/*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
mychip = &nand->chips[ofs >> nand->chipshift];
NanD_Command(nand, NAND_CMD_ERASE1);
NanD_Address(nand, ADDR_PAGE, ofs);
NanD_Command(nand, NAND_CMD_ERASE2);
/* always check for bad block first, genuine bad blocks
* should _never_ be erased.
*/
if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
/* Select the NAND device */
NAND_ENABLE_CE(nand); /* set pin low */
NanD_Command(nand, NAND_CMD_STATUS);
NanD_Command(nand, NAND_CMD_ERASE1);
NanD_Address(nand, ADDR_PAGE, ofs);
NanD_Command(nand, NAND_CMD_ERASE2);
if (READ_NAND(nandptr) & 1) {
printf ("%s: Error erasing at 0x%lx\n",
__FUNCTION__, (long)ofs);
/* There was an error */
ret = -1;
goto out;
NanD_Command(nand, NAND_CMD_STATUS);
if (READ_NAND(nandptr) & 1) {
printf ("%s: Error erasing at 0x%lx\n",
__FUNCTION__, (long)ofs);
/* There was an error */
ret = -1;
goto out;
}
if (clean) {
int n; /* return value not used */
int p, l;
/* clean marker position and size depend
* on the page size, since 256 byte pages
* only have 8 bytes of oob data
*/
if (nand->page256) {
p = NAND_JFFS2_OOB8_FSDAPOS;
l = NAND_JFFS2_OOB8_FSDALEN;
}
else {
p = NAND_JFFS2_OOB16_FSDAPOS;
l = NAND_JFFS2_OOB16_FSDALEN;
}
ret = nand_write_oob(nand, ofs + p, l, &n,
(u_char *)&clean_marker);
/* quit here if write failed */
if (ret)
goto out;
}
}
ofs += nand->erasesize;
len -= nand->erasesize;
@ -1346,7 +1346,6 @@ void nand_probe(unsigned long physadr)
oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3;
oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4;
oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5;
oob_config.badblock_pos = 5;
oob_config.eccvalid_pos = 4;
#else
oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0;
@ -1355,9 +1354,9 @@ void nand_probe(unsigned long physadr)
oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3;
oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4;
oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5;
oob_config.badblock_pos = NAND_NOOB_BADBPOS;
oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS;
#endif
oob_config.badblock_pos = 5;
for (i=0; i<CFG_MAX_NAND_DEVICE; i++) {
if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) {
@ -1366,15 +1365,23 @@ void nand_probe(unsigned long physadr)
}
}
memset((char *)nand, 0, sizeof(struct nand_chip));
nand->IO_ADDR = physadr;
nand->cache_page = -1; /* init the cache page */
NanD_ScanChips(nand);
if (nand->totlen == 0) {
/* no chips found, clean up and quit */
memset((char *)nand, 0, sizeof(struct nand_chip));
nand->ChipID = NAND_ChipID_UNKNOWN;
return;
}
nand->ChipID = ChipID;
if (curr_device == -1)
curr_device = i;
memset((char *)nand, 0, sizeof(struct nand_chip));
nand->cache_page = -1; /* init the cache page */
nand->IO_ADDR = physadr;
nand->ChipID = ChipID;
NanD_ScanChips(nand);
nand->data_buf = malloc (nand->oobblock + nand->oobsize);
if (!nand->data_buf) {
puts ("Cannot allocate memory for data structures.\n");
@ -1451,11 +1458,11 @@ static void nand_trans_result(u_char reg2, u_char reg3,
*/
static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
{
u_char idx, reg1, reg2, reg3;
u_char idx, reg1, reg3;
int j;
/* Initialize variables */
reg1 = reg2 = reg3 = 0;
reg1 = reg3 = 0;
ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
/* Build up column parity */
@ -1463,17 +1470,16 @@ static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
/* Get CP0 - CP5 from table */
idx = nand_ecc_precalc_table[dat[j]];
reg1 ^= (idx & 0x3f);
reg1 ^= idx;
/* All bit XOR = 1 ? */
if (idx & 0x40) {
reg3 ^= (u_char) j;
reg2 ^= ~((u_char) j);
}
}
/* Create non-inverted ECC code from line parity */
nand_trans_result(reg2, reg3, ecc_code);
nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code);
/* Calculate final ECC code */
ecc_code[0] = ~ecc_code[0];

157
common/cmd_portio.c Normal file
View file

@ -0,0 +1,157 @@
/*
* (C) Copyright 2003
* Marc Singer, elf@buici.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Port I/O Functions
*
* Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
*/
#include <common.h>
#include <command.h>
#include <cmd_portio.h>
#if (CONFIG_COMMANDS & CFG_CMD_PORTIO)
extern int cmd_get_data_size (char *arg, int default_size);
/* Display values from last command.
* Memory modify remembered values are different from display memory.
*/
static uint in_last_addr, in_last_size;
static uint out_last_addr, out_last_size, out_last_value;
int do_portio_out (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
uint addr = out_last_addr;
uint size = out_last_size;
uint value = out_last_value;
if (argc != 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* New command specified. Check for a size specification.
* Defaults to long if no or incorrect specification.
*/
size = cmd_get_data_size (argv[0], 1);
addr = simple_strtoul (argv[1], NULL, 16);
value = simple_strtoul (argv[2], NULL, 16);
}
#if defined (CONFIG_X86)
{
unsigned short port = addr;
switch (size) {
default:
case 1:
{
unsigned char ch = value;
__asm__ volatile ("out %0, %%dx"::"a" (ch), "d" (port));
}
break;
case 2:
{
unsigned short w = value;
__asm__ volatile ("out %0, %%dx"::"a" (w), "d" (port));
}
break;
case 4:
__asm__ volatile ("out %0, %%dx"::"a" (value), "d" (port));
break;
}
}
#endif /* CONFIG_X86 */
out_last_addr = addr;
out_last_size = size;
out_last_value = value;
return 0;
}
int do_portio_in (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
uint addr = in_last_addr;
uint size = in_last_size;
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* New command specified. Check for a size specification.
* Defaults to long if no or incorrect specification.
*/
size = cmd_get_data_size (argv[0], 1);
addr = simple_strtoul (argv[1], NULL, 16);
}
#if defined (CONFIG_X86)
{
unsigned short port = addr;
switch (size) {
default:
case 1:
{
unsigned char ch;
__asm__ volatile ("in %%dx, %0":"=a" (ch):"d" (port));
printf (" %02x\n", ch);
}
break;
case 2:
{
unsigned short w;
__asm__ volatile ("in %%dx, %0":"=a" (w):"d" (port));
printf (" %04x\n", w);
}
break;
case 4:
{
unsigned long l;
__asm__ volatile ("in %%dx, %0":"=a" (l):"d" (port));
printf (" %08lx\n", l);
}
break;
}
}
#endif /* CONFIG_X86 */
in_last_addr = addr;
in_last_size = size;
return 0;
}
#endif /* CFG_CMD_PORTIO */

View file

@ -73,6 +73,7 @@
#include <cmd_log.h>
#include <cmd_fdos.h>
#include <cmd_bmp.h>
#include <cmd_portio.h>
#ifdef CONFIG_AMIGAONEG3SE
#include <cmd_menu.h>
@ -284,6 +285,7 @@ cmd_tbl_t cmd_tbl[] = {
CMD_TBL_IMM
CMD_TBL_INM
CMD_TBL_IMW
CMD_TBL_PORTIO_IN
CMD_TBL_ICRC
CMD_TBL_IPROBE
CMD_TBL_ILOOP
@ -314,6 +316,7 @@ cmd_tbl_t cmd_tbl[] = {
CMD_TBL_NANDBOOT
CMD_TBL_NEXT
CMD_TBL_NM
CMD_TBL_PORTIO_OUT
CMD_TBL_PCI
CMD_TBL_PRINTENV
CMD_TBL_PROTECT

View file

@ -26,17 +26,18 @@ include $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o start16.o reset.o
OBJS = serial.o interrupts.o cpu.o timer.o
COBJS = serial.o interrupts.o cpu.o timer.o sc520.o
AOBJS = sc520_asm.o
all: .depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) crv $@ $(OBJS)
$(LIB): $(COBJS) $(AOBJS)
$(AR) crv $@ $(COBJS) $(AOBJS)
#########################################################################
.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
.depend: Makefile $(START:.o=.S) $(COBJS:.o=.c) $(AOBJS:.o=.S)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(COBJS:.o=.c) $(AOBJS:.o=.S) > $@
sinclude .depend

View file

@ -21,6 +21,6 @@
# MA 02111-1307 USA
#
PLATFORM_RELFLAGS += # -pipe -mpreferred-stack-boundary=2 -fno-builtin -nostdinc -nostdlib
PLATFORM_RELFLAGS +=
PLATFORM_CPPFLAGS += -march=i386
PLATFORM_CPPFLAGS += -march=i386 -Werror

View file

@ -38,6 +38,13 @@
int cpu_init(void)
{
/* initialize FPU, reset EM, set MP and NE */
asm ("fninit\n" \
"movl %cr0, %eax\n" \
"andl $~0x4, %eax\n" \
"orl $0x22, %eax\n" \
"movl %eax, %cr0\n" );
return 0;
}

View file

@ -29,22 +29,6 @@
#include <asm/ibmpc.h>
#if 0
/* done */
int interrupt_init (void);
void irq_install_handler(int, interrupt_handler_t *, void *);
void irq_free_handler (int);
void enable_interrupts (void);
int disable_interrupts (void);
/* todo */
void timer_interrupt (struct pt_regs *);
void external_interrupt (struct pt_regs *);
void reset_timer (void);
ulong get_timer (ulong base);
void set_timer (ulong t);
#endif
struct idt_entry {
u16 base_low;
@ -76,43 +60,30 @@ typedef struct {
static irq_desc_t irq_table[MAX_IRQ];
/* syscall stuff, very untested
* the current approach which includes copying
* part of the stack will work badly for
* varargs functions.
* if we were to store the top three words on the
* stack (eip, ss, eflags) somwhere and add 14 to
* %esp ....
*/
asm(".globl syscall_entry\n" \
"syscall_entry:\n" \
"movl 12(%esp), %eax\n" \
"movl %esp, %ebx\n" \
"addl $16, %ebx\n" \
"pushl %ebx\n" \
"pushl %eax\n" \
"call do_syscall\n" \
"addl $8, %esp\n" \
"iret\n");
"popl %ebx\n" /* throw away the return address, flags */ \
"popl %ebx\n" /* and segment that the INT instruction pushed */ \
"popl %ebx\n" /* on to the stack */ \
"movl %eax, %ecx\n" /* load the syscall nr argument*/ \
"movl syscall_tbl, %eax\n" /* load start of syscall table */ \
"cmpl $(11-1), %ecx\n" /* FixMe: find a way to use NR_SYSCALLS macro here */ \
"ja bad_syscall\n" \
"movl (%eax, %ecx, 4), %eax\n" /* load the handler of the syscall*/ \
"test %eax, %eax\n" /* test for null */ \
"je bad_syscall\n" \
"popl %ecx\n" \
"popl %ebx\n" \
"sti \n" \
"jmp *%eax\n" \
"bad_syscall: movl $0xffffffff, %eax\n" \
"popl %ecx\n" \
"popl %ebx\n" \
"ret");
void __attribute__ ((regparm(0))) syscall_entry(void);
int __attribute__ ((regparm(0))) do_syscall(u32 nr, u32 *stack)
{
if (nr<NR_SYSCALLS) {
/* We copy 8 args of the syscall,
* this will be a problem with the
* printf syscall .... */
int (*fp)(u32, u32, u32, u32,
u32, u32, u32, u32);
fp = syscall_tbl[nr];
return fp(stack[0], stack[1], stack[2], stack[3],
stack[4], stack[5], stack[6], stack[7]);
}
return -1;
}
asm ("irq_return:\n"
" addl $4, %esp\n"

View file

@ -24,10 +24,14 @@
/* stuff specific for the sc520,
* but idependent of implementation */
#include <config.h>
#ifdef CONFIG_SC520
#include <common.h>
#include <config.h>
#include <pci.h>
#include <ssi.h>
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/ic/sc520.h>
@ -235,6 +239,91 @@ unsigned long init_sc520_dram(void)
#ifdef CONFIG_PCI
static struct {
u8 priority;
u16 level_reg;
u8 level_bit;
} sc520_irq[] = {
{ SC520_IRQ0, SC520_MPICMODE, 0x01 },
{ SC520_IRQ1, SC520_MPICMODE, 0x02 },
{ SC520_IRQ2, SC520_SL1PICMODE, 0x02 },
{ SC520_IRQ3, SC520_MPICMODE, 0x08 },
{ SC520_IRQ4, SC520_MPICMODE, 0x10 },
{ SC520_IRQ5, SC520_MPICMODE, 0x20 },
{ SC520_IRQ6, SC520_MPICMODE, 0x40 },
{ SC520_IRQ7, SC520_MPICMODE, 0x80 },
{ SC520_IRQ8, SC520_SL1PICMODE, 0x01 },
{ SC520_IRQ9, SC520_SL1PICMODE, 0x02 },
{ SC520_IRQ10, SC520_SL1PICMODE, 0x04 },
{ SC520_IRQ11, SC520_SL1PICMODE, 0x08 },
{ SC520_IRQ12, SC520_SL1PICMODE, 0x10 },
{ SC520_IRQ13, SC520_SL1PICMODE, 0x20 },
{ SC520_IRQ14, SC520_SL1PICMODE, 0x40 },
{ SC520_IRQ15, SC520_SL1PICMODE, 0x80 }
};
/* The interrupt used for PCI INTA-INTD */
int sc520_pci_ints[15] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1
};
/* utility function to configure a pci interrupt */
int pci_sc520_set_irq(int pci_pin, int irq)
{
int i;
# if 0
printf("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq);
#endif
if (irq < 0 || irq > 15) {
return -1; /* illegal irq */
}
if (pci_pin < 0 || pci_pin > 15) {
return -1; /* illegal pci int pin */
}
/* first disable any non-pci interrupt source that use
* this level */
for (i=SC520_GPTMR0MAP;i<=SC520_GP10IMAP;i++) {
if (i>=SC520_PCIINTAMAP&&i<=SC520_PCIINTDMAP) {
continue;
}
if (read_mmcr_byte(i) == sc520_irq[irq].priority) {
write_mmcr_byte(i, SC520_IRQ_DISABLED);
}
}
/* Set the trigger to level */
write_mmcr_byte(sc520_irq[irq].level_reg,
read_mmcr_byte(sc520_irq[irq].level_reg) | sc520_irq[irq].level_bit);
if (pci_pin < 4) {
/* PCI INTA-INTD */
/* route the interrupt */
write_mmcr_byte(SC520_PCIINTAMAP + pci_pin, sc520_irq[irq].priority);
} else {
/* GPIRQ0-GPIRQ10 used for additional PCI INTS */
write_mmcr_byte(SC520_GP0IMAP + pci_pin - 4, sc520_irq[irq].priority);
/* also set the polarity in this case */
write_mmcr_word(SC520_INTPINPOL,
read_mmcr_word(SC520_INTPINPOL) | (1 << (pci_pin-4)));
}
/* register the pin */
sc520_pci_ints[pci_pin] = irq;
return 0; /* OK */
}
void pci_sc520_init(struct pci_controller *hose)
{
@ -293,6 +382,7 @@ void pci_sc520_init(struct pci_controller *hose)
}
#endif
#ifdef CFG_TIMER_SC520
@ -345,4 +435,68 @@ void udelay(unsigned long usec)
#endif
int ssi_set_interface(int freq, int lsb_first, int inv_clock, int inv_phase)
{
u8 temp=0;
if (freq >= 8192) {
temp |= CTL_CLK_SEL_4;
} else if (freq >= 4096) {
temp |= CTL_CLK_SEL_8;
} else if (freq >= 2048) {
temp |= CTL_CLK_SEL_16;
} else if (freq >= 1024) {
temp |= CTL_CLK_SEL_32;
} else if (freq >= 512) {
temp |= CTL_CLK_SEL_64;
} else if (freq >= 256) {
temp |= CTL_CLK_SEL_128;
} else if (freq >= 128) {
temp |= CTL_CLK_SEL_256;
} else {
temp |= CTL_CLK_SEL_512;
}
if (!lsb_first) {
temp |= MSBF_ENB;
}
if (inv_clock) {
temp |= CLK_INV_ENB;
}
if (inv_phase) {
temp |= PHS_INV_ENB;
}
write_mmcr_byte(SC520_SSICTL, temp);
return 0;
}
u8 ssi_txrx_byte(u8 data)
{
write_mmcr_byte(SC520_SSIXMIT, data);
while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMITRCV);
while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
return read_mmcr_byte(SC520_SSIRCV);
}
void ssi_tx_byte(u8 data)
{
write_mmcr_byte(SC520_SSIXMIT, data);
while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMIT);
}
u8 ssi_rx_byte(void)
{
while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_RCV);
while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);
return read_mmcr_byte(SC520_SSIRCV);
}
#endif /* CONFIG_SC520 */

View file

@ -104,6 +104,9 @@
*******************************************************************************
*/
#include <config.h>
#ifdef CONFIG_SC520
.section .text
.equ DRCCTL, 0x0fffef010 /* DRAM control register */
.equ DRCTMCTL, 0x0fffef012 /* DRAM timing control register */
@ -140,34 +143,34 @@
mem_init:
xorw %ax,%ax
movl $DBCTL, %edi
fs movb %al, (%edi) /* disable write buffer */
movb %al, (%edi) /* disable write buffer */
movl $ECCCTL, %edi
fs movb %al, (%edi) /* disable ECC */
movb %al, (%edi) /* disable ECC */
movl $DRCTMCTL, %edi
movb $0x1E,%al /* Set SDRAM timing for slowest */
fs movb %al, (%edi)
movb %al, (%edi)
/*
* setup loop to do 4 external banks starting with bank 3
*/
movl $0xff000000,%eax /* enable last bank and setup */
movl $DRCBENDADR, %edi /* ending address register */
fs movl %eax, (%edi)
movl %eax, (%edi)
movl $DRCCFG, %edi /* setup */
movw $0xbbbb,%ax /* dram config register for */
fs movw %ax, (%edi)
movw %ax, (%edi)
/*
* issue a NOP to all DRAMs
*/
movl $DRCCTL, %edi /* setup DRAM control register with */
movb $0x1,%al /* Disable refresh,disable write buffer */
fs movb %al, (%edi)
movb %al, (%edi)
movl $CACHELINESZ, %esi /* just a dummy address to write for */
fs movw %ax, (%esi)
movw %ax, (%esi)
/*
* delay for 100 usec? 200?
* ******this is a cludge for now *************
@ -181,41 +184,41 @@ sizdelay:
* issue all banks precharge
*/
movb $0x2,%al /* All banks precharge */
fs movb %al, (%edi)
fs movw %ax, (%esi)
movb %al, (%edi)
movw %ax, (%esi)
/*
* issue 2 auto refreshes to all banks
*/
movb $0x4,%al /* Auto refresh cmd */
fs movb %al, (%edi)
movb %al, (%edi)
movw $2,%cx
refresh1:
fs movw %ax, (%esi)
movw %ax, (%esi)
loop refresh1
/*
* issue LOAD MODE REGISTER command
*/
movb $0x3,%al /* Load mode register cmd */
fs movb %al, (%edi)
fs movw %ax, (%esi)
movb %al, (%edi)
movw %ax, (%esi)
/*
* issue 8 more auto refreshes to all banks
*/
movb $0x4,%al /* Auto refresh cmd */
fs movb %al, (%edi)
movb %al, (%edi)
movw $8,%cx
refresh2:
fs movw %ax, (%esi)
movw %ax, (%esi)
loop refresh2
/*
* set control register to NORMAL mode
*/
movb $0x0,%al /* Normal mode value */
fs movb %al, (%edi)
movb %al, (%edi)
/*
* size dram starting with external bank 3 moving to external bank 0
@ -229,8 +232,8 @@ nextbank:
*/
movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
movl $COL11_DATA, %eax /* pattern for max supported columns(11) */
fs movl %eax, (%esi) /* write max col pattern at max col adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write max col pattern at max col adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -239,8 +242,8 @@ fs movl (%esi), %ebx /* optional read */
movl $COL10_ADR, %esi /* set address to 10 col wrap address */
movl $COL10_DATA, %eax /* pattern for 10 col wrap */
fs movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -248,8 +251,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $COL09_ADR, %esi /* set address to 9 col wrap address */
movl $COL09_DATA, %eax /* pattern for 9 col wrap */
fs movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -257,8 +260,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $COL08_ADR, %esi /* set address to min(8) col wrap address */
movl $COL08_DATA, %eax /* pattern for min (8) col wrap */
fs movl %eax, (%esi) /* write min col pattern @ min col adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write min col pattern @ min col adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -266,8 +269,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */
movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */
fs movl %eax, (%esi) /* write max row pattern at max row adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write max row pattern at max row adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -275,8 +278,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $ROW13_ADR, %esi /* set address to 13 row wrap address */
movl $ROW13_DATA, %eax /* pattern for 13 row wrap */
fs movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -284,8 +287,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $ROW12_ADR, %esi /* set address to 12 row wrap address */
movl $ROW12_DATA, %eax /* pattern for 12 row wrap */
fs movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */
fs movl (%esi), %ebx /* optional read */
movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */
movl (%esi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -293,8 +296,8 @@ fs movl (%esi), %ebx /* optional read */
*/
movl $ROW11_ADR, %edi /* set address to 11 row wrap address */
movl $ROW11_DATA, %eax /* pattern for 11 row wrap */
fs movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */
fs movl (%edi), %ebx /* optional read */
movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */
movl (%edi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -302,8 +305,8 @@ fs movl (%edi), %ebx /* optional read */
*/
movl $ROW10_ADR, %edi /* set address to 10 row wrap address */
movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */
fs movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */
fs movl (%edi), %ebx /* optional read */
movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */
movl (%edi), %ebx /* optional read */
cmpl %ebx,%eax /* to verify write */
jnz bad_ram /* this ram is bad */
/*
@ -314,7 +317,7 @@ fs movl (%edi), %ebx /* optional read */
* if data @ row 12 wrap == 11 or 12, we have 4 banks,
*/
xorw %di,%di /* value for 2 banks in DI */
fs movl (%esi), %ebx /* read from 12 row wrap to check banks
movl (%esi), %ebx /* read from 12 row wrap to check banks
* (esi is setup from the write to row 12 wrap) */
cmpl %ebx,%eax /* check for AA pattern (eax holds the aa pattern) */
jz only2 /* if pattern == AA, we only have 2 banks */
@ -333,7 +336,7 @@ only2:
* validate row mask
*/
movl $ROW14_ADR, %esi /* set address back to max row wrap addr */
fs movl (%esi), %eax /* read actual number of rows @ row14 adr */
movl (%esi), %eax /* read actual number of rows @ row14 adr */
cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */
jb bad_ram
@ -351,7 +354,7 @@ fs movl (%esi), %eax /* read actual number of rows @ row14 a
* read col 11 wrap adr for real column data value
*/
movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
fs movl (%esi), %eax /* read real col number at max col adr */
movl (%esi), %eax /* read real col number at max col adr */
/*
* validate column data
*/
@ -389,9 +392,9 @@ fs movl (%esi), %eax /* read real col number at max col adr
bad_reint:
movl $DRCCTL, %esi /* setup DRAM control register with */
movb $0x2,%al /* All banks precharge */
fs movb %al, (%esi)
movb %al, (%esi)
movl $CACHELINESZ, %esi /* address to init read buffer */
fs movw %ax, (%esi)
movw %ax, (%esi)
/*
* update ENDING ADDRESS REGISTER
@ -399,7 +402,7 @@ fs movw %ax, (%esi)
movl $DRCBENDADR, %edi /* DRAM ending address register */
movl %ecx,%ebx
addl %ebx, %edi
fs movb %dh, (%edi)
movb %dh, (%edi)
/*
* update CONFIG REGISTER
*/
@ -413,10 +416,10 @@ fs movb %dh, (%edi)
notw %bx
xchgw %cx,%ax
movl $DRCCFG, %edi
fs mov (%edi), %ax
mov (%edi), %ax
andw %bx,%ax
orw %dx,%ax
fs movw %ax, (%edi)
movw %ax, (%edi)
jcxz cleanup
decw %cx
@ -424,15 +427,15 @@ fs movw %ax, (%edi)
movl $DRCBENDADR, %edi /* DRAM ending address register */
movb $0xff,%al
addl %ebx, %edi
fs movb %al, (%edi)
movb %al, (%edi)
/*
* set control register to NORMAL mode
*/
movl $DRCCTL, %esi /* setup DRAM control register with */
movb $0x0,%al /* Normal mode value */
fs movb %al, (%esi)
movb %al, (%esi)
movl $CACHELINESZ, %esi /* address to init read buffer */
fs movw %ax, (%esi)
movw %ax, (%esi)
jmp nextbank
cleanup:
@ -440,7 +443,7 @@ cleanup:
movw $4,%cx
xorw %ax,%ax
cleanuplp:
fs movb (%edi), %al
movb (%edi), %al
orb %al,%al
jz emptybank
@ -451,7 +454,7 @@ fs movb (%edi), %al
nottoomuch:
movb %al,%ah
orb $0x80,%al
fs movb %al, (%edi)
movb %al, (%edi)
emptybank:
incl %edi
loop cleanuplp
@ -471,13 +474,13 @@ emptybank:
#endif
movl $DRCCTL, %edi /* DRAM Control register */
movb $0x3,%al /* Load mode register cmd */
fs movb %al, (%edi)
fs movw %ax, (%esi)
movb %al, (%edi)
movw %ax, (%esi)
movl $DRCCTL, %edi /* DRAM Control register */
movb $0x18,%al /* Enable refresh and NORMAL mode */
fs movb %al, (%edi)
movb %al, (%edi)
jmp dram_done
@ -528,3 +531,6 @@ bank0: movl (%edi), %eax
done: movl %ebx, %eax
jmp *%ebp
#endif /* CONFIG_SC520 */

View file

@ -24,6 +24,7 @@
* MA 02111-1307 USA
*/
/*------------------------------------------------------------------------------+ */
/*
* This source code has been made available to you by IBM on an AS-IS
* basis. Anyone receiving this source is licensed under IBM
@ -89,13 +90,15 @@ typedef struct {
char *rx_buffer;
ulong rx_put;
ulong rx_get;
int cts;
} serial_buffer_t;
volatile static serial_buffer_t buf_info;
volatile serial_buffer_t buf_info;
static int serial_buffer_active=0;
#endif
static int serial_div (int baudrate )
static int serial_div(int baudrate)
{
switch (baudrate) {
@ -112,7 +115,8 @@ static int serial_div (int baudrate )
case 115200:
return 1;
}
hang ();
return 12;
}
@ -121,7 +125,7 @@ static int serial_div (int baudrate )
* as serial console interface.
*/
int serial_init (void)
int serial_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
@ -134,24 +138,24 @@ int serial_init (void)
outb(bdiv, UART0_BASE + UART_DLL); /* set baudrate divisor */
outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
outb(0x03, UART0_BASE + UART_LCR); /* clear DLAB; set 8 bits, no parity */
outb(0x00, UART0_BASE + UART_FCR); /* disable FIFO */
outb(0x00, UART0_BASE + UART_MCR); /* no modem control DTR RTS */
outb(0x01, UART0_BASE + UART_FCR); /* enable FIFO */
outb(0x0b, UART0_BASE + UART_MCR); /* Set DTR and RTS active */
val = inb(UART0_BASE + UART_LSR); /* clear line status */
val = inb(UART0_BASE + UART_RBR); /* read receive buffer */
outb(0x00, UART0_BASE + UART_SCR); /* set scratchpad */
outb(0x00, UART0_BASE + UART_IER); /* set interrupt enable reg */
return (0);
return 0;
}
void serial_setbrg (void)
void serial_setbrg(void)
{
DECLARE_GLOBAL_DATA_PTR;
unsigned short bdiv;
bdiv = serial_div (gd->baudrate);
bdiv = serial_div(gd->baudrate);
outb(0x80, UART0_BASE + UART_LCR); /* set DLAB bit */
outb(bdiv&0xff, UART0_BASE + UART_DLL); /* set baudrate divisor */
@ -160,7 +164,7 @@ void serial_setbrg (void)
}
void serial_putc (const char c)
void serial_putc(const char c)
{
int i;
@ -169,31 +173,38 @@ void serial_putc (const char c)
/* check THRE bit, wait for transmiter available */
for (i = 1; i < 3500; i++) {
if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20)
if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) {
break;
udelay (100);
}
udelay(100);
}
outb(c, UART0_BASE + UART_THR); /* put character out */
}
void serial_puts (const char *s)
void serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
serial_putc(*s++);
}
}
int serial_getc ()
int serial_getc(void)
{
unsigned char status = 0;
#if CONFIG_SERIAL_SOFTWARE_FIFO
if (serial_buffer_active) {
return serial_buffered_getc();
}
#endif
while (1) {
#if defined(CONFIG_HW_WATCHDOG)
WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
WATCHDOG_RESET(); /* Reset HW Watchdog, if needed */
#endif /* CONFIG_HW_WATCHDOG */
status = inb (UART0_BASE + UART_LSR);
status = inb(UART0_BASE + UART_LSR);
if ((status & asyncLSRDataReady1) != 0x0) {
break;
}
@ -211,11 +222,17 @@ int serial_getc ()
}
int serial_tstc ()
int serial_tstc(void)
{
unsigned char status;
status = inb (UART0_BASE + UART_LSR);
#if CONFIG_SERIAL_SOFTWARE_FIFO
if (serial_buffer_active) {
return serial_buffered_tstc();
}
#endif
status = inb(UART0_BASE + UART_LSR);
if ((status & asyncLSRDataReady1) != 0x0) {
return (1);
}
@ -234,36 +251,50 @@ int serial_tstc ()
#if CONFIG_SERIAL_SOFTWARE_FIFO
void serial_isr (void *arg)
void serial_isr(void *arg)
{
int space;
int c;
const int rx_get = buf_info.rx_get;
int rx_put = buf_info.rx_put;
if (rx_get <= rx_put) {
space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
if (buf_info.rx_get <= rx_put) {
space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - buf_info.rx_get);
} else {
space = rx_get - rx_put;
space = buf_info.rx_get - rx_put;
}
while (serial_tstc ()) {
c = serial_getc ();
while (inb(UART0_BASE + UART_LSR) & 1) {
c = inb(UART0_BASE);
if (space) {
buf_info.rx_buffer[rx_put++] = c;
space--;
if (rx_put == buf_info.rx_get) {
buf_info.rx_get++;
if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
buf_info.rx_get = 0;
}
}
if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
rx_put = 0;
if (0 == buf_info.rx_get) {
buf_info.rx_get = 1;
}
}
}
if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
rx_put = 0;
if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
/* Stop flow by setting RTS inactive */
outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
outb(inb(UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
UART0_BASE + UART_MCR);
}
}
buf_info.rx_put = rx_put;
}
void serial_buffered_init (void)
void serial_buffered_init(void)
{
serial_puts ("Switching to interrupt driven serial input mode.\n");
buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
@ -272,8 +303,10 @@ void serial_buffered_init (void)
if (inb (UART0_BASE + UART_MSR) & 0x10) {
serial_puts ("Check CTS signal present on serial port: OK.\n");
buf_info.cts = 1;
} else {
serial_puts ("WARNING: CTS signal not present on serial port.\n");
buf_info.cts = 0;
}
irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ ,
@ -283,32 +316,49 @@ void serial_buffered_init (void)
/* Enable "RX Data Available" Interrupt on UART */
/* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */
outb(0x01, UART0_BASE + UART_IER);
/* Set DTR active */
outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR);
/* Start flow by setting RTS active */
outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
/* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
outb((1 << 6) | 1, UART0_BASE + UART_FCR);
/* Set DTR and RTS active, enable interrupts */
outb(inb (UART0_BASE + UART_MCR) | 0x0b, UART0_BASE + UART_MCR);
/* Setup UART FIFO: RX trigger level: 1 byte, Enable FIFO */
outb( /*(1 << 6) |*/ 1, UART0_BASE + UART_FCR);
serial_buffer_active = 1;
}
void serial_buffered_putc (const char c)
{
int i;
/* Wait for CTS */
#if defined(CONFIG_HW_WATCHDOG)
while (!(inb (UART0_BASE + UART_MSR) & 0x10))
WATCHDOG_RESET ();
#else
while (!(inb (UART0_BASE + UART_MSR) & 0x10));
if (buf_info.cts) {
for (i=0;i<1000;i++) {
if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
break;
}
}
if (i!=1000) {
buf_info.cts = 0;
}
} else {
if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
buf_info.cts = 1;
}
}
#endif
serial_putc (c);
}
void serial_buffered_puts (const char *s)
void serial_buffered_puts(const char *s)
{
serial_puts (s);
}
int serial_buffered_getc (void)
int serial_buffered_getc(void)
{
int space;
int c;
@ -322,8 +372,9 @@ int serial_buffered_getc (void)
while (rx_get == buf_info.rx_put);
#endif
c = buf_info.rx_buffer[rx_get++];
if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) {
rx_get = 0;
}
buf_info.rx_get = rx_get;
rx_put = buf_info.rx_put;
@ -340,7 +391,7 @@ int serial_buffered_getc (void)
return c;
}
int serial_buffered_tstc (void)
int serial_buffered_tstc(void)
{
return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
}
@ -358,7 +409,7 @@ int serial_buffered_tstc (void)
configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
*/
#if (CONFIG_KGDB_SER_INDEX & 2)
void kgdb_serial_init (void)
void kgdb_serial_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
@ -381,7 +432,7 @@ void kgdb_serial_init (void)
}
void putDebugChar (const char c)
void putDebugChar(const char c)
{
if (c == '\n')
serial_putc ('\r');
@ -393,7 +444,7 @@ void putDebugChar (const char c)
}
void putDebugStr (const char *s)
void putDebugStr(const char *s)
{
while (*s) {
serial_putc(*s++);
@ -401,7 +452,7 @@ void putDebugStr (const char *s)
}
int getDebugChar (void)
int getDebugChar(void)
{
unsigned char status = 0;
@ -424,34 +475,34 @@ int getDebugChar (void)
}
void kgdb_interruptible (int yes)
void kgdb_interruptible(int yes)
{
return;
}
#else /* ! (CONFIG_KGDB_SER_INDEX & 2) */
void kgdb_serial_init (void)
void kgdb_serial_init(void)
{
serial_printf ("[on serial] ");
}
void putDebugChar (int c)
void putDebugChar(int c)
{
serial_putc (c);
}
void putDebugStr (const char *str)
void putDebugStr(const char *str)
{
serial_puts (str);
}
int getDebugChar (void)
int getDebugChar(void)
{
return serial_getc ();
}
void kgdb_interruptible (int yes)
void kgdb_interruptible(int yes)
{
return;
}

View file

@ -1,7 +1,7 @@
/*
* U-boot - i386 Startup Code
*
* Copyright (c) 2002 Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
* Copyright (c) 2002, 2003 Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
*
* See file CREDITS for list of people who contributed to this
* project.
@ -40,7 +40,7 @@ board_init16_ret:
/* Turn of cache (this might require a 486-class CPU) */
movl %cr0, %eax
orl $060000000,%eax
orl $0x60000000,%eax
movl %eax, %cr0
wbinvd

View file

@ -543,7 +543,7 @@ relocate_code:
mr r10, r5 /* Save copy of Destination Address */
mr r3, r5 /* Destination Address */
#ifdef DEBUG
#ifdef CFG_RAMBOOT
lis r4, CFG_SDRAM_BASE@h /* Source Address */
ori r4, r4, CFG_SDRAM_BASE@l
#else

View file

@ -353,6 +353,12 @@ void pci_mpc8250_init(struct pci_controller *hose)
pci_hose_write_config_word(hose, host_devno, PCI_COMMAND,
tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
#ifdef CONFIG_MPC8266ADS
/* do some bridge init, should be done on all 8260 based bridges */
pci_hose_write_config_byte(hose, host_devno, PCI_CACHE_LINE_SIZE, 0x08);
pci_hose_write_config_byte(hose, host_devno, PCI_LATENCY_TIMER, 0xF8);
#endif
hose->first_busno = 0;
hose->last_busno = 0xff;
@ -373,11 +379,11 @@ void pci_mpc8250_init(struct pci_controller *hose)
/* PCI memory space */
#ifdef CONFIG_MPC8266ADS
pci_set_region(hose->regions + 0,
PCI_SLV_MEM_BUS,
PCI_SLV_MEM_LOCAL,
gd->ram_size,
PCI_REGION_MEM | PCI_REGION_MEMORY);
pci_set_region(hose->regions + 1,
PCI_MSTR_MEMIO_BUS,
PCI_MSTR_MEMIO_LOCAL,
PCI_MSTR_MEMIO_SIZE,
PCI_REGION_MEM);
#else
pci_set_region(hose->regions + 1,
PCI_MSTR_MEM_BUS,

View file

@ -69,6 +69,8 @@ mm 2
mtest 5
muxinfo 3
mw 2
nand 3
nboot 4
next 4
nm 2
pciinfo 3

176
doc/README.nand Normal file
View file

@ -0,0 +1,176 @@
NAND FLASH commands and notes
# (C) Copyright 2003
# Dave Ellis, SIXNET, dge@sixnetio.com
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
Commands:
nand bad
Print a list of all of the bad blocks in the current device.
nand device
Print information about the current NAND device.
nand device num
Make device `num' the current device and print information about it.
nand erase off size
nand erase clean [off size]
Erase `size' bytes starting at offset `off'. Only complete erase
blocks can be erased.
If `clean' is specified, a JFFS2-style clean marker is written to
each block after it is erased. If `clean' is specified without an
offset or size, the entire flash is erased.
This command will not erase blocks that are marked bad. There is
a debug option in cmd_nand.c to allow bad blocks to be erased.
Please read the warning there before using it, as blocks marked
bad by the manufacturer must _NEVER_ be erased.
nand info
Print information about all of the NAND devices found.
nand read addr ofs size
Read `size' bytes from `ofs' in NAND flash to `addr'. If a page
cannot be read because it is marked bad or an uncorrectable data
error is found the command stops with an error.
nand read.jffs2 addr ofs size
Like `read', but the data for blocks that are marked bad is read as
0xff. This gives a readable JFFS2 image that can be processed by
the JFFS2 commands such as ls and fsload.
nand read.oob addr ofs size
Read `size' bytes from the out-of-band data area corresponding to
`ofs' in NAND flash to `addr'. This is limited to the 16 bytes of
data for one 512-byte page or 2 256-byte pages. There is no check
for bad blocks or ECC errors.
nand write addr ofs size
Write `size' bytes from `addr' to `ofs' in NAND flash. If a page
cannot be written because it is marked bad or the write fails the
command stops with an error.
nand write.jffs2 addr ofs size
Like `write', but blocks that are marked bad are skipped and the
is written to the next block instead. This allows writing writing
a JFFS2 image, as long as the image is short enough to fit even
after skipping the bad blocks. Compact images, such as those
produced by mkfs.jffs2 should work well, but loading an image copied
from another flash is going to be trouble if there are any bad blocks.
nand write.oob addr ofs size
Write `size' bytes from `addr' to the out-of-band data area
corresponding to `ofs' in NAND flash. This is limited to the 16 bytes
of data for one 512-byte page or 2 256-byte pages. There is no check
for bad blocks.
Configuration Options:
CFG_CMD_NAND
A good one to add to CONFIG_COMMANDS since it enables NAND support.
CONFIG_MTD_NAND_ECC_JFFS2
Define this if you want the Error Correction Code information in
the out-of-band data to be formatted to match the JFFS2 file system.
CONFIG_MTD_NAND_ECC_YAFFS would be another useful choice for
someone to implement.
CFG_MAX_NAND_DEVICE
The maximum number of NAND devices you want to support.
NAND Interface:
#define NAND_WAIT_READY(nand)
Wait until the NAND flash is ready. Typically this would be a
loop waiting for the READY/BUSY line from the flash to indicate it
it is ready.
#define WRITE_NAND_COMMAND(d, adr)
Write the command byte `d' to the flash at `adr' with the
CLE (command latch enable) line true. If your board uses writes to
different addresses to control CLE and ALE, you can modify `adr'
to be the appropriate address here. If your board uses I/O registers
to control them, it is probably better to let NAND_CTL_SETCLE()
and company do it.
#define WRITE_NAND_ADDRESS(d, adr)
Write the address byte `d' to the flash at `adr' with the
ALE (address latch enable) line true. If your board uses writes to
different addresses to control CLE and ALE, you can modify `adr'
to be the appropriate address here. If your board uses I/O registers
to control them, it is probably better to let NAND_CTL_SETALE()
and company do it.
#define WRITE_NAND(d, adr)
Write the data byte `d' to the flash at `adr' with the
ALE and CLE lines false. If your board uses writes to
different addresses to control CLE and ALE, you can modify `adr'
to be the appropriate address here. If your board uses I/O registers
to control them, it is probably better to let NAND_CTL_CLRALE()
and company do it.
#define READ_NAND(adr)
Read a data byte from the flash at `adr' with the
ALE and CLE lines false. If your board uses reads from
different addresses to control CLE and ALE, you can modify `adr'
to be the appropriate address here. If your board uses I/O registers
to control them, it is probably better to let NAND_CTL_CLRALE()
and company do it.
#define NAND_DISABLE_CE(nand)
Set CE (Chip Enable) low to enable the NAND flash.
#define NAND_ENABLE_CE(nand)
Set CE (Chip Enable) high to disable the NAND flash.
#define NAND_CTL_CLRALE(nandptr)
Set ALE (address latch enable) low. If ALE control is handled by
WRITE_NAND_ADDRESS() this can be empty.
#define NAND_CTL_SETALE(nandptr)
Set ALE (address latch enable) high. If ALE control is handled by
WRITE_NAND_ADDRESS() this can be empty.
#define NAND_CTL_CLRCLE(nandptr)
Set CLE (command latch enable) low. If CLE control is handled by
WRITE_NAND_ADDRESS() this can be empty.
#define NAND_CTL_SETCLE(nandptr)
Set CLE (command latch enable) high. If CLE control is handled by
WRITE_NAND_ADDRESS() this can be empty.
More Definitions:
These definitions are needed in the board configuration for now, but
may really belong in a header file.
TODO: Figure which ones are truly configuration settings and rename
them to CFG_NAND_... and move the rest somewhere appropriate.
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1

View file

@ -4,8 +4,6 @@ i386 port missing features:
* setup the BIOS data area and BIOS equipment word to reflect machine config.
* Make reset work (from Linux and from the boot prompt)
* DMA, FDC, RTC, KBC initialization
* video card support (call BIOS to initialize, use helper routrine in BSP to shadow
video rom if on pci) and PC keyboard
* split of part of cpu/i386/interrupt.c to cpu/i385/entry.c?
* re-entry of protected mode from real mode, should be added to realmode_switch.S
(and used by INT 10h and INT 16h handlers for console I/O during early
@ -13,8 +11,6 @@ i386 port missing features:
* missing functions in lib_i386 and cpu/i386
* speaker beep interface
i386 port bugs:
* IDE does not work
SC520 missing features:
* Watchdog
@ -24,16 +20,10 @@ SC520 missing features:
* SC520 MMCR reset
SC520 CDP board support missing features:
* Synchronius serial port and seriel EEPROM
* environment in SEEP
* environment in flash
* environment in sram
* status LED ?
* flash driver
SC520 CDP board support bugs:
* SPI EEPROM support does not work
* 0x680 LEDS dos not work for me
* is it possible to make both the internal serial ports and the
ports on the sio work at the same time?
* ali sio cio lines?
* On-borad ethernet does not work from Linux

View file

@ -27,16 +27,23 @@ include $(TOPDIR)/config.mk
LIB = libdrivers.a
OBJS = 3c589.o 5701rls.o at91rm9200_ether.o \
bcm570x.o bcm570x_autoneg.o \
cfb_console.o cs8900.o ct69000.o dc2114x.o \
OBJS = 3c589.o 5701rls.o ali512x.o at91rm9200_ether.o \
bcm570x.o bcm570x_autoneg.o cfb_console.o \
cs8900.o ct69000.o dc2114x.o \
eepro100.o i8042.o i82365.o inca-ip_sw.o \
lan91c96.o natsemi.o ns16550.o ns8382x.o ns87308.o \
lan91c96.o natsemi.o \
ns16550.o ns8382x.o ns87308.o \
pci.o pci_auto.o pci_indirect.o \
pcnet.o plb2800_eth.o \
s3c24x0_i2c.o sed13806.o serial.o \
smc91111.o smiLynxEM.o sym53c8xx.o \
tigon3.o w83c553f.o
smc91111.o smiLynxEM.o sym53c8xx.o \
ti_pci1410a.o tigon3.o w83c553f.o
## Disabled for now:
## cs8900.o ct69000.o dc2114x.o ds1722.o \
## lan91c96.o mw_eeprom.o natsemi.o \
## smc91111.o smiLynxEM.o spi_eeprom.o sym53c8xx.o \
##
all: $(LIB)

View file

@ -30,6 +30,10 @@
*----------------------------------------------------------------------
*/
#include <config.h>
#ifdef CONFIG_ALI152X
#include <common.h>
#include <asm/io.h>
#include <asm/ic/ali512x.h>
@ -60,19 +64,21 @@ static void ali_write(u8 index, u8 value)
outb(value, ALI_DATA);
}
#if 0
static int ali_read(u8 index)
{
outb(index, ALI_INDEX);
return inb(ALI_DATA);
}
#endif
#define ALI_OPEN() \
outb(0x51, ALI_DATA); \
outb(0x23, ALI_DATA)
outb(0x51, ALI_INDEX); \
outb(0x23, ALI_INDEX)
#define ALI_CLOSE() \
outb(0xbb, ALI_DATA)
outb(0xbb, ALI_INDEX)
/* Select a logical device */
#define ALI_SELDEV(dev) \
@ -246,22 +252,22 @@ void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq)
* CIO36 ALT_MDAT Alternative Mouse Data
* CIO37 ALT_KBC Alternative KBC select
*
* The CIO use a double indirect address scheme.
* The CIO use an indirect address scheme.
*
* Reigster 3 in the SIO is used to selectg where the CIO
* I/O registers show up under function 8. Note that these
* registers clash with the CIO function select regsters,
* below.
* Reigster 3 in the SIO is used to select the index and data
* port addresses where the CIO I/O registers show up.
* The function selection registers are accessible under
* function SIO 8.
*
* SIO reigster 3 (CIO Address Selection) bit definitions:
* bit 7 CIO data register enabled
* bit 1-0 CIO indirect registers select
* bit 7 CIO index and data registers enabled
* bit 1-0 CIO indirect registers port address select
* 0 index = 0xE0 data = 0xE1
* 1 index = 0xE2 data = 0xE3
* 2 index = 0xE4 data = 0xE5
* 3 index = 0xEA data = 0xEB
*
* There are three CIO I/O register accessed via CIO index and CIO data
* There are three CIO I/O register accessed via CIO index port and CIO data port
* 0x01 CIO 10-17 data
* 0x02 CIO 20-25 data (bits 7-6 unused)
* 0x03 CIO 30-37 data
@ -305,50 +311,61 @@ void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq)
*
*/
#define ALI_CIO_PORT_SEL 0x83
#define ALI_CIO_INDEX 0xea
#define ALI_CIO_DATA 0xeb
void ali512x_set_cio(int enabled)
{
int i;
ALI_OPEN();
ali_write(0x3, 3); /* Disable CIO data register */
if (enabled) {
ali_write(0x3, ALI_CIO_PORT_SEL); /* Enable CIO data register */
} else {
ali_write(0x3, ALI_CIO_PORT_SEL & ~0x80);
}
ALI_SELDEV(8);
ali_write(0x30, enabled?1:0);
/* set all pins to input to start with */
for (i=0xe0;i<0xee;i++) {
ali_write(i, 1);
}
for (i=0xf5;i<0xfe;i++) {
ali_write(i, 1);
}
ALI_CLOSE();
}
void ali512x_cio_function(int pin, int special, int inv, int input)
{
u8 data;
u8 addr;
/* valid pins are 10-17, 20-25 and 30-37 */
if (pin >= 10 && pin <= 17) {
addr = 0xe0+(pin-10);
addr = 0xe0+(pin&7);
} else if (pin >= 20 && pin <= 25) {
addr = 0xe8+(pin-20);
addr = 0xe8+(pin&7);
} else if (pin >= 30 && pin <= 37) {
addr = 0xf5+(pin-30);
addr = 0xf5+(pin&7);
} else {
return;
}
ALI_OPEN();
ALI_SELDEV(8);
ali_write(0x03, 0x03); /* Disable CIO data register */
data=0;
data=0xf4;
if (special) {
data |= 0x08;
} else {
@ -371,37 +388,18 @@ void ali512x_cio_out(int pin, int value)
u8 data;
u8 bit;
/* valid pins are 10-17, 20-25 and 30-37 */
if (pin >= 10 && pin <= 17) {
reg = 1;
pin -= 10;
} else if (pin >= 20 && pin <= 25) {
reg = 2;
pin -= 20;
} else if (pin >= 30 && pin <= 37) {
reg = 3;
pin -= 30;
} else {
return;
}
bit = 1 << pin;
reg = pin/10;
bit = 1 << (pin%10);
ALI_OPEN();
ALI_SELDEV(8);
ali_write(0x03, 0x83); /* Enable CIO data register, use data port at 0xea */
ali_write(0xea, reg); /* select I/O register */
data = ali_read(0xeb);
outb(reg, ALI_CIO_INDEX); /* select I/O register */
data = inb(ALI_CIO_DATA);
if (value) {
data |= bit;
} else {
data &= ~bit;
}
ali_write(0xeb, data);
ali_write(0xea, 0); /* select register 0 */
ali_write(0x03, 0x03); /* Disable CIO data register */
ALI_CLOSE();
outb(data, ALI_CIO_DATA);
}
int ali512x_cio_in(int pin)
@ -409,34 +407,17 @@ int ali512x_cio_in(int pin)
u8 reg;
u8 data;
u8 bit;
/* valid pins are 10-17, 20-25 and 30-37 */
if (pin >= 10 && pin <= 17) {
reg = 1;
pin -= 10;
} else if (pin >= 20 && pin <= 25) {
reg = 2;
pin -= 20;
} else if (pin >= 30 && pin <= 37) {
reg = 3;
pin -= 30;
} else {
return -1;
}
bit = 1 << pin;
reg = pin/10;
bit = 1 << (pin%10);
ALI_OPEN();
ALI_SELDEV(8);
ali_write(0x03, 0x83); /* Enable CIO data register, use data port at 0xea */
ali_write(0xea, reg); /* select I/O register */
data = ali_read(0xeb);
ali_write(0xea, 0); /* select register 0 */
ali_write(0x03, 0x03); /* Disable CIO data register */
ALI_CLOSE();
outb(reg, ALI_CIO_INDEX); /* select I/O register */
data = inb(ALI_CIO_DATA);
return data & bit;
}
#endif

142
drivers/ds1722.c Normal file
View file

@ -0,0 +1,142 @@
#include <common.h>
#include <ssi.h>
#ifdef CONFIG_DS1722
static void ds1722_select(int dev)
{
ssi_set_interface(4096, 0, 0, 0);
ssi_chip_select(0);
udelay(1);
ssi_chip_select(dev);
udelay(1);
}
u8 ds1722_read(int dev, int addr)
{
u8 res;
ds1722_select(dev);
ssi_tx_byte(addr);
res = ssi_rx_byte();
ssi_chip_select(0);
return res;
}
void ds1722_write(int dev, int addr, u8 data)
{
ds1722_select(dev);
ssi_tx_byte(0x80|addr);
ssi_tx_byte(data);
ssi_chip_select(0);
}
u16 ds1722_temp(int dev, int resolution)
{
static int useconds[] = {
75000, 150000, 300000, 600000, 1200000
};
char temp;
u16 res;
/* set up the desired resulotion ... */
ds1722_write(dev, 0, 0xe0 | (resolution << 1));
/* wait while the chip measures the tremperature */
udelay(useconds[resolution]);
res = (temp = ds1722_read(dev, 2)) << 8;
if (temp < 0) {
temp = (16 - (ds1722_read(dev, 1) >> 4)) & 0x0f;
} else {
temp = (ds1722_read(dev, 1) >> 4);
}
switch (temp) {
case 0:
/* .0000 */
break;
case 1:
/* .0625 */
res |=1;
break;
case 2:
/* .1250 */
res |=1;
break;
case 3:
/* .1875 */
res |=2;
break;
case 4:
/* .2500 */
res |=3;
break;
case 5:
/* .3125 */
res |=3;
break;
case 6:
/* .3750 */
res |=4;
break;
case 7:
/* .4375 */
res |=4;
break;
case 8:
/* .5000 */
res |=5;
break;
case 9:
/* .5625 */
res |=6;
break;
case 10:
/* .6250 */
res |=6;
break;
case 11:
/* .6875 */
res |=7;
break;
case 12:
/* .7500 */
res |=8;
break;
case 13:
/* .8125 */
res |=8;
break;
case 14:
/* .8750 */
res |=9;
break;
case 15:
/* .9375 */
res |=9;
break;
}
return res;
}
int ds1722_probe(int dev)
{
u16 temp = ds1722_temp(dev, DS1722_RESOLUTION_12BIT);
printf("%d.%d deg C\n\n", (char)(temp >> 8), temp & 0xff);
return 0;
}
#endif

View file

@ -331,8 +331,8 @@ int eepro100_initialize (bd_t * bis)
dev = (struct eth_device *) malloc (sizeof *dev);
sprintf (dev->name, "i82559#%d", card_number);
dev->priv = (void *) devno; /* this have to come before bus_to_phys() */
dev->iobase = bus_to_phys (iobase);
dev->priv = (void *) devno;
dev->init = eepro100_init;
dev->halt = eepro100_halt;
dev->send = eepro100_send;

242
drivers/mw_eeprom.c Normal file
View file

@ -0,0 +1,242 @@
/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */
#include <common.h>
#include <ssi.h>
#ifdef CONFIG_MW_EEPROM
/*
* Serial EEPROM opcodes, including start bit
*/
#define EEP_OPC_ERASE 0x7 /* 3-bit opcode */
#define EEP_OPC_WRITE 0x5 /* 3-bit opcode */
#define EEP_OPC_READ 0x6 /* 3-bit opcode */
#define EEP_OPC_ERASE_ALL 0x12 /* 5-bit opcode */
#define EEP_OPC_ERASE_EN 0x13 /* 5-bit opcode */
#define EEP_OPC_WRITE_ALL 0x11 /* 5-bit opcode */
#define EEP_OPC_ERASE_DIS 0x10 /* 5-bit opcode */
static int addrlen;
static void mw_eeprom_select(int dev)
{
ssi_set_interface(2048, 0, 0, 0);
ssi_chip_select(0);
udelay(1);
ssi_chip_select(dev);
udelay(1);
}
static int mw_eeprom_size(int dev)
{
int x;
u16 res;
mw_eeprom_select(dev);
ssi_tx_byte(EEP_OPC_READ);
res = ssi_txrx_byte(0) << 8;
res |= ssi_rx_byte();
for (x = 0; x < 16; x++) {
if (! (res & 0x8000)) {
break;
}
res <<= 1;
}
ssi_chip_select(0);
return x;
}
int mw_eeprom_erase_enable(int dev)
{
mw_eeprom_select(dev);
ssi_tx_byte(EEP_OPC_ERASE_EN);
ssi_tx_byte(0);
udelay(1);
ssi_chip_select(0);
return 0;
}
int mw_eeprom_erase_disable(int dev)
{
mw_eeprom_select(dev);
ssi_tx_byte(EEP_OPC_ERASE_DIS);
ssi_tx_byte(0);
udelay(1);
ssi_chip_select(0);
return 0;
}
u32 mw_eeprom_read_word(int dev, int addr)
{
u16 rcv;
u16 res;
int bits;
mw_eeprom_select(dev);
ssi_tx_byte((EEP_OPC_READ << 5) | ((addr >> (addrlen - 5)) & 0x1f));
rcv = ssi_txrx_byte(addr << (13 - addrlen));
res = rcv << (16 - addrlen);
bits = 4 + addrlen;
while (bits>0) {
rcv = ssi_rx_byte();
if (bits > 7) {
res |= rcv << (bits - 8);
} else {
res |= rcv >> (8 - bits);
}
bits -= 8;
}
ssi_chip_select(0);
return res;
}
int mw_eeprom_write_word(int dev, int addr, u16 data)
{
u8 byte1=0;
u8 byte2=0;
mw_eeprom_erase_enable(dev);
mw_eeprom_select(dev);
switch (addrlen) {
case 6:
byte1 = EEP_OPC_WRITE >> 2;
byte2 = (EEP_OPC_WRITE << 6)&0xc0;
byte2 |= addr;
break;
case 7:
byte1 = EEP_OPC_WRITE >> 1;
byte2 = (EEP_OPC_WRITE << 7)&0x80;
byte2 |= addr;
break;
case 8:
byte1 = EEP_OPC_WRITE;
byte2 = addr;
break;
case 9:
byte1 = EEP_OPC_WRITE << 1;
byte1 |= addr >> 8;
byte2 = addr & 0xff;
break;
case 10:
byte1 = EEP_OPC_WRITE << 2;
byte1 |= addr >> 8;
byte2 = addr & 0xff;
break;
default:
printf("Unsupported number of address bits: %d\n", addrlen);
return -1;
}
ssi_tx_byte(byte1);
ssi_tx_byte(byte2);
ssi_tx_byte(data >> 8);
ssi_tx_byte(data & 0xff);
ssi_chip_select(0);
udelay(10000); /* Worst case */
mw_eeprom_erase_disable(dev);
return 0;
}
int mw_eeprom_write(int dev, int addr, u8 *buffer, int len)
{
int done;
done = 0;
if (addr & 1) {
u16 temp = mw_eeprom_read_word(dev, addr >> 1);
temp &= 0xff00;
temp |= buffer[0];
mw_eeprom_write_word(dev, addr >> 1, temp);
len--;
addr++;
buffer++;
done++;
}
while (len <= 2) {
mw_eeprom_write_word(dev, addr >> 1, *(u16*)buffer);
len-=2;
addr+=2;
buffer+=2;
done+=2;
}
if (len) {
u16 temp = mw_eeprom_read_word(dev, addr >> 1);
temp &= 0x00ff;
temp |= buffer[0] << 8;
mw_eeprom_write_word(dev, addr >> 1, temp);
len--;
addr++;
buffer++;
done++;
}
return done;
}
int mw_eeprom_read(int dev, int addr, u8 *buffer, int len)
{
int done;
done = 0;
if (addr & 1) {
u16 temp = mw_eeprom_read_word(dev, addr >> 1);
buffer[0]= temp & 0xff;
len--;
addr++;
buffer++;
done++;
}
while (len <= 2) {
*(u16*)buffer = mw_eeprom_read_word(dev, addr >> 1);
len-=2;
addr+=2;
buffer+=2;
done+=2;
}
if (len) {
u16 temp = mw_eeprom_read_word(dev, addr >> 1);
buffer[0] = temp >> 8;
len--;
addr++;
buffer++;
done++;
}
return done;
}
int mw_eeprom_probe(int dev)
{
addrlen = mw_eeprom_size(dev);
if (addrlen < 6 || addrlen > 10) {
return -1;
}
return 0;
}
#endif

668
drivers/ti_pci1410a.c Normal file
View file

@ -0,0 +1,668 @@
/*
* (C) Copyright 2000-2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB
*
* 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
*
********************************************************************
*
* Lots of code copied from:
*
* m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
* (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
*
* "The ExCA standard specifies that socket controllers should provide
* two IO and five memory windows per socket, which can be independently
* configured and positioned in the host address space and mapped to
* arbitrary segments of card address space. " - David A Hinds. 1999
*
* This controller does _not_ meet the ExCA standard.
*
* m8xx pcmcia controller brief info:
* + 8 windows (attrib, mem, i/o)
* + up to two slots (SLOT_A and SLOT_B)
* + inputpins, outputpins, event and mask registers.
* - no offset register. sigh.
*
* Because of the lacking offset register we must map the whole card.
* We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
* Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
* * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
* The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
* They are maximum 64KByte each...
*/
#undef DEBUG /**/
/*
* PCMCIA support
*/
#include <common.h>
#include <command.h>
#include <config.h>
#include <pci.h>
#include <asm/io.h>
#include <pcmcia.h>
#include <cmd_pcmcia.h>
#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && defined(CONFIG_IDE_TI_CARDBUS)
int pcmcia_on(int ide_base_bus);
static int pcmcia_off(void);
static int hardware_disable(int slot);
static int hardware_enable(int slot);
static int voltage_set(int slot, int vcc, int vpp);
static void print_funcid(int func);
static void print_fixed(volatile uchar *p);
static int identify(volatile uchar *p);
static int check_ide_device(int slot, int ide_base_bus);
/* ------------------------------------------------------------------------- */
const char *indent = "\t ";
/* ------------------------------------------------------------------------- */
int do_pinit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
#ifndef CFG_FISRT_PCMCIA_BUS
# define CFG_FISRT_PCMCIA_BUS 0
#endif
int rcode = 0;
if (argc != 2) {
printf ("Usage: pinit {on | off}\n");
return 1;
}
if (strcmp(argv[1],"on") == 0) {
rcode = pcmcia_on(CFG_FISRT_PCMCIA_BUS);
} else if (strcmp(argv[1],"off") == 0) {
rcode = pcmcia_off();
} else {
printf ("Usage: pinit {on | off}\n");
return 1;
}
return rcode;
}
/* ------------------------------------------------------------------------- */
static struct pci_device_id supported[] = {
{ PCI_VENDOR_ID_TI, 0xac50 }, /* Ti PCI1410A */
{ PCI_VENDOR_ID_TI, 0xac56 }, /* Ti PCI1510 */
{ }
};
static pci_dev_t devbusfn;
static u32 socket_base;
static u32 pcmcia_cis_ptr;
int pcmcia_on(int ide_base_bus)
{
u16 dev_id;
u32 socket_status;
int slot = 0;
int cis_len;
u16 io_base;
u16 io_len;
/*
* Find the CardBus PCI device(s).
*/
if ((devbusfn = pci_find_devices(supported, 0)) < 0) {
printf("Ti CardBus: not found\n");
return 1;
}
pci_read_config_word(devbusfn, PCI_DEVICE_ID, &dev_id);
if (dev_id == 0xac56) {
debug("Enable PCMCIA Ti PCI1510\n");
} else {
debug("Enable PCMCIA Ti PCI1410A\n");
}
pcmcia_cis_ptr = CFG_PCMCIA_CIS_WIN;
cis_len = CFG_PCMCIA_CIS_WIN_SIZE;
io_base = CFG_PCMCIA_IO_WIN;
io_len = CFG_PCMCIA_IO_WIN_SIZE;
/*
* Setup the PCI device.
*/
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &socket_base);
socket_base &= ~0xf;
socket_status = readl(socket_base+8);
if ((socket_status & 6) == 0) {
printf("Card Present: ");
switch (socket_status & 0x3c00) {
case 0x400:
printf("5V ");
break;
case 0x800:
printf("3.3V ");
break;
case 0xc00:
printf("3.3/5V ");
break;
default:
printf("unsupported Vcc ");
break;
}
switch (socket_status & 0x30) {
case 0x10:
printf("16bit PC-Card\n");
break;
case 0x20:
printf("32bit CardBus Card\n");
break;
default:
printf("8bit PC-Card\n");
break;
}
}
writeb(0x41, socket_base + 0x806); /* Enable I/O window 0 and memory window 0 */
writeb(0x0e, socket_base + 0x807); /* Reset I/O window options */
/* Careful: the linux yenta driver do not seem to reset the offset
* in the i/o windows, so leaving them non-zero is a problem */
writeb(io_base & 0xff, socket_base + 0x808); /* I/O window 0 base address */
writeb(io_base>>8, socket_base + 0x809);
writeb((io_base + io_len - 1) & 0xff, socket_base + 0x80a); /* I/O window 0 end address */
writeb((io_base + io_len - 1)>>8, socket_base + 0x80b);
writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address 0x000 */
writeb(0x00, socket_base + 0x837);
writeb((pcmcia_cis_ptr&0x000ff000) >> 12,
socket_base + 0x810); /* Memory window 0 start address bits 19-12 */
writeb((pcmcia_cis_ptr&0x00f00000) >> 20,
socket_base + 0x811); /* Memory window 0 start address bits 23-20 */
writeb(((pcmcia_cis_ptr+cis_len-1) & 0x000ff000) >> 12,
socket_base + 0x812); /* Memory window 0 end address bits 19-12*/
writeb(((pcmcia_cis_ptr+cis_len-1) & 0x00f00000) >> 20,
socket_base + 0x813); /* Memory window 0 end address bits 23-20*/
writeb(0x00, socket_base + 0x814); /* Memory window 0 offset bits 19-12 */
writeb(0x40, socket_base + 0x815); /* Memory window 0 offset bits 23-20 and
* options (read/write, attribute access) */
writeb(0x00, socket_base + 0x816); /* ExCA card-detect and general control */
writeb(0x00, socket_base + 0x81e); /* ExCA global control (interrupt modes) */
writeb((pcmcia_cis_ptr & 0xff000000) >> 24,
socket_base + 0x840); /* Memory window address bits 31-24 */
/* turn off voltage */
if (voltage_set(slot, 0, 0)) {
return 1;
}
/* Enable external hardware */
if (hardware_enable(slot)) {
return 1;
}
if (check_ide_device(slot, ide_base_bus)) {
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------- */
static int pcmcia_off (void)
{
int slot = 0;
writeb(0x00, socket_base + 0x806); /* disable all I/O and memory windows */
writeb(0x00, socket_base + 0x808); /* I/O window 0 base address */
writeb(0x00, socket_base + 0x809);
writeb(0x00, socket_base + 0x80a); /* I/O window 0 end address */
writeb(0x00, socket_base + 0x80b);
writeb(0x00, socket_base + 0x836); /* I/O window 0 offset address */
writeb(0x00, socket_base + 0x837);
writeb(0x00, socket_base + 0x80c); /* I/O window 1 base address */
writeb(0x00, socket_base + 0x80d);
writeb(0x00, socket_base + 0x80e); /* I/O window 1 end address */
writeb(0x00, socket_base + 0x80f);
writeb(0x00, socket_base + 0x838); /* I/O window 1 offset address */
writeb(0x00, socket_base + 0x839);
writeb(0x00, socket_base + 0x810); /* Memory window 0 start address */
writeb(0x00, socket_base + 0x811);
writeb(0x00, socket_base + 0x812); /* Memory window 0 end address */
writeb(0x00, socket_base + 0x813);
writeb(0x00, socket_base + 0x814); /* Memory window 0 offset */
writeb(0x00, socket_base + 0x815);
writeb(0xc0, socket_base + 0x840); /* Memory window 0 page address */
/* turn off voltage */
voltage_set(slot, 0, 0);
/* disable external hardware */
printf ("Shutdown and Poweroff Ti PCI1410A\n");
hardware_disable(slot);
return 0;
}
/* ------------------------------------------------------------------------- */
#define MAX_TUPEL_SZ 512
#define MAX_FEATURES 4
int ide_devices_found;
static int check_ide_device(int slot, int ide_base_bus)
{
volatile uchar *ident = NULL;
volatile uchar *feature_p[MAX_FEATURES];
volatile uchar *p, *start;
int n_features = 0;
uchar func_id = ~0;
uchar code, len;
ushort config_base = 0;
int found = 0;
int i;
u32 socket_status;
debug ("PCMCIA MEM: %08X\n", pcmcia_cis_ptr);
socket_status = readl(socket_base+8);
if ((socket_status & 6) != 0 || (socket_status & 0x20) != 0) {
printf("no card or CardBus card\n");
return 1;
}
start = p = (volatile uchar *) pcmcia_cis_ptr;
while ((p - start) < MAX_TUPEL_SZ) {
code = *p; p += 2;
if (code == 0xFF) { /* End of chain */
break;
}
len = *p; p += 2;
#if defined(DEBUG) && (DEBUG > 1)
{
volatile uchar *q = p;
printf ("\nTuple code %02x length %d\n\tData:",
code, len);
for (i = 0; i < len; ++i) {
printf (" %02x", *q);
q+= 2;
}
}
#endif /* DEBUG */
switch (code) {
case CISTPL_VERS_1:
ident = p + 4;
break;
case CISTPL_FUNCID:
/* Fix for broken SanDisk which may have 0x80 bit set */
func_id = *p & 0x7F;
break;
case CISTPL_FUNCE:
if (n_features < MAX_FEATURES)
feature_p[n_features++] = p;
break;
case CISTPL_CONFIG:
config_base = (*(p+6) << 8) + (*(p+4));
debug ("\n## Config_base = %04x ###\n", config_base);
default:
break;
}
p += 2 * len;
}
found = identify(ident);
if (func_id != ((uchar)~0)) {
print_funcid (func_id);
if (func_id == CISTPL_FUNCID_FIXED)
found = 1;
else
return 1; /* no disk drive */
}
for (i=0; i<n_features; ++i) {
print_fixed(feature_p[i]);
}
if (!found) {
printf("unknown card type\n");
return 1;
}
/* select config index 1 */
writeb(1, pcmcia_cis_ptr + config_base);
#if 0
printf("Confiuration Option Register: %02x\n", readb(pcmcia_cis_ptr + config_base));
printf("Card Confiuration and Status Register: %02x\n", readb(pcmcia_cis_ptr + config_base + 2));
printf("Pin Replacement Register Register: %02x\n", readb(pcmcia_cis_ptr + config_base + 4));
printf("Socket and Copy Register: %02x\n", readb(pcmcia_cis_ptr + config_base + 6));
#endif
ide_devices_found |= (1 << (slot+ide_base_bus));
return 0;
}
static int voltage_set(int slot, int vcc, int vpp)
{
u32 socket_control;
int reg=0;
switch (slot) {
case 0:
reg = socket_base + 0x10;
break;
default:
return 1;
}
socket_control = 0;
switch (vcc) {
case 50:
socket_control |= 0x20;
break;
case 33:
socket_control |= 0x30;
break;
case 0:
default:
}
switch (vpp) {
case 120:
socket_control |= 0x1;
break;
case 50:
socket_control |= 0x2;
break;
case 33:
socket_control |= 0x3;
break;
case 0:
default:
}
writel(socket_control, reg);
debug ("voltage_set: Ti PCI1410A Slot %d, Vcc=%d.%d, Vpp=%d.%d\n",
slot, vcc/10, vcc%10, vpp/10, vpp%10);
udelay(500);
return 0;
}
static int hardware_enable(int slot)
{
u32 socket_status;
u16 brg_ctrl;
int is_82365sl;
socket_status = readl(socket_base+8);
if ((socket_status & 6) == 0) {
switch (socket_status & 0x3c00) {
case 0x400:
printf("5V ");
voltage_set(slot, 50, 0);
break;
case 0x800:
voltage_set(slot, 33, 0);
break;
case 0xc00:
voltage_set(slot, 33, 0);
break;
default:
voltage_set(slot, 0, 0);
break;
}
} else {
voltage_set(slot, 0, 0);
}
pci_read_config_word(devbusfn, PCI_BRIDGE_CONTROL, &brg_ctrl);
brg_ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_word(devbusfn, PCI_BRIDGE_CONTROL, brg_ctrl);
is_82365sl = ((readb(socket_base+0x800) & 0x0f) == 2);
writeb(is_82365sl?0x90:0x98, socket_base+0x802);
writeb(0x67, socket_base+0x803);
udelay(100000);
#if 0
printf("ExCA Id %02x, Card Status %02x, Power config %02x, Interrupt Config %02x, bridge control %04x %d\n",
readb(socket_base+0x800), readb(socket_base+0x801),
readb(socket_base+0x802), readb(socket_base+0x803), brg_ctrl, is_82365sl);
#endif
return ((readb(socket_base+0x801)&0x6c)==0x6c)?0:1;
}
static int hardware_disable(int slot)
{
voltage_set(slot, 0, 0);
return 0;
}
static void print_funcid(int func)
{
puts(indent);
switch (func) {
case CISTPL_FUNCID_MULTI:
puts(" Multi-Function");
break;
case CISTPL_FUNCID_MEMORY:
puts(" Memory");
break;
case CISTPL_FUNCID_SERIAL:
puts(" Serial Port");
break;
case CISTPL_FUNCID_PARALLEL:
puts(" Parallel Port");
break;
case CISTPL_FUNCID_FIXED:
puts(" Fixed Disk");
break;
case CISTPL_FUNCID_VIDEO:
puts(" Video Adapter");
break;
case CISTPL_FUNCID_NETWORK:
puts(" Network Adapter");
break;
case CISTPL_FUNCID_AIMS:
puts(" AIMS Card");
break;
case CISTPL_FUNCID_SCSI:
puts(" SCSI Adapter");
break;
default:
puts(" Unknown");
break;
}
puts(" Card\n");
}
/* ------------------------------------------------------------------------- */
static void print_fixed(volatile uchar *p)
{
if (p == NULL)
return;
puts(indent);
switch (*p) {
case CISTPL_FUNCE_IDE_IFACE:
{ uchar iface = *(p+2);
puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
puts (" interface ");
break;
}
case CISTPL_FUNCE_IDE_MASTER:
case CISTPL_FUNCE_IDE_SLAVE:
{
uchar f1 = *(p+2);
uchar f2 = *(p+4);
puts((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
if (f1 & CISTPL_IDE_UNIQUE) {
puts(" [unique]");
}
puts((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
if (f2 & CISTPL_IDE_HAS_SLEEP) {
puts(" [sleep]");
}
if (f2 & CISTPL_IDE_HAS_STANDBY) {
puts(" [standby]");
}
if (f2 & CISTPL_IDE_HAS_IDLE) {
puts(" [idle]");
}
if (f2 & CISTPL_IDE_LOW_POWER) {
puts(" [low power]");
}
if (f2 & CISTPL_IDE_REG_INHIBIT) {
puts(" [reg inhibit]");
}
if (f2 & CISTPL_IDE_HAS_INDEX) {
puts(" [index]");
}
if (f2 & CISTPL_IDE_IOIS16) {
puts(" [IOis16]");
}
break;
}
}
putc('\n');
}
/* ------------------------------------------------------------------------- */
#define MAX_IDENT_CHARS 64
#define MAX_IDENT_FIELDS 4
static uchar *known_cards[] = {
"ARGOSY PnPIDE D5",
NULL
};
static int identify(volatile uchar *p)
{
uchar id_str[MAX_IDENT_CHARS];
uchar data;
uchar *t;
uchar **card;
int i, done;
if (p == NULL)
return (0); /* Don't know */
t = id_str;
done =0;
for (i=0; i<=4 && !done; ++i, p+=2) {
while ((data = *p) != '\0') {
if (data == 0xFF) {
done = 1;
break;
}
*t++ = data;
if (t == &id_str[MAX_IDENT_CHARS-1]) {
done = 1;
break;
}
p += 2;
}
if (!done)
*t++ = ' ';
}
*t = '\0';
while (--t > id_str) {
if (*t == ' ') {
*t = '\0';
} else {
break;
}
}
puts(id_str);
putc('\n');
for (card=known_cards; *card; ++card) {
debug ("## Compare against \"%s\"\n", *card);
if (strcmp(*card, id_str) == 0) { /* found! */
debug ("## CARD FOUND ##\n");
return 1;
}
}
return 0; /* don't know */
}
#endif /* CONFIG_IDE_TI_CARDBUS */

354
examples/82559_eeprom.c Normal file
View file

@ -0,0 +1,354 @@
/*
* Copyright 1998-2001 by Donald Becker.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
* Contact the author for use under other terms.
*
* This program must be compiled with "-O"!
* See the bottom of this file for the suggested compile-command.
*
* The author may be reached as becker@scyld.com, or C/O
* Scyld Computing Corporation
* 410 Severn Ave., Suite 210
* Annapolis MD 21403
*
* Common-sense licensing statement: Using any portion of this program in
* your own program means that you must give credit to the original author
* and release the resulting code under the GPL.
*/
#define _PPC_STRING_H_ /* avoid unnecessary str/mem functions */
#define _LINUX_STRING_H_ /* avoid unnecessary str/mem functions */
#include <common.h>
#include <syscall.h>
#include <asm/io.h>
/* Default EEPROM for i82559 */
static unsigned short default_eeprom[64] = {
0x0100, 0x0302, 0x0504, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0x40c0, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
static unsigned short eeprom[256];
static int eeprom_size = 64;
static int eeprom_addr_size = 6;
static int debug = 0;
static inline unsigned short swap16(unsigned short x)
{
return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
}
static inline void *memcpy(void *dst, const void *src, unsigned int len)
{
void * ret = dst;
while (len-- > 0) *((char *)dst)++ = *((char *)src)++;
return ret;
}
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
/* Serial EEPROM section. */
#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
#define EE_CS 0x02 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
#define EE_ENB (0x4800 | EE_CS)
#define EE_WRITE_0 0x4802
#define EE_WRITE_1 0x4806
#define EE_OFFSET 14
/* Delay between EEPROM clock transitions. */
#define eeprom_delay(ee_addr) inw(ee_addr)
/* Wait for the EEPROM to finish the previous operation. */
static int eeprom_busy_poll(long ee_ioaddr)
{
int i;
outw(EE_ENB, ee_ioaddr);
for (i = 0; i < 10000; i++) /* Typical 2000 ticks */
if (inw(ee_ioaddr) & EE_DATA_READ)
break;
return i;
}
/* This executes a generic EEPROM command, typically a write or write enable.
It returns the data output from the EEPROM, and thus may also be used for
reads. */
static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
{
unsigned retval = 0;
long ee_addr = ioaddr + EE_OFFSET;
if (debug > 1)
mon_printf(" EEPROM op 0x%x: ", cmd);
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
/* Shift the command bits out. */
do {
short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
outw(dataval, ee_addr);
eeprom_delay(ee_addr);
if (debug > 2)
mon_printf("%X", inw(ee_addr) & 15);
outw(dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(ee_addr);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
} while (--cmd_len >= 0);
#if 0
outw(EE_ENB, ee_addr);
#endif
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
if (debug > 1)
mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
return retval;
}
static int read_eeprom(long ioaddr, int location, int addr_len)
{
return do_eeprom_cmd(ioaddr, ((EE_READ_CMD << addr_len) | location)
<< 16 , 3 + addr_len + 16) & 0xffff;
}
static void write_eeprom(long ioaddr, int index, int value, int addr_len)
{
long ee_ioaddr = ioaddr + EE_OFFSET;
int i;
/* Poll for previous op finished. */
eeprom_busy_poll(ee_ioaddr); /* Typical 0 ticks */
/* Enable programming modes. */
do_eeprom_cmd(ioaddr, (0x4f << (addr_len-4)), 3 + addr_len);
/* Do the actual write. */
do_eeprom_cmd(ioaddr,
(((EE_WRITE_CMD<<addr_len) | index)<<16) | (value & 0xffff),
3 + addr_len + 16);
/* Poll for write finished. */
i = eeprom_busy_poll(ee_ioaddr); /* Typical 2000 ticks */
if (debug)
mon_printf(" Write finished after %d ticks.\n", i);
/* Disable programming. This command is not instantaneous, so we check
for busy before the next op. */
do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
eeprom_busy_poll(ee_ioaddr);
}
static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
{
unsigned short checksum = 0;
int size_test;
int i;
mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
eeprom_size = 1 << eeprom_addr_size;
memcpy(eeprom, default_eeprom, sizeof default_eeprom);
for (i = 0; i < 3; i++)
eeprom[i] = (hwaddr[i*2+1]<<8) + hwaddr[i*2];
/* Recalculate the checksum. */
for (i = 0; i < eeprom_size - 1; i++)
checksum += eeprom[i];
eeprom[i] = 0xBABA - checksum;
for (i = 0; i < eeprom_size; i++)
write_eeprom(ioaddr, i, eeprom[i], eeprom_addr_size);
for (i = 0; i < eeprom_size; i++)
if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
mon_printf("failed\n");
return 1;
}
mon_printf("done\n");
return 0;
}
static unsigned int hatoi(char *p, char **errp)
{
unsigned int res = 0;
while (1) {
switch (*p) {
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
res |= (*p - 'a' + 10);
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
res |= (*p - 'A' + 10);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
res |= (*p - '0');
break;
default:
if (errp) {
*errp = p;
}
return res;
}
p++;
if (*p == 0) {
break;
}
res <<= 4;
}
if (errp) {
*errp = NULL;
}
return res;
}
static unsigned char *gethwaddr(char *in, unsigned char *out)
{
char tmp[3];
int i;
char *err;
for (i=0;i<6;i++) {
if (in[i*3+2] == 0 && i == 5) {
out[i] = hatoi(&in[i*3], &err);
if (err) {
return NULL;
}
} else if (in[i*3+2] == ':' && i < 5) {
tmp[0] = in[i*3];
tmp[1] = in[i*3+1];
tmp[2] = 0;
out[i] = hatoi(tmp, &err);
if (err) {
return NULL;
}
} else {
return NULL;
}
}
return out;
}
static u32
read_config_dword(int bus, int dev, int func, int reg)
{
u32 res;
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
0xcf8);
res = inl(0xcfc);
outl(0, 0xcf8);
return res;
}
static u16
read_config_word(int bus, int dev, int func, int reg)
{
u32 res;
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
0xcf8);
res = inw(0xcfc + (reg & 2));
outl(0, 0xcf8);
return res;
}
static void
write_config_word(int bus, int dev, int func, int reg, u16 data)
{
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
0xcf8);
outw(data, 0xcfc + (reg & 2));
outl(0, 0xcf8);
}
int main (int argc, char *argv[])
{
unsigned char *eth_addr;
char buf[6];
int instance;
if (argc != 2) {
mon_printf ("call with base Ethernet address\n");
return 1;
}
eth_addr = gethwaddr(argv[1], buf);
if (NULL == eth_addr) {
mon_printf ("Can not parse ethernet address\n");
return 1;
}
if (eth_addr[5] & 0x01) {
mon_printf("Base Ethernet address must be even\n");
}
for (instance = 0; instance < 2; instance ++) {
unsigned int io_addr;
unsigned char mac[6];
int bar1 = read_config_dword(0, 6+instance, 0, 0x14);
if (! (bar1 & 1)) {
mon_printf("ETH%d is disabled %x\n", instance, bar1);
} else {
mon_printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
}
io_addr = (bar1 & (~3L));
write_config_word(0, 6+instance, 0, 4,
read_config_word(0, 6+instance, 0, 4) | 1);
mon_printf("ETH%d CMD %04x\n", instance,
read_config_word(0, 6+instance, 0, 4));
memcpy(mac, eth_addr, 6);
mac[5] += instance;
mon_printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
io_addr, mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
reset_eeprom(io_addr, mac);
}
return 0;
}

View file

@ -28,6 +28,11 @@ include $(TOPDIR)/config.mk
SREC = hello_world.srec
BIN = hello_world.bin
ifeq ($(ARCH),i386)
SREC += 82559_eeprom.srec
BIN += 82559_eeprom.bin
endif
ifeq ($(ARCH),ppc)
SREC += sched.srec
BIN += sched.bin

View file

@ -76,7 +76,11 @@ mon_free:
#define SYSCALL(name,n) \
.globl SYMBOL_NAME(name) ; \
SYMBOL_NAME_LABEL(name) ; \
ret
movl $n, %eax ;\
pushl %ebx; \
pushl %ecx; \
int $0x40 ;\
#endif /* CONFIG_I386 */

View file

@ -5,7 +5,6 @@
* Copyright 1992, Linus Torvalds.
*/
#include <linux/config.h>
/*
* These have to be done with inline assembly: that way the bit-setting

View file

@ -5,10 +5,6 @@
#ifdef __GNUC__
/* For avoiding bswap on i386 */
#ifdef __KERNEL__
#include <linux/config.h>
#endif
static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
{

View file

@ -116,6 +116,11 @@
#define SC520_UART2CTL 0x0cc4 /* UART 2 General Control Register */
#define SC520_UART2STA 0x0cc5 /* UART 2 General Status Register */
#define SC520_UART2FCRSHAD 0x0cc6 /* UART 2 FIFO Control Shadow Register */
#define SC520_SSICTL 0x0cd0 /* SSI Control */
#define SC520_SSIXMIT 0x0cd1 /* SSI Transmit */
#define SC520_SSICMD 0x0cd2 /* SSI Command */
#define SC520_SSISTA 0x0cd3 /* SSI Status */
#define SC520_SSIRCV 0x0cd4 /* SSI Receive */
#define SC520_PICICR 0x0d00 /* Interrupt Control Register */
#define SC520_MPICMODE 0x0d02 /* Master PIC Interrupt Mode Register */
#define SC520_SL1PICMODE 0x0d03 /* Slave 1 PIC Interrupt Mode Register */
@ -195,9 +200,31 @@
/* MMCR Register bits (not all of them :) ) */
/* SSI Stuff */
#define CTL_CLK_SEL_4 0x00 /* Nominal Bit Rate = 8 MHz */
#define CTL_CLK_SEL_8 0x10 /* Nominal Bit Rate = 4 MHz */
#define CTL_CLK_SEL_16 0x20 /* Nominal Bit Rate = 2 MHz */
#define CTL_CLK_SEL_32 0x30 /* Nominal Bit Rate = 1 MHz */
#define CTL_CLK_SEL_64 0x40 /* Nominal Bit Rate = 512 KHz */
#define CTL_CLK_SEL_128 0x50 /* Nominal Bit Rate = 256 KHz */
#define CTL_CLK_SEL_256 0x60 /* Nominal Bit Rate = 128 KHz */
#define CTL_CLK_SEL_512 0x70 /* Nominal Bit Rate = 64 KHz */
#define TC_INT_ENB 0x08 /* Transaction Complete Interrupt Enable */
#define PHS_INV_ENB 0x04 /* SSI Inverted Phase Mode Enable */
#define CLK_INV_ENB 0x02 /* SSI Inverted Clock Mode Enable */
#define MSBF_ENB 0x01 /* SSI Most Significant Bit First Mode Enable */
#define SSICMD_CMD_SEL_XMITRCV 0x03 /* Simultaneous Transmit / Receive Transaction */
#define SSICMD_CMD_SEL_RCV 0x02 /* Receive Transaction */
#define SSICMD_CMD_SEL_XMIT 0x01 /* Transmit Transaction */
#define SSISTA_BSY 0x02 /* SSI Busy */
#define SSISTA_TC_INT 0x01 /* SSI Transaction Complete Interrupt */
/* BITS for SC520_ADDDECCTL: */
#define WPV_INT_ENB 0x80 /* Write-Protect Violation Interrupt Enable */
#define IO_HOLE_DEST 0x10 /* I/O Hole Access Destination */
#define IO_HOLE_DEST_PCI 0x10 /* I/O Hole Access Destination */
#define RTC_DIS 0x04 /* RTC Disable */
#define UART2_DIS 0x02 /* UART2 Disable */
#define UART1_DIS 0x01 /* UART1 Disable */
@ -215,25 +242,64 @@
#define SC520_ISA_IO_BUS 0x00000000
#define SC520_ISA_IO_SIZE 0x00001000
/* PCI I/O space from 0x1000 to 0xfdff */
/* PCI I/O space from 0x1000 to 0xdfff
* (make 0xe000-0xfdff available for stuff like PCCard boot) */
#define SC520_PCI_IO_PHYS 0x00001000
#define SC520_PCI_IO_BUS 0x00001000
#define SC520_PCI_IO_SIZE 0x0000ee00
#define SC520_PCI_IO_SIZE 0x0000d000
/* system memory from 0x00000000 to 0x0fffffff */
#define SC520_PCI_MEMORY_PHYS 0x00000000
#define SC520_PCI_MEMORY_BUS 0x00000000
#define SC520_PCI_MEMORY_SIZE 0x10000000
/* PCI bus memory from 0x10000000 to 0x27ffffff */
/* PCI bus memory from 0x10000000 to 0x26ffffff
* (make 0x27000000 - 0x27ffffff available for stuff like PCCard boot) */
#define SC520_PCI_MEM_PHYS 0x10000000
#define SC520_PCI_MEM_BUS 0x10000000
#define SC520_PCI_MEM_SIZE 0x18000000
#define SC520_PCI_MEM_SIZE 0x17000000
/* 0x28000000 - 0x3fffffff is used by the flash banks */
/* 0x40000000 - 0xffffffff is not adressable by the SC520 */
/* priority numbers used for interrupt channel mappings */
#define SC520_IRQ_DISABLED 0
#define SC520_IRQ0 1
#define SC520_IRQ1 2
#define SC520_IRQ2 4 /* same as IRQ9 */
#define SC520_IRQ3 11
#define SC520_IRQ4 12
#define SC520_IRQ5 13
#define SC520_IRQ6 21
#define SC520_IRQ7 22
#define SC520_IRQ8 3
#define SC520_IRQ9 4
#define SC520_IRQ10 5
#define SC520_IRQ11 6
#define SC520_IRQ12 7
#define SC520_IRQ13 8
#define SC520_IRQ14 9
#define SC520_IRQ15 10
/* pin number used for PCI interrupt mappings */
#define SC520_PCI_INTA 0
#define SC520_PCI_INTB 1
#define SC520_PCI_INTC 2
#define SC520_PCI_INTD 3
#define SC520_PCI_GPIRQ0 4
#define SC520_PCI_GPIRQ1 5
#define SC520_PCI_GPIRQ2 6
#define SC520_PCI_GPIRQ3 7
#define SC520_PCI_GPIRQ4 8
#define SC520_PCI_GPIRQ5 9
#define SC520_PCI_GPIRQ6 10
#define SC520_PCI_GPIRQ7 11
#define SC520_PCI_GPIRQ8 12
#define SC520_PCI_GPIRQ9 13
#define SC520_PCI_GPIRQ10 14
/* utility functions */
void write_mmcr_byte(u16 mmcr, u8 data);
void write_mmcr_word(u16 mmcr, u16 data);
@ -242,8 +308,11 @@ u8 read_mmcr_byte(u16 mmcr);
u16 read_mmcr_word(u16 mmcr);
u32 read_mmcr_long(u16 mmcr);
extern int sc520_pci_ints[];
void init_sc520(void);
unsigned long init_sc520_dram(void);
void pci_sc520_init(struct pci_controller *hose);
int pci_sc520_set_irq(int pci_pin, int irq);
#endif

View file

@ -1,8 +1,6 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
#include <linux/config.h>
/*
* This file contains the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl and the "string versions" of the same

View file

@ -27,5 +27,11 @@
#define _PCI_I386_H_ 1
void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data);
int pci_enable_legacy_video_ports(struct pci_controller* hose);
int pci_shadow_rom(pci_dev_t dev, unsigned char *dest);
void pci_remove_rom_window(struct pci_controller* hose, u32 addr);
u32 pci_get_rom_window(struct pci_controller* hose, int size);
#endif

View file

@ -27,5 +27,6 @@
int bios_setup(void);
int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out);
int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out);
#endif

View file

@ -46,8 +46,15 @@ int cpu_init(void);
int timer_init(void);
/* board/.../... */
int board_init(void);
int dram_init (void);
int board_init(void);
int dram_init(void);
void isa_unmap_rom(u32 addr);
u32 isa_map_rom(u32 bus_addr, int size);
/* lib_i386/... */
int video_bios_init(void);
int video_init(void);
#endif /* _U_BOOT_I386_H_ */

View file

@ -43,7 +43,8 @@ typedef struct bd_info {
unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
unsigned long bi_intfreq; /* Internal Freq, in MHz */
unsigned long bi_busfreq; /* Bus Freq, in MHz */
unsigned long bi_baudrate; /* Console Baudrate */
unsigned int bi_baudrate; /* Console Baudrate */
unsigned long bi_boot_params; /* where this board expects params */
struct environment_s *bi_env;
struct /* RAM configuration */
{

View file

@ -80,6 +80,7 @@
#define CFG_CMD_VFD 0x0000400000000000 /* VFD support (TRAB) */
#define CFG_CMD_NAND 0x0000800000000000 /* NAND support */
#define CFG_CMD_BMP 0x0001000000000000 /* BMP support */
#define CFG_CMD_PORTIO 0x0002000000000000 /* Port I/O */
#define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFF /* ALL commands */

View file

@ -27,18 +27,21 @@
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CMD_TBL_NAND MK_CMD_TBL_ENTRY( \
"nand", 3, 5, 1, do_nand, \
"nand - NAND sub-system\n", \
"nand", 3, 5, 1, do_nand, \
"nand - NAND sub-system\n", \
"info - show available NAND devices\n" \
"nand device [dev] - show or set current device\n" \
"nand read addr off size\n" \
"nand write addr off size - read/write `size'" \
" bytes starting at offset `off'\n" \
" to/from memory address `addr'\n" \
"nand erase off size - erase `size' bytes of NAND from offset `off'\n" \
"nand read[.jffs2] addr off size\n" \
"nand write[.jffs2] addr off size - read/write `size' bytes starting\n" \
" at offset `off' to/from memory address `addr'\n" \
"nand erase [clean] [off size] - erase `size' bytes from\n" \
" offset `off' (entire device if not specified)\n" \
"nand bad - show bad blocks\n" \
"nand read.oob addr off size - read out-of-band data\n" \
"nand write.oob addr off size - read out-of-band data\n" \
),
#define CMD_TBL_NANDBOOT MK_CMD_TBL_ENTRY( \
#define CMD_TBL_NANDBOOT MK_CMD_TBL_ENTRY( \
"nboot", 4, 4, 1, do_nandboot, \
"nboot - boot from NAND device\n", \
"loadAddr dev\n" \

52
include/cmd_portio.h Normal file
View file

@ -0,0 +1,52 @@
/*
* (C) Copyright 2003
* Marc Singer, elf@buici.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Memory Functions
*/
#ifndef _CMD_PORTIO_H
#define _CMD_PORTIO_H
#if (CONFIG_COMMANDS & CFG_CMD_PORTIO)
#define CMD_TBL_PORTIO_OUT MK_CMD_TBL_ENTRY( \
"out", 3, 3, 1, do_portio_out, \
"out - write datum to IO port\n", \
"[.b, .w, .l] port value\n - output to IO port\n" \
),
#define CMD_TBL_PORTIO_IN MK_CMD_TBL_ENTRY( \
"in", 2, 2, 1, do_portio_in, \
"in - read data from an IO port\n", \
"[.b, .w, .l] port\n" \
" - read datum from IO port\n" \
),
int do_portio_out (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_portio_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_PORTIO_OUT
#define CMD_TBL_PORTIO_IN
#endif /* CFG_CMD_PORTIO */
#endif /* _CMD_PORTIO_H */

View file

@ -279,7 +279,7 @@
/* Memory Bank 0 (Flash Bank 0, NOR-FLASH) initialization */
#define CFG_EBC_PB0AP 0x92015480
//#define CFG_EBC_PB0AP 0x08055880 /* TWT=16,CSN=1,OEN=1,WBN=1,WBF=1,TH=4,SOR=1 */
/*#define CFG_EBC_PB0AP 0x08055880 /XXX* TWT=16,CSN=1,OEN=1,WBN=1,WBF=1,TH=4,SOR=1 */
#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */
/* Memory Bank 1 (Flash Bank 1, NAND-FLASH) initialization */

View file

@ -29,7 +29,7 @@
#define __CONFIG_H
/* Debug options */
//#define __DEBUG_START_FROM_SRAM__
/*#define __DEBUG_START_FROM_SRAM__ */
@ -259,7 +259,7 @@
#endif
//#define CFG_MONITOR_LEN (200 * 1024) /* Reserve 200 kB for Monitor */
/*#define CFG_MONITOR_LEN (200 * 1024) /XXX* Reserve 200 kB for Monitor */
#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 200 kB for Monitor */
#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */

View file

@ -27,7 +27,18 @@
*/
/*
* Config header file for a MPC8260ADS Pilot 16M Ram Simm, 8Mbytes Flash Simm
* Config header file for a MPC8266ADS Pilot 16M Ram Simm, 8Mbytes Flash Simm
*/
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! This configuration requires JP3 to be in position 1-2 to work !!
!! To make it work for the default, the TEXT_BASE define in !!
!! board/mpc8266ads/config.mk must be changed from 0xfe000000 to !!
!! 0xfff00000 !!
!! The CFG_HRCW_MASTER define below must also be changed to match !!
!! !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#ifndef __CONFIG_H
@ -375,6 +386,7 @@
#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
/* Use this HRCW for booting from address 0xfe00000 (JP3 in setting 1-2) */
/* 0x0EB2B645 */
#define CFG_HRCW_MASTER (( HRCW_BPS11 | HRCW_CIP ) |\
( HRCW_L2CPC10 | HRCW_DPPC11 | HRCW_ISB010 ) |\
@ -382,8 +394,10 @@
( HRCW_CS10PC01 | HRCW_MODCK_H0101 ) \
)
/* Use this HRCW for booting from address 0xfff0000 (JP3 in setting 2-3) */
/* #define CFG_HRCW_MASTER 0x0cb23645 */
/* This value should actually be situated in the first 256 bytes of the FLASH
/* This value should actually be situated in the first 256 bytes of the FLASH
which on the standard MPC8266ADS board is at address 0xFF800000
The linker script places it at 0xFFF00000 instead.
@ -395,8 +409,7 @@
- Rune
*/
/* #define CFG_HRCW_MASTER 0x0cb23645 */
*/
/* no slaves */
#define CFG_HRCW_SLAVE1 0
@ -436,7 +449,24 @@
#endif
#define CFG_HID0_INIT 0
/*-----------------------------------------------------------------------
* HIDx - Hardware Implementation-dependent Registers 2-11
*-----------------------------------------------------------------------
* HID0 also contains cache control - initially enable both caches and
* invalidate contents, then the final state leaves only the instruction
* cache enabled. Note that Power-On and Hard reset invalidate the caches,
* but Soft reset does not.
*
* HID1 has only read-only information - nothing to set.
*/
/*#define CFG_HID0_INIT 0 */
#define CFG_HID0_INIT (HID0_ICE |\
HID0_DCE |\
HID0_ICFI |\
HID0_DCI |\
HID0_IFEM |\
HID0_ABE)
#define CFG_HID0_FINAL (HID0_ICE | HID0_IFEM | HID0_ABE )
#define CFG_HID2 0
@ -519,7 +549,7 @@
#define CFG_PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */
#define CFG_PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */
#define CPU_PCI_MEMIO_START PCI_MSTR_MEMIO_LOCAL
#define CFG_CPU_PCI_MEMIO_START PCI_MSTR_MEMIO_LOCAL
#define CFG_PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */
#define CFG_POCMR1_MASK_ATTRIB (POCMR_MASK_512MB | POCMR_ENABLE)
@ -530,7 +560,7 @@
*/
#define CFG_PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
#define CFG_PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
#define CFG_PCI_MSTR_IO_BUS 0xF4000000 /* PCI base */
#define CFG_CPU_PCI_IO_START PCI_MSTR_IO_LOCAL
#define CFG_PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
#define CFG_POCMR2_MASK_ATTRIB (POCMR_MASK_64MB | POCMR_ENABLE | POCMR_PCI_IO)

View file

@ -143,11 +143,52 @@
#define CFG_DISCOVER_PHY
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_EEPROM | CFG_CMD_DATE)
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \
CFG_CMD_EEPROM | \
CFG_CMD_NAND | \
CFG_CMD_DATE)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
/* NAND flash support */
#define CONFIG_MTD_NAND_ECC_JFFS2
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* DFBUSY is available on Port C, bit 12; 0 if busy */
#define NAND_WAIT_READY(nand) \
while (!(((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat & 0x0008));
#define WRITE_NAND_COMMAND(d, adr) WRITE_NAND((d), (adr))
#define WRITE_NAND_ADDRESS(d, adr) WRITE_NAND((d), (adr))
#define WRITE_NAND(d, adr) \
do { (*(volatile uint8_t *)(adr) = (uint8_t)(d)); } while (0)
#define READ_NAND(adr) (*(volatile uint8_t *)(adr))
#define CLE_LO 0x01 /* 0 selects CLE mode (CLE high) */
#define ALE_LO 0x02 /* 0 selects ALE mode (ALE high) */
#define CE_LO 0x04 /* 1 selects chip (CE low) */
#define nand_setcr(cr, val) do {*(volatile uint8_t*)(cr) = (val);} while (0)
#define NAND_DISABLE_CE(nand) \
nand_setcr((nand)->IO_ADDR + 1, ALE_LO | CLE_LO)
#define NAND_ENABLE_CE(nand) \
nand_setcr((nand)->IO_ADDR + 1, CE_LO | ALE_LO | CLE_LO)
#define NAND_CTL_CLRALE(nandptr) \
nand_setcr((nandptr) + 1, CE_LO | ALE_LO | CLE_LO)
#define NAND_CTL_SETALE(nandptr) \
nand_setcr((nandptr) + 1, CE_LO | CLE_LO)
#define NAND_CTL_CLRCLE(nandptr) \
nand_setcr((nandptr) + 1, CE_LO | ALE_LO | CLE_LO)
#define NAND_CTL_SETCLE(nandptr) \
nand_setcr((nandptr) + 1, CE_LO | ALE_LO)
/*
* Miscellaneous configurable options
*/
@ -329,7 +370,7 @@
* These preliminary values are also the final values.
*/
#define CFG_OR_TIMING_FPGA \
(OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
(OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | OR_SCY_4_CLK | OR_EHTR | OR_TRLX)
#define CFG_BR1_PRELIM ((CFG_FPGA_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
#define CFG_OR1_PRELIM (((-CFG_FPGA_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_FPGA)
@ -338,7 +379,7 @@
* These preliminary values are also the final values.
*/
#define CFG_OR_TIMING_DFLASH \
(OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
(OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_2_CLK | OR_EHTR | OR_TRLX)
#define CFG_BR4_PRELIM ((CFG_DFLASH_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
#define CFG_OR4_PRELIM (((-CFG_DFLASH_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_DFLASH)

View file

@ -34,6 +34,8 @@
*/
#define CONFIG_X86 1 /* This is a X86 CPU */
#define CONFIG_SC520 1 /* Include support for AMD SC520 */
#define CONFIG_ALI152X 1 /* Include support for Ali 152x SIO */
#define CFG_SDRAM_PRECHARGE_DELAY 6 /* 6T */
#define CFG_SDRAM_REFRESH_RATE 78 /* 7.8uS (choices are 7.8, 15.6, 31.2 or 62.5uS) */
@ -63,16 +65,9 @@
#define CONFIG_MALLOC_SIZE (CFG_ENV_SIZE + 128*1024)
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CFG_ENV_IS_NOWHERE 1
#undef CFG_ENV_IS_IN_FLASH
#undef CFG_ENV_IS_IN_NVRAM
#undef CFG_ENV_IS_INEEPROM
#define CONFIG_BAUDRATE 9600
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_JFFS2 | CFG_CMD_IDE | CFG_CMD_NET)
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_JFFS2 | CFG_CMD_IDE | CFG_CMD_NET | CFG_CMD_EEPROM)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
@ -86,8 +81,6 @@
#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */
#endif
#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */
#define CFG_JFFS2_NUM_BANKS 1 /* */
/*
* Miscellaneous configurable options
@ -104,7 +97,7 @@
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0x38000000 /* default load address */
#define CFG_LOAD_ADDR 0x100000 /* default load address */
#define CFG_HZ 1024 /* incrementer freq: 1kHz */
@ -117,27 +110,37 @@
*/
#define CONFIG_NR_DRAM_BANKS 4 /* we have 4 banks of DRAM */
#define PHYS_FLASH_1 0x38000000 /* Flash Bank #1 */
#define PHYS_FLASH_SIZE 0x00800000 /* 8 MB */
#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_MAX_FLASH_BANKS 3 /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 64 /* max number of sectors on one chip */
/* 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
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x7a0000) /* Addr of Environment Sector */
#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */
#define CONFIG_SPI_EEPROM /* Support for SPI EEPROMs (AT25128) */
#define CONFIG_MW_EEPROM /* Support for MicroWire EEPROMs (AT93LC46) */
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
/* Environment in EEPROM */
#define CFG_ENV_IS_IN_EEPROM 1
#define CONFIG_SPI
#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment EEPROM 16k is SPI is used or 128 bytes if MW is used*/
#define CFG_ENV_OFFSET 0
#define CONFIG_SC520_CDP_USE_SPI /* Store configuration in the SPI part */
#undef CONFIG_SC520_CDP_USE_MW /* Store configuration in the MicroWire part */
#define CONFIG_SPI_X 1
#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */
#define CFG_JFFS2_NUM_BANKS 1 /* */
/*-----------------------------------------------------------------------
* Device drivers
*/
@ -146,19 +149,20 @@
#define CONFIG_PCNET_79C973
#define CONFIG_PCNET_79C975
#define PCNET_HAS_PROM 1
/************************************************************
* IDE/ATA stuff
************************************************************/
#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */
#define CFG_IDE_MAXBUS 1 /* max. 2 IDE busses */
#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
#define CFG_ATA_IDE0_OFFSET 0x01F0 /* ide0 offste */
#define CFG_ATA_IDE1_OFFSET 0x0170 /* ide1 offset */
//#define CFG_ATA_IDE1_OFFSET 0x0170 /* ide1 offset */
#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */
#define CFG_ATA_REG_OFFSET 0 /* reg offset */
#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */
#define CFG_ATA_BASE_ADDR 0
#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */
#undef CONFIG_IDE_LED /* no led for ide supported */
#undef CONFIG_IDE_RESET /* reset for ide unsupported... */
#undef CONFIG_IDE_RESET_ROUTINE /* no special reset function */
@ -176,23 +180,13 @@
#define CONFIG_ISO_PARTITION /* Experimental */
/************************************************************
* Keyboard support
* Video/Keyboard support
************************************************************/
#define CONFIG_ISA_KEYBOARD
#define CONFIG_VIDEO /* To enable video controller support */
#define CONFIG_I8042_KBD
#define CFG_ISA_IO 0
#if 0
/************************************************************
* Video support
************************************************************/
#define CONFIG_VIDEO /*To enable video controller support */
#define CONFIG_VIDEO_CT69000
#define CONFIG_CFB_CONSOLE
#define CONFIG_VIDEO_LOGO
#define CONFIG_CONSOLE_EXTRA_INFO
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VIDEO_ONBOARD /* Video controller is on-board */
#endif
/************************************************************
* RTC
@ -207,4 +201,10 @@
#define CONFIG_PCI_PNP /* pci plug-and-play */
#define CONFIG_PCI_SCAN_SHOW
#define CFG_FIRST_PCI_IRQ 10
#define CFG_SECOND_PCI_IRQ 9
#define CFG_THIRD_PCI_IRQ 11
#define CFG_FORTH_PCI_IRQ 15
#endif /* __CONFIG_H */

View file

@ -0,0 +1,212 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
*
* 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
*/
/*
* board/config.h - configuration options, board specific
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_X86 1 /* This is a X86 CPU */
#define CONFIG_SC520 1 /* Include support for AMD SC520 */
#define CFG_SDRAM_PRECHARGE_DELAY 6 /* 6T */
#define CFG_SDRAM_REFRESH_RATE 78 /* 7.8uS (choices are 7.8, 15.6, 31.2 or 62.5uS) */
#define CFG_SDRAM_RAS_CAS_DELAY 3 /* 3T */
/* define at most one of these */
#undef CFG_SDRAM_CAS_LATENCY_2T
#define CFG_SDRAM_CAS_LATENCY_3T
#define CFG_SC520_HIGH_SPEED 0 /* 100 or 133MHz */
#define CFG_RESET_GENERIC 1 /* use tripple-fault to reset cpu */
#undef CFG_RESET_SC520 /* use SC520 MMCR's to reset cpu */
#undef CFG_TIMER_SC520 /* use SC520 swtimers */
#define CFG_TIMER_GENERIC 1 /* use the i8254 PIT timers */
#undef CFG_TIMER_TSC /* use the Pentium TSC timers */
#define CFG_STACK_SIZE 0x8000 /* Size of bootloader stack */
#define CONFIG_SHOW_BOOT_PROGRESS 1
#define CONFIG_LAST_STAGE_INIT 1
/*
* Size of malloc() pool
*/
#define CONFIG_MALLOC_SIZE (CFG_ENV_SIZE + 128*1024)
#define CONFIG_BAUDRATE 9600
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_JFFS2 | CFG_CMD_IDE | CFG_CMD_NET | CFG_CMD_PCMCIA | CFG_CMD_EEPROM)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define CONFIG_BOOTDELAY 15
#define CONFIG_BOOTARGS "root=/dev/mtdblock1 console=ttyS0,9600 mtdparts=phys:7936k(root),256k(uboot) "
#define CONFIG_BOOTCOMMAND "setenv bootargs root=/dev/nfs ip=autoconf console=ttyS0,9600 mtdparts=phys:7808k(root),128k(env),256k(uboot); bootp; bootm"
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "boot > " /* 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_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x00100000 /* memtest works on */
#define CFG_MEMTEST_END 0x01000000 /* 1 ... 16 MB in DRAM */
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0x100000 /* default load address */
#define CFG_HZ 1024 /* incrementer freq: 1kHz */
/* valid baudrates */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 4 /* we have 4 banks of DRAM */
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 512 /* max number of sectors on one chip */
/* 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 CONFIG_SPI_EEPROM /* SPI EEPROMs such as AT25010 or AT25640 */
#define CONFIG_MW_EEPROM /* MicroWire EEPROMS such as AT93LC46 */
#define CONFIG_DS1722 /* Dallas DS1722 SPI Temperature probe */
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#if 0
/* Environment in flash */
#define CFG_ENV_IS_IN_FLASH 1
# define CFG_ENV_ADDR (0x387a0000) /* Addr of Environment Sector */
# define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector (or 0x10000) */
# define CFG_ENV_OFFSET 0
#else
/* Environment in EEPROM */
# define CFG_ENV_IS_IN_EEPROM 1
# define CONFIG_SPI
# define CONFIG_SPI_X 1
# define CFG_ENV_SIZE 0x2000 /* Total Size of Environment EEPROM */
# define CFG_ENV_OFFSET 0x1c00
#endif
#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */
#define CFG_JFFS2_NUM_BANKS 1 /* */
/*-----------------------------------------------------------------------
* Device drivers
*/
#define CONFIG_NET_MULTI /* Multi ethernet cards support */
#define CONFIG_EEPRO100
/************************************************************
* IDE/ATA stuff
************************************************************/
#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */
#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
#define CFG_ATA_BASE_ADDR 0
#define CFG_ATA_IDE0_OFFSET 0x01f0 /* ide0 offset */
#define CFG_ATA_IDE1_OFFSET 0xe000 /* ide1 offset */
#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */
#define CFG_ATA_REG_OFFSET 0 /* reg offset */
#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */
#define CFG_FISRT_PCMCIA_BUS 1
#undef CONFIG_IDE_LED /* no led for ide supported */
#undef CONFIG_IDE_RESET /* reset for ide unsupported... */
#undef CONFIG_IDE_RESET_ROUTINE /* no special reset function */
#define CONFIG_IDE_TI_CARDBUS
#define CFG_PCMCIA_CIS_WIN 0x27f00000
#define CFG_PCMCIA_CIS_WIN_SIZE 0x00100000
#define CFG_PCMCIA_IO_WIN 0xe000
#define CFG_PCMCIA_IO_WIN_SIZE 16
/************************************************************
* DISK Partition support
************************************************************/
#define CONFIG_DOS_PARTITION
#define CONFIG_MAC_PARTITION
#define CONFIG_ISO_PARTITION /* Experimental */
/************************************************************
* RTC
***********************************************************/
#define CONFIG_RTC_MC146818
#undef CONFIG_WATCHDOG /* watchdog disabled */
/*
* PCI stuff
*/
#define CONFIG_PCI /* include pci support */
#define CONFIG_PCI_PNP /* pci plug-and-play */
#define CONFIG_PCI_SCAN_SHOW
#define CFG_FIRST_PCI_IRQ 9
#define CFG_SECOND_PCI_IRQ 10
#define CFG_THIRD_PCI_IRQ 11
#define CFG_FORTH_PCI_IRQ 12
#endif /* __CONFIG_H */

View file

@ -0,0 +1,32 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
*
* 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 _outer_config
#define _outer_config
#include "sc520_spunk.h"
#undef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND "fsload boot/vmlinuz ; bootm"
#endif

View file

@ -51,16 +51,39 @@
#define CONFIG_UTX8245 1
#define DEBUG 1
#define CONFIG_IDENT_STRING " [UTX5] "
#define CONFIG_CONS_INDEX 1
#define CONFIG_BAUDRATE 57600
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
#define CONFIG_BOOTDELAY 5
#define CONFIG_BOOTDELAY 2
#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n"
#define CONFIG_BOOTCOMMAND "bootm FF920000 FF800000" /* autoboot command */
#define CONFIG_BOOTCOMMAND "run nfsboot" /* autoboot command */
#define CONFIG_BOOTARGS "root=/dev/ram console=ttyS0,57600" /* RAMdisk */
#define CONFIG_ETHADDR 41:52:4c:61:00:01 /* MAC address */
#define CONFIG_SERVERIP 10.8.17.105
#define CONFIG_ETHADDR 00:AA:00:14:00:05 /* UTX5 */
#define CONFIG_SERVERIP 10.8.17.105 /* Spree */
#define CFG_TFTP_LOADADDR 10000
#define CONFIG_EXTRA_ENV_SETTINGS \
"kernel_addr=FFA00000\0" \
"ramdisk_addr=FF800000\0" \
"u-boot_startaddr=FFB00000\0" \
"u-boot_endaddr=FFB2FFFF\0" \
"nfsargs=setenv bootargs console=ttyS0,$(baudrate) root=/dev/nfs rw \
nfsroot=$(nfsrootip):$(rootpath) ip=dhcp\0" \
"ramargs=setenv bootargs console=ttyS0,$(baudrate) root=/dev/ram0\0" \
"smargs=setenv bootargs console=ttyS0,$(baudrate) root=/dev/mtdblock1 ro\0" \
"fwargs=setenv bootargs console=ttyS0,$(baudrate) root=/dev/sda2 ro\0" \
"nfsboot=run nfsargs;bootm $(kernel_addr)\0" \
"ramboot=run ramargs;bootm $(kernel_addr) $(ramdisk_addr)\0" \
"smboot=run smargs;bootm $(kernel_addr) $(ramdisk_addr)\0" \
"fwboot=run fwargs;bootm $(kernel_addr) $(ramdisk_addr)\0" \
"update_u-boot=tftp $(loadaddr) /bdi2000/u-boot.bin;protect off \
$(u-boot_startaddr) $(u-boot_endaddr);era $(u-boot_startaddr) \
$(u-boot_endaddr);cp.b $(loadaddr) $(u-boot_startaddr) $(filesize);\
protect on $(u-boot_startaddr) $(u-boot_endaddr)"
#define CONFIG_ENV_OVERWRITE
#define CONFIG_COMMANDS (CFG_CMD_DFL | CFG_CMD_BDI | CFG_CMD_PCI \
@ -70,7 +93,8 @@
| CFG_CMD_IMI | CFG_CMD_CACHE \
| CFG_CMD_RUN | CFG_CMD_ECHO \
| CFG_CMD_REGINFO | CFG_CMD_NET\
| CFG_CMD_DHCP)
| CFG_CMD_DHCP | CFG_CMD_I2C \
| CFG_CMD_DATE)
/* This must be included AFTER the definition of CONFIG_COMMANDS (if any)
*/
@ -80,9 +104,9 @@
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
/* Print Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
@ -101,12 +125,20 @@
#define CONFIG_PCI_SCAN_SHOW
#define CONFIG_NET_MULTI
#define CONFIG_EEPRO100
#define CONFIG_EEPRO100_SROM_WRITE
#define PCI_ENET0_IOADDR 0x80000000
#define PCI_ENET0_IOADDR 0xF0000000
#define PCI_ENET0_MEMADDR 0xF0000000
#define PCI_FIREWIRE_IOADDR 0xF1000000
#define PCI_FIREWIRE_MEMADDR 0xF1000000
/*
#define PCI_ENET0_IOADDR 0xFE000000
#define PCI_ENET0_MEMADDR 0x80000000
#define PCI_FIREWIRE_IOADDR 0x81000000
#define PCI_FIREWIRE_MEMADDR 0x81000000
*/
/*-----------------------------------------------------------------------
* Start addresses for the final memory configuration
@ -114,12 +146,13 @@
* Please note that CFG_SDRAM_BASE _must_ start at 0
*/
#define CFG_SDRAM_BASE 0x00000000
#define CFG_MAX_RAM_SIZE 0x10000000 /* amount of SDRAM */
#define CFG_MAX_RAM_SIZE 0x10000000 /* 256MB */
/*#define CFG_VERY_BIG_RAM 1 */
/* even though FLASHP_BASE is FF800000, with 2MB on RCS0, the
* reset vector is actually located at FF800100, but the 8245
* takes care of us.
/* FLASH_BASE is FF800000, with 4MB on RCS0, but the reset vector
* is actually located at FFF00100. Therefore, U-Boot is
* physically located at 0xFFB0_0000, but is also mirrored at
* 0xFFF0_0000.
*/
#define CFG_RESET_ADDRESS 0xFFF00100
@ -132,17 +165,19 @@
/*#define CFG_DRAM_TEST 1 */
#define CFG_MEMTEST_START 0x00003000 /* memtest works on 0...256 MB */
#define CFG_MEMTEST_END 0x0ff8ffa8 /* in SDRAM, skips exception */
#define CFG_MEMTEST_END 0x0ff8ffa7 /* in SDRAM, skips exception */
/* vectors and U-Boot */
/*--------------------------------------------------------------------
* Definitions for initial stack pointer and data area
*------------------------------------------------------------------*/
#define CFG_GBL_DATA_SIZE 128 /* Size in bytes reserved for */
#define CFG_INIT_DATA_SIZE 128 /* Size in bytes reserved for */
/* initial data */
#define CFG_INIT_RAM_ADDR 0x40000000
#define CFG_INIT_RAM_END 0x1000
#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
#define CFG_GBL_DATA_SIZE 128
#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
/*--------------------------------------------------------------------
@ -153,10 +188,16 @@
#define CFG_NS16550_REG_SIZE 1
#define CFG_NS16550_CLK get_bus_freq(0)
#if (CONFIG_CONS_INDEX == 1 || CONFIG_CONS_INDEX == 2)
# define CFG_NS16550_CLK get_bus_freq(0)
#else
# define CFG_NS16550_CLK 33000000
#endif
#define CFG_NS16550_COM1 (CFG_EUMB_ADDR + 0x4500)
#define CFG_NS16550_COM2 (CFG_EUMB_ADDR + 0x4600)
#define CFG_NS16550_COM3 0xFF000000
#define CFG_NS16550_COM4 0xFF000008
/*--------------------------------------------------------------------
* Low Level Configuration Settings
@ -168,46 +209,61 @@
#define CONFIG_SYS_CLK_FREQ 33000000
#define CFG_HZ 1000
#define CFG_ETH_DEV_FN 0x7800
#define CFG_ETH_IOBASE 0x00104000
/*#define CFG_ETH_DEV_FN 0x7800 */
/*#define CFG_ETH_IOBASE 0x00104000 */
/*--------------------------------------------------------------------
* I2C Configuration
*------------------------------------------------------------------*/
#if 1
#define CONFIG_HARD_I2C 1 /* To enable I2C support */
#undef CONFIG_SOFT_I2C /* I2C bit-banged */
#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */
#define CFG_I2C_SLAVE 0x7F
#endif
#define CONFIG_RTC_PCF8563 1 /* enable I2C support for */
/* Philips PCF8563 RTC */
#define CFG_I2C_RTC_ADDR 0x51 /* Philips PCF8563 RTC address */
/*--------------------------------------------------------------------
* Memory Control Configuration Register values
* - see sec. 4.12 of MPC8245 UM
*------------------------------------------------------------------*/
/* MCCR1 */
/**** MCCR1 ****/
#define CFG_ROMNAL 0
#define CFG_ROMFAL 2 /* (tacc=70ns)*mem_freq - 2 */
#define CFG_BANK0_ROW 2 /* SDRAM bank 7-0 row address */
#define CFG_BANK1_ROW 2 /* bit count */
#define CFG_BANK2_ROW 0
#define CFG_BANK3_ROW 0
#define CFG_BANK4_ROW 0
#define CFG_BANK5_ROW 0
#define CFG_BANK6_ROW 0
#define CFG_BANK7_ROW 0
#define CFG_ROMFAL 10 /* (tacc=70ns)*mem_freq - 2,
mem_freq = 100MHz */
/* MCCR2, refresh interval clock cycles */
#define CFG_BANK7_ROW 0 /* SDRAM bank 7-0 row address */
#define CFG_BANK6_ROW 0 /* bit count */
#define CFG_BANK5_ROW 0
#define CFG_BANK4_ROW 0
#define CFG_BANK3_ROW 0
#define CFG_BANK2_ROW 0
#define CFG_BANK1_ROW 2
#define CFG_BANK0_ROW 2
/**** MCCR2, refresh interval clock cycles ****/
#define CFG_REFINT 480 /* 33 MHz SDRAM clock was 480 */
/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4 */
/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. */
#define CFG_BSTOPRE 1023 /* burst to precharge[0..9], */
/* sets open page interval */
/* MCCR3 */
#define CFG_REFREC 5 /* Refresh to activate interval, trc */
/**** MCCR3 ****/
#define CFG_REFREC 7 /* Refresh to activate interval, trc */
/* MCCR4 */
/**** MCCR4 ****/
#define CFG_PRETOACT 2 /* trp */
#define CFG_ACTTOPRE 7 /* trcd + (burst length - 1) + tdrl */
#define CFG_ACTTOPRE 7 /* trcd + (burst length - 1) + trdl */
#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latancy */
#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type, sequential */
#define CFG_ACTORW 2 /* trcd min */
#define CFG_DBUS_SIZE2 1 /* set for 8-bit RCS1, clear for 32,64 */
#define CFG_REGISTERD_TYPE_BUFFER 1
#define CFG_EXTROM 1
#define CFG_EXTROM 0 /* we don't need extended ROM space */
#define CFG_REGDIMM 0
/* calculate according to formula in sec. 6-22 of 8245 UM */
@ -216,10 +272,18 @@
/* was 45 */
#define CFG_SDRAM_DSCD 0x20 /* SDRAM data in sample clock delay - note */
/* bottom 3 bits MUST be 0 */
/* bits 7,6, and 3-0 MUST be 0 */
#if 0
#define CFG_DLL_MAX_DELAY 0x04
#else
#define CFG_DLL_MAX_DELAY 0
#endif
#if 0 /* need for 33MHz SDRAM */
#define CFG_DLL_EXTEND 0x80
#else
#define CFG_DLL_EXTEND 0
#endif
#define CFG_PCI_HOLD_DEL 0x20
@ -255,29 +319,34 @@
#define CFG_BANK7_END 0x3fffffff
#define CFG_BANK7_ENABLE 0
/*--------------------------------------------------------------------
* 4.4 - Output Driver Control Register
*------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* 4.4 - Output Driver Control Register */
/*--------------------------------------------------------------------*/
#define CFG_ODCR 0xe5
/*--------------------------------------------------------------------
* 4.8 - Error Handling Registers
*------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* 4.8 - Error Handling Registers */
/*-------------------------------CFG_SDMODE_BURSTLEN-------------------------------------*/
#define CFG_ERRENR1 0x11 /* enable SDRAM refresh overflow error */
/* SDRAM 0-256 MB */
#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
/*#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_CACHEINHIBIT) */
#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
/* stack in dcache */
#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE)
#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP)
/* PCI memory */
#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
/* Flash, config addrs, etc. */
#define CFG_IBAT2L (CFG_SDRAM_BASE + 0x10000000 | BATL_PP_10 | BATL_MEMCOHERENCE)
#define CFG_IBAT2U (CFG_SDRAM_BASE + 0x10000000| BATU_BL_256M | BATU_VS | BATU_VP)
/* PCI memory */
/*#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) */
/*#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) */
/*Flash, config addrs, etc. */
#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
@ -298,27 +367,31 @@
#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
/*-----------------------------------------------------------------------
* FLASH organization (AMD AM29LV116D)
*/
* FLASH organization
*----------------------------------------------------------------------*/
#define CFG_FLASH_BASE 0xFF800000
#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
/* NOTE: environment is not EMBEDDED in the u-boot code.
It's stored in flash in its own separate sector. */
#define CFG_ENV_IS_IN_FLASH 1
#if 1 /* AMD AM29LV033C */
#define CFG_MAX_FLASH_SECT 64 /* Max number of sectors in one bank */
#define CFG_ENV_ADDR 0xFFBF0000 /* flash sector SA63 */
#define CFG_ENV_SECT_SIZE (64*1024) /* Size of the Environment Sector */
#else /* AMD AM29LV116D */
#define CFG_MAX_FLASH_SECT 35 /* Max number of sectors in one bank */
#define CFG_ENV_ADDR 0xFF9FA000 /* flash sector SA33 */
#define CFG_ENV_SECT_SIZE (8*1024) /* Size of the Environment Sector */
#endif /* #if */
#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* Size of the Environment */
#define CFG_ENV_OFFSET 0 /* starting right at the beginning */
#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
/* Warning: environment is not EMBEDDED in the U-Boot code.
* It's stored in flash separately.
*/
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_ADDR 0xFF9FA000 /* flash sector SA33 */
#define CFG_ENV_SIZE 0x2000 /* Size of the Environment */
#define CFG_ENV_OFFSET 0 /* starting right at the beginning */
#define CFG_ENV_SECT_SIZE 0x2000 /* Size of the Environment Sector */
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
#undef CFG_RAMBOOT
#else

View file

@ -134,6 +134,7 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot);
#define AMD_ID_F016D 0xAD /* 29F016 ID ( 2 M x 8) */
#define AMD_ID_F032B 0x41 /* 29F032 ID ( 4 M x 8) */
#define AMD_ID_LV116DT 0xC7 /* 29LV116DT ( 2 M x 8, top boot sect) */
#define AMD_ID_LV016B 0xc8 /* 29LV016 ID ( 2 M x 8) */
#define AMD_ID_LV400T 0x22B922B9 /* 29LV400T ID ( 4 M, top boot sector) */
#define AMD_ID_LV400B 0x22BA22BA /* 29LV400B ID ( 4 M, bottom boot sect) */

View file

@ -26,6 +26,13 @@
#ifndef _I8042_H_
#define _I8042_H_
#ifdef __I386__
#include <common.h>
#include <asm/io.h>
#define in8(p) inb(p)
#define out8(p,v) outb(v,p)
#endif
/* defines */
#define I8042_DATA_REG (CFG_ISA_IO + 0x0060) /* keyboard i/o buffer */

View file

@ -114,8 +114,6 @@ struct nand_chip {
unsigned long mfr; /* Flash IDs - only one type of flash per device */
unsigned long id;
char* name;
struct NFTLrecord nftl;
int nftl_found;
int numchips;
char page256;
char pageadrlen;
@ -195,4 +193,6 @@ struct nand_flash_dev {
#define NAND_JFFS2_OOB8_FSDALEN 2
#define NAND_JFFS2_OOB16_FSDALEN 8
void nand_probe(unsigned long physadr);
#endif /* __LINUX_MTD_NAND_H */

View file

@ -37,6 +37,7 @@ static struct nand_flash_dev nand_flash_ids[] = {
{"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},
{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},
{"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},
{"Toshiba TH58100FT", NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000},
{"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},
{"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},

View file

@ -462,6 +462,8 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index);
extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
extern pci_dev_t pci_find_class(int wanted_class, int wanted_sub_code,
int wanted_prog_if, int index);
extern int pci_hose_config_device(struct pci_controller *hose,
pci_dev_t dev,

View file

@ -25,11 +25,11 @@ include $(TOPDIR)/config.mk
LIB = lib$(ARCH).a
AOBJS = bios.o realmode_switch.o ic/sc520_asm.o
AOBJS = bios.o bios_pci.o realmode_switch.o
COBJS = board.o bios_setup.o i386_linux.o zimage.o realmode.o \
pci_type1.o ic/sc520.o ic/ali512x.o
pci_type1.o pci.o video_bios.o video.o
OBJS = $(AOBJS) $(COBJS)
$(LIB): .depend $(OBJS)

View file

@ -30,6 +30,8 @@
*----------------------------------------------------------------------
*/
#include "bios.h"
/*
* During it's initialization phase, before switching to protected
* mode, the Linux Kernel makes a few BIOS calls. This won't work
@ -40,29 +42,13 @@
* a general purpose replacement for a real BIOS !!
*/
#define OFFS_ES 0
#define OFFS_GS 2
#define OFFS_DS 4
#define OFFS_DI 6
#define OFFS_SI 8
#define OFFS_BP 10
#define OFFS_SP 12
#define OFFS_BX 14
#define OFFS_DX 16
#define OFFS_CX 18
#define OFFS_AX 20
#define OFFS_VECTOR 22
#define OFFS_IP 24
#define OFFS_CS 26
#define OFFS_FLAGS 28
#define SEGMENT 0x40
#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */
.section .bios, "ax"
.code16
.org 0
/* a call to f000:0 should warmboot */
jmp realmode_reset
.globl rm_int00
rm_int00:
pushw $0
@ -202,30 +188,23 @@ rm_def_int:
* stack.
*/
any_interrupt16:
pusha /* save general registers */
pushw %ds /* save some segments */
pushw %gs
pushw %es
pushw %ss /* save callers stack segment .. */
popw %gs /* ... in gs */
movw $SEGMENT,%ax /* setup my segments */
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
movw %sp,%bp
movw $STACK,%sp /* setup BIOS stackpointer */
MAKE_BIOS_STACK
gs movw OFFS_VECTOR(%bp), %ax
cmpw $0x10, %ax
je Lint_10h
cmpw $0x11, %ax
je Lint_11h
cmpw $0x12, %ax
je Lint_12h
cmpw $0x13, %ax
je Lint_13h
cmpw $0x15, %ax
je Lint_15h
cmpw $0x16, %ax
je Lint_16h
cmpw $0x1a, %ax
je Lint_1ah
movw $0xffff, %ax
jmp Lout
Lint_10h: /* VGA BIOS services */
@ -234,6 +213,9 @@ Lint_10h: /* VGA BIOS services */
Lint_11h:
call bios_11h
jmp Lout
Lint_12h:
call bios_12h
jmp Lout
Lint_13h: /* BIOS disk services */
call bios_13h
jmp Lout
@ -243,6 +225,9 @@ Lint_15h: /* Misc. BIOS services */
Lint_16h: /* keyboard services */
call bios_16h
jmp Lout
Lint_1ah: /* PCI bios */
call bios_1ah
jmp Lout
Lout:
cmpw $0, %ax
je Lhandeled
@ -256,16 +241,7 @@ Lout:
* we shuls make int 0x10 and int 0x16 work as well))
*/
Lhandeled:
pushw %gs /* restore callers stack segment */
popw %ss
movw %bp,%sp /* restore stackpointer */
popw %es /* restore segment selectors */
popw %gs
popw %ds
popa /* restore GP registers */
RESTORE_CALLERS_STACK
addw $2,%sp /* dump vector number */
iret /* return from interrupt */
@ -309,12 +285,36 @@ gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */
*/
bios_11h:
movw bios_equipment, %ax
cs movw bios_equipment, %ax
gs movw %ax, OFFS_AX(%bp)
xorw %ax, %ax
ret
/*
************************************************************
* BIOS interrupt 12h -- Get Memory Size
************************************************************
*/
bios_12h:
cs movw ram_in_64kb_chunks, %ax
cmpw $0xa, %ax
ja b12_more_than_640k
shlw $6, %ax
jmp b12_return
b12_more_than_640k:
movw $0x280, %ax
b12_return:
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */
gs movw OFFS_FLAGS(%bp), %ax
andw $0xfffe, %ax /* clear carry -- function succeeded */
gs movw %ax, OFFS_FLAGS(%bp)
xorw %ax, %ax
ret
/*
************************************************************
* BIOS interrupt 13h -- Disk services
@ -372,27 +372,28 @@ gs movw %ax, OFFS_FLAGS(%bp)
ret
Lfunc_e801h: /* Get memory size for >64M Configurations */
movw $ram_in_64kb_chunks, %ax
cmpw $256, %ax
ja Lmore_than_16mb
shlw $6, %ax /* multiply by 64 */
gs movw %ax, OFFS_AX(%bp) /* return memory size in 1kb chunks in AX and CX */
cs movw ram_in_64kb_chunks, %ax
cmpw $0x100, %ax
ja e801_more_than_16mb
shlw $6, %ax /* multiply by 64 */
subw $0x400, %ax /* 1st meg does not count */
gs movw %ax, OFFS_AX(%bp) /* return memory size between 1M and 16M in 1kb chunks in AX and CX */
gs movw %ax, OFFS_CX(%bp)
xorw %ax, %ax
gs movw %ax, OFFS_BX(%bp) /* set BX and DX to 0*/
gs movw %ax, OFFS_DX(%bp)
gs movw $0, OFFS_BX(%bp) /* set BX and DX to 0*/
gs movw $0, OFFS_DX(%bp)
gs movw OFFS_FLAGS(%bp), %ax
andw $0xfffe, %ax /* clear carry -- function succeeded */
gs movw %ax, OFFS_FLAGS(%bp)
xorw %ax, %ax
ret
Lmore_than_16mb:
e801_more_than_16mb:
subw $0x100, %ax /* subtract 16MB */
gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-384k) in AX and CX */
gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-1MB) in AX and CX */
gs movw $0x3c00, OFFS_CX(%bp)
gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks - 256 */
gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks above 16MB */
gs movw %ax, OFFS_DX(%bp)
gs movw OFFS_FLAGS(%bp), %ax
@ -402,11 +403,15 @@ gs movw %ax, OFFS_FLAGS(%bp)
ret
Lfunc_88h:
movw ram_in_64kb_chunks, %ax
subw $16, %ax
cs movw ram_in_64kb_chunks, %ax
cmpw $0x100, %ax
jna b88_not_more_than16
movw $0x100, %ax
b88_not_more_than16:
shlw $6, %ax
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */
subw $0x400, %ax /* 1st meg does not count */
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes between 16MB and 16MB in ax */
gs movw OFFS_FLAGS(%bp), %ax
andw $0xfffe, %ax /* clear carry -- function succeeded */
@ -432,6 +437,22 @@ Lfunc_03h:
xorw %ax, %ax /* do nothing -- function not supported */
ret
/*
************************************************************
* BIOS interrupt 1ah -- PCI bios
************************************************************
*/
bios_1ah:
gs movw OFFS_AX(%bp), %ax
cmpb $0xb1, %ah
je Lfunc_b1h
movw $0xffff, %ax
ret
Lfunc_b1h:
call realmode_pci_bios
xorw %ax, %ax /* do nothing -- function not supported */
ret
.globl ram_in_64kb_chunks
ram_in_64kb_chunks:

94
lib_i386/bios.h Normal file
View file

@ -0,0 +1,94 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* 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 _BIOS_H_
#define _BIOS_H_
#define OFFS_ES 0 /* 16bit */
#define OFFS_GS 2 /* 16bit */
#define OFFS_DS 4 /* 16bit */
#define OFFS_EDI 6 /* 32bit */
#define OFFS_DI 6 /* low 16 bits of EDI */
#define OFFS_ESI 10 /* 32bit */
#define OFFS_SI 10 /* low 16 bits of ESI */
#define OFFS_EBP 14 /* 32bit */
#define OFFS_BP 14 /* low 16 bits of EBP */
#define OFFS_ESP 18 /* 32bit */
#define OFFS_SP 18 /* low 16 bits of ESP */
#define OFFS_EBX 22 /* 32bit */
#define OFFS_BX 22 /* low 16 bits of EBX */
#define OFFS_BL 22 /* low 8 bits of BX */
#define OFFS_BH 23 /* high 8 bits of BX */
#define OFFS_EDX 26 /* 32bit */
#define OFFS_DX 26 /* low 16 bits of EBX */
#define OFFS_DL 26 /* low 8 bits of BX */
#define OFFS_DH 27 /* high 8 bits of BX */
#define OFFS_ECX 30 /* 32bit */
#define OFFS_CX 30 /* low 16 bits of EBX */
#define OFFS_CL 30 /* low 8 bits of BX */
#define OFFS_CH 31 /* high 8 bits of BX */
#define OFFS_EAX 34 /* 32bit */
#define OFFS_AX 34 /* low 16 bits of EBX */
#define OFFS_AL 34 /* low 8 bits of BX */
#define OFFS_AH 35 /* high 8 bits of BX */
#define OFFS_VECTOR 38 /* 16bit */
#define OFFS_IP 40 /* 16bit */
#define OFFS_CS 42 /* 16bit */
#define OFFS_FLAGS 44 /* 16bit */
#define SEGMENT 0x40
#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */
/* save general registers */
/* save some segments */
/* save callers stack segment .. */
/* ... in gs */
/* setup my segments */
/* setup BIOS stackpointer */
#define MAKE_BIOS_STACK \
pushal ; \
pushw %ds ; \
pushw %gs ; \
pushw %es ; \
pushw %ss ; \
popw %gs ; \
movw $SEGMENT,%ax ; \
movw %ax,%ds ; \
movw %ax,%es ; \
movw %ax,%ss ; \
movw %sp,%bp ; \
movw $STACK,%sp
#define RESTORE_CALLERS_STACK \
pushw %gs ; /* restore callers stack segment */ \
popw %ss ; \
movw %bp,%sp ; /* restore stackpointer */ \
\
popw %es ; /* restore segment selectors */ \
popw %gs ; \
popw %ds ; \
\
popal /* restore GP registers */
#endif

411
lib_i386/bios_pci.S Normal file
View file

@ -0,0 +1,411 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* 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
*/
/*
* x86 realmode assembly implementation of a PCI BIOS
* for platforms that use one PCI hose and configuration
* access type 1. (The common case for low-end PC's)
*/
#include "bios.h"
#define PCI_BIOS_DEBUG
.section .bios, "ax"
.code16
.globl realmode_pci_bios_call_entry
realmode_pci_bios_call_entry:
MAKE_BIOS_STACK
call realmode_pci_bios
RESTORE_CALLERS_STACK
ret
.globl realmode_pci_bios
realmode_pci_bios:
gs movw OFFS_AX(%bp), %ax
cmpb $1, %al
je pci_bios_present
cmpb $2, %al
je pci_bios_find_device
cmpb $3, %al
je pci_bios_find_class
cmpb $6, %al
je pci_bios_generate_special_cycle
cmpb $8, %al
je pci_bios_read_cfg_byte
cmpb $9, %al
je pci_bios_read_cfg_word
cmpb $10, %al
je pci_bios_read_cfg_dword
cmpb $11, %al
je pci_bios_write_cfg_byte
cmpb $12, %al
je pci_bios_write_cfg_word
cmpb $13, %al
je pci_bios_write_cfg_dword
cmpb $14, %al
je pci_bios_get_irq_routing
cmpb $15, %al
je pci_bios_set_irq
jmp unknown_function
/*****************************************************************************/
pci_bios_present:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_present
#endif
movl $0x20494350, %eax
gs movl %eax, OFFS_EDX(%bp)
movb $0x01, %al
gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
movw $0x0210, %ax /* version 2.10 */
gs movw %ax, OFFS_BX(%bp)
cs movb pci_last_bus, %al /* last bus number */
gs movb %al, OFFS_CL(%bp)
jmp clear_carry
/*****************************************************************************/
/* device 0-31, function 0-7 */
pci_bios_find_device:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_find_device
#endif
gs movw OFFS_CX(%bp), %di
shll $16, %edi
gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
* bits and vendor in lower 16 bits */
gs movw OFFS_SI(%bp), %si
xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
pfd_loop:
xorw %ax, %ax /* dword 0 is vendor/device */
call __pci_bios_select_register
movw $0xcfc, %dx
inl %dx, %eax
cmpl %edi, %eax /* our device ? */
je pfd_found_one
pfd_next_dev:
/* check for multi function devices */
movw %bx, %ax
andw $3, %ax
jnz pfd_function_not_zero
movw $0x000c, %ax
call __pci_bios_select_register
movw $0xcfe, %dx
inb %dx, %al
andb $0x80, %al
jz pfd_not_multi_function
pfd_function_not_zero:
incw %bx /* next function, overflows in to
* device number, then bus number */
jmp pfd_check_bus
pfd_not_multi_function:
andw $0xfff8, %bx /* remove function bits */
addw $0x0008, %bx /* next device, overflows in to bus number */
pfd_check_bus:
cs movb pci_last_bus, %ah
cmpb %ah, %bh
ja pfd_not_found
jmp pfd_loop
pfd_found_one:
decw %si
js pfd_done
jmp pfd_next_dev
pfd_done:
gs movw %bx, OFFS_BX(%bp)
jmp clear_carry
pfd_not_found:
movb $0x86, %ah /* device not found */
jmp set_carry
/*****************************************************************************/
pci_bios_find_class:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_find_class
#endif
gs movl OFFS_ECX(%bp), %edi
andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
gs movw OFFS_SI(%bp), %si
xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
pfc_loop:
movw $8, %ax /* dword 8 is class-code high 24bits */
call __pci_bios_select_register
movw $0xcfc, %dx
inl %dx, %eax
shrl $8, %eax
andl $0x00ffffff, %eax
cmpl %edi, %eax /* our device ? */
je pfc_found_one
pfc_next_dev:
/* check for multi function devices */
andw $3, %bx
jnz pfc_function_not_zero
movw $0x000c, %ax
call __pci_bios_select_register
movw $0xcfe, %dx
inb %dx, %al
andb $0x80, %al
jz pfc_not_multi_function
pfc_function_not_zero:
incw %bx /* next function, overflows in to
* device number, then bus number */
jmp pfc_check_bus
pfc_not_multi_function:
andw $0xfff8, %bx /* remove function bits */
addw $0x0008, %bx /* next device, overflows in to bus number */
pfc_check_bus:
cs movb pci_last_bus, %ah
cmpb %ah, %bh
ja pfc_not_found
jmp pfc_loop
pfc_found_one:
decw %si
js pfc_done
jmp pfc_next_dev
pfc_done:
gs movw %bx, OFFS_BX(%bp)
jmp clear_carry
pfc_not_found:
movb $0x86, %ah /* device not found */
jmp set_carry
/*****************************************************************************/
pci_bios_generate_special_cycle:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_generate_special_cycle
#endif
movb $0x81, %ah /* function not supported */
jmp set_carry
/*****************************************************************************/
pci_bios_read_cfg_byte:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_read_cfg_byte
#endif
call pci_bios_select_register
gs movw OFFS_DI(%bp), %dx
andw $3, %dx
addw $0xcfc, %dx
inb %dx, %al
gs movb %al, OFFS_CL(%bp)
jmp clear_carry
/*****************************************************************************/
pci_bios_read_cfg_word:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_read_cfg_word
#endif
call pci_bios_select_register
gs movw OFFS_DI(%bp), %dx
andw $2, %dx
addw $0xcfc, %dx
inw %dx, %ax
gs movw %ax, OFFS_CX(%bp)
jmp clear_carry
/*****************************************************************************/
pci_bios_read_cfg_dword:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_read_cfg_dword
#endif
call pci_bios_select_register
movw $0xcfc, %dx
inl %dx, %eax
gs movl %eax, OFFS_ECX(%bp)
jmp clear_carry
/*****************************************************************************/
pci_bios_write_cfg_byte:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_write_cfg_byte
#endif
call pci_bios_select_register
gs movw OFFS_DI(%bp), %dx
gs movb OFFS_CL(%bp), %al
andw $3, %dx
addw $0xcfc, %dx
outb %al, %dx
jmp clear_carry
/*****************************************************************************/
pci_bios_write_cfg_word:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_write_cfg_word
#endif
call pci_bios_select_register
gs movw OFFS_DI(%bp), %dx
gs movw OFFS_CX(%bp), %ax
andw $2, %dx
addw $0xcfc, %dx
outw %ax, %dx
jmp clear_carry
/*****************************************************************************/
pci_bios_write_cfg_dword:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_write_cfg_dword
#endif
call pci_bios_select_register
gs movl OFFS_ECX(%bp), %eax
movw $0xcfc, %dx
outl %eax, %dx
jmp clear_carry
/*****************************************************************************/
pci_bios_get_irq_routing:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_get_irq_routing
#endif
movb $0x81, %ah /* function not supported */
jmp set_carry
/*****************************************************************************/
pci_bios_set_irq:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_set_irq
#endif
movb $0x81, %ah /* function not supported */
jmp set_carry
/*****************************************************************************/
unknown_function:
#ifdef PCI_BIOS_DEBUG
cs incl num_pci_bios_unknown_function
#endif
movb $0x81, %ah /* function not supported */
jmp set_carry
/*****************************************************************************/
pci_bios_select_register:
gs movw OFFS_BX(%bp), %bx
gs movw OFFS_DI(%bp), %ax
/* destroys eax, dx */
__pci_bios_select_register: /* BX holds device id, AX holds register index */
pushl %ebx
andl $0xfc, %eax
andl $0xffff, %ebx
shll $8, %ebx
orl %ebx, %eax
orl $0x80000000, %eax
movw $0xcf8, %dx
outl %eax, %dx
popl %ebx
ret
clear_carry:
gs movw OFFS_FLAGS(%bp), %ax
andw $0xfffe, %ax /* clear carry -- function succeeded */
gs movw %ax, OFFS_FLAGS(%bp)
xorw %ax, %ax
gs movb %ah, OFFS_AH(%bp)
ret
set_carry:
gs movb %ah, OFFS_AH(%bp)
gs movw OFFS_FLAGS(%bp), %ax
orw $1, %ax /* return carry -- function not supported */
gs movw %ax, OFFS_FLAGS(%bp)
movw $-1, %ax
ret
/*****************************************************************************/
.globl pci_last_bus
pci_last_bus:
.byte 0
#ifdef PCI_BIOS_DEBUG
.globl num_pci_bios_present
num_pci_bios_present:
.long 0
.globl num_pci_bios_find_device
num_pci_bios_find_device:
.long 0
.globl num_pci_bios_find_class
num_pci_bios_find_class:
.long 0
.globl num_pci_bios_generate_special_cycle
num_pci_bios_generate_special_cycle:
.long 0
.globl num_pci_bios_read_cfg_byte
num_pci_bios_read_cfg_byte:
.long 0
.globl num_pci_bios_read_cfg_word
num_pci_bios_read_cfg_word:
.long 0
.globl num_pci_bios_read_cfg_dword
num_pci_bios_read_cfg_dword:
.long 0
.globl num_pci_bios_write_cfg_byte
num_pci_bios_write_cfg_byte:
.long 0
.globl num_pci_bios_write_cfg_word
num_pci_bios_write_cfg_word:
.long 0
.globl num_pci_bios_write_cfg_dword
num_pci_bios_write_cfg_dword:
.long 0
.globl num_pci_bios_get_irq_routing
num_pci_bios_get_irq_routing:
.long 0
.globl num_pci_bios_set_irq
num_pci_bios_set_irq:
.long 0
.globl num_pci_bios_unknown_function
num_pci_bios_unknown_function:
.long 0
#endif

View file

@ -32,6 +32,7 @@
*/
#include <common.h>
#include <pci.h>
#include <asm/realmode.h>
#include <asm/io.h>
@ -42,8 +43,13 @@
#define BIOS_BASE ((char*)0xf0000)
#define BIOS_CS 0xf000
/* these are defined in a 16bit segment and needs
* to be accessed with the RELOC_16_xxxx() macros below
*/
extern u16 ram_in_64kb_chunks;
extern u16 bios_equipment;
extern u8 pci_last_bus;
extern void *rm_int00;
extern void *rm_int01;
extern void *rm_int02;
@ -78,6 +84,34 @@ extern void *rm_int1e;
extern void *rm_int1f;
extern void *rm_def_int;
extern void *realmode_reset;
extern void *realmode_pci_bios_call_entry;
static int set_jmp_vector(int entry_point, void *target)
{
if (entry_point & ~0xffff) {
return -1;
}
if (((u32)target-0xf0000) & ~0xffff) {
return -1;
}
printf("set_jmp_vector: 0xf000:%04x -> %p\n",
entry_point, target);
/* jmp opcode */
writeb(0xea, 0xf0000 + entry_point);
/* offset */
writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1);
/* segment */
writew(0xf000, 0xf0000 + entry_point + 3);
return 0;
}
/*
************************************************************
* Install an interrupt vector
@ -96,11 +130,16 @@ static void setvector(int vector, u16 segment, void *handler)
#endif
}
#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off)
#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off)
#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off)
int bios_setup(void)
{
DECLARE_GLOBAL_DATA_PTR;
static int done=0;
int vector;
struct pci_controller *pri_hose;
if (done) {
return 0;
@ -169,9 +208,26 @@ int bios_setup(void)
setvector(0x1e, BIOS_CS, &rm_int1e);
setvector(0x1f, BIOS_CS, &rm_int1f);
set_jmp_vector(0xfff0, &realmode_reset);
set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry);
/* fill in data area */
ram_in_64kb_chunks = gd->ram_size >> 16;
bios_equipment = 0; /* FixMe */
RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16;
RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */
/* If we assume only one PCI hose, this PCI hose
* will own PCI bus #0, and the last PCI bus of
* that PCI hose will be the last PCI bus in the
* system.
* (This, ofcause break on multi hose systems,
* but our PCI BIOS only support one hose anyway)
*/
pri_hose = pci_bus_to_hose(0);
if (NULL != pri_hose) {
/* fill in last pci bus number for use by the realmode
* PCI BIOS */
RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno;
}
return 0;
}

View file

@ -37,6 +37,7 @@
#include <syscall.h>
#include <net.h>
#include <ide.h>
#include <asm/u-boot-i386.h>
extern long _i386boot_start;
extern long _i386boot_end;
@ -82,21 +83,14 @@ static int mem_malloc_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
#if 1
/* start malloc area right after the stack */
mem_malloc_start = i386boot_bss_start +
i386boot_bss_size + CFG_STACK_SIZE;
mem_malloc_start = (mem_malloc_start+3)&~3;
#else
mem_malloc_start = 0x400000;
#endif
#if 1
/* Use all available RAM for malloc() */
mem_malloc_end = gd->ram_size;
#else
/* Use only CONFIG_MALLOC_SIZE bytes of RAM for malloc() */
mem_malloc_end = mem_malloc_start + CONFIG_MALLOC_SIZE;
#endif
mem_malloc_brk = mem_malloc_start;
return 0;
@ -149,10 +143,10 @@ 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));
char tmp[64]; /* long enough for environment variables */
int i = getenv_r("baudrate", tmp, 64);
gd->baudrate = (i > 0)
gd->baudrate = (i != 0)
? (int) simple_strtoul (tmp, NULL, 10)
: CONFIG_BAUDRATE;
@ -237,6 +231,7 @@ init_fnc_t *init_sequence[] = {
mem_malloc_init, /* dependant on dram_init */
interrupt_init, /* set up exceptions */
timer_init,
serial_init,
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
@ -267,6 +262,7 @@ void start_i386boot (void)
memset (gd->bd, 0, sizeof (bd_t));
show_boot_progress(0x22);
gd->baudrate = CONFIG_BAUDRATE;
for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
show_boot_progress(0xa130|i);
@ -323,7 +319,8 @@ void start_i386boot (void)
/* allocate syscalls table (console_init_r will fill it in */
syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
memset(syscall_tbl, 0, NR_SYSCALLS * sizeof (void *));
/* Initialize the console (after the relocation and devices init) */
console_init_r();
syscalls_init();
@ -355,7 +352,7 @@ void start_i386boot (void)
#endif
/* enable exceptions */
enable_interrupts ();
enable_interrupts();
show_boot_progress(0x28);
/* Must happen after interrupts are initialized since
@ -369,7 +366,7 @@ void start_i386boot (void)
status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
#endif
udelay (20);
udelay(20);
set_timer (0);
@ -399,7 +396,7 @@ void start_i386boot (void)
#if (CONFIG_COMMANDS & CFG_CMD_DOC)
WATCHDOG_RESET();
puts ("DOC: ");
puts("DOC: ");
doc_init();
#endif
@ -428,12 +425,13 @@ void start_i386boot (void)
board_poweroff();
}
#endif
show_boot_progress(0x29);
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
main_loop();
}
/* NOTREACHED - no way out of command loop except booting */

156
lib_i386/pci.c Normal file
View file

@ -0,0 +1,156 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* 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 <pci.h>
#include <asm/io.h>
#include <asm/pci.h>
#ifdef CONFIG_PCI
#undef PCI_ROM_SCAN_VERBOSE
int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
{
struct pci_controller *hose;
int res = -1;
int i;
u32 rom_addr;
u32 addr_reg;
u32 size;
u16 vendor;
u16 device;
u32 class_code;
hose = pci_bus_to_hose(PCI_BUS(dev));
#if 0
printf("pci_shadow_rom() asked to shadow device %x to %x\n",
dev, (u32)dest);
#endif
pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
pci_read_config_word(dev, PCI_DEVICE_ID, &device);
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
class_code &= 0xffffff00;
class_code >>= 8;
#if 0
printf("PCI Header Vendor %04x device %04x class %06x\n",
vendor, device, class_code);
#endif
/* Enable the rom addess decoder */
pci_write_config_dword(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
if (!addr_reg) {
/* register unimplemented */
printf("pci_chadow_rom: device do not seem to have a rom\n");
return -1;
}
size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;
#if 0
printf("ROM is %d bytes\n", size);
#endif
rom_addr = pci_get_rom_window(hose, size);
#if 0
printf("ROM mapped at %x \n", rom_addr);
#endif
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
pci_phys_to_mem(dev, rom_addr)
|PCI_ROM_ADDRESS_ENABLE);
for (i=rom_addr;i<rom_addr+size; i+=512) {
if (readw(i) == 0xaa55) {
u32 pci_data;
#ifdef PCI_ROM_SCAN_VERBOSE
printf("ROM signature found\n");
#endif
pci_data = readw(0x18+i);
pci_data += i;
if (0==memcmp((void*)pci_data, "PCIR", 4)) {
#ifdef PCI_ROM_SCAN_VERBOSE
printf("Fount PCI rom image at offset %d\n", i-rom_addr);
printf("Vendor %04x device %04x class %06x\n",
readw(pci_data+4), readw(pci_data+6),
readl(pci_data+0x0d)&0xffffff);
printf("%s\n",
(readw(pci_data+0x15) &0x80)?
"Last image":"More images follow");
switch (readb(pci_data+0x14)) {
case 0:
printf("X86 code\n");
break;
case 1:
printf("Openfirmware code\n");
break;
case 2:
printf("PARISC code\n");
break;
}
printf("Image size %d\n", readw(pci_data+0x10) * 512);
#endif
/* FixMe: I think we should compare the class code
* bytes as well but I have no reference on the
* exact order of these bytes in the PCI ROM header */
if (readw(pci_data+4) == vendor &&
readw(pci_data+6) == device &&
/* (readl(pci_data+0x0d)&0xffffff) == class_code && */
readb(pci_data+0x14) == 0 /* x86 code image */ ) {
#ifdef PCI_ROM_SCAN_VERBOSE
printf("Suitable ROM image found, copying\n");
#endif
memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
res = 0;
break;
}
if (readw(pci_data+0x15) &0x80) {
break;
}
}
}
}
#ifdef PCI_ROM_SCAN_VERBOSE
if (res) {
printf("No suitable image found\n");
}
#endif
/* disable PAR register and PCI device ROM address devocer */
pci_remove_rom_window(hose, rom_addr);
pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
return res;
}
#endif

View file

@ -33,7 +33,21 @@
extern char realmode_enter;
int realmode_setup(void)
{
/* copy the realmode switch code */
if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
printf("realmode switch too large (%ld bytes, max is %d)\n",
i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
return -1;
}
memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
asm("wbinvd\n");
return 0;
}
int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
{
@ -41,17 +55,11 @@ int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
if (bios_setup()) {
return -1;
}
/* copy the realmode switch code */
if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
printf("realmode switch too large (%ld bytes, max is %d)\n",
i386boot_realmode_size, (int)(REALMODE_MAILBOX-REALMODE_BASE));
if (realmode_setup()) {
return -1;
}
memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
in->eip = off;
in->xcs = seg;
if (3>(in->esp & 0xffff)) {
@ -59,12 +67,30 @@ int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
}
memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
asm("wbinvd\n");
__asm__ volatile (
"lcall $0x20,%0\n" : : "i" (&realmode_enter) );
asm("wbinvd\n");
memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
return out->eax;
}
/* This code is supposed to access a realmode interrupt
* it does currently not work for me */
int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
{
/* place two instructions at 0x700 */
writeb(0xcd, 0x700); /* int $lvl */
writeb(lvl, 0x701);
writeb(0xcb, 0x702); /* lret */
asm("wbinvd\n");
enter_realmode(0x00, 0x700, in, out);
return out->eflags&1;
}

View file

@ -50,7 +50,6 @@
.section .realmode, "ax"
.code16
/* 16bit protected mode code here */
.globl realmode_enter
realmode_enter:

238
lib_i386/video.c Normal file
View file

@ -0,0 +1,238 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* 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 <pci.h>
#include <devices.h>
#include <i8042.h>
#include <asm/ptrace.h>
#include <asm/realmode.h>
#include <asm/io.h>
#include <asm/pci.h>
/* basic textmode I/O from linux kernel */
static char *vidmem = (char *)0xb8000;
static int vidport;
static int lines, cols;
static int orig_x, orig_y;
static void beep(int dur)
{
int i;
outb_p(3, 0x61);
for (i=0;i<10*dur;i++) {
udelay(1000);
}
outb_p(0, 0x61);
}
static void scroll(void)
{
int i;
memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
vidmem[i] = ' ';
}
static void __video_putc(const char c, int *x, int *y)
{
if (c == '\n') {
(*x) = 0;
if ( ++(*y) >= lines ) {
scroll();
(*y)--;
}
} else if (c == '\b') {
if ((*x) != 0) {
--(*x);
vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' ';
}
} else if (c == '\r') {
(*x) = 0;
} else if (c == '\a') {
beep(3);
} else if (c == '\t') {
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
__video_putc(' ', x, y);
} else if (c == '\v') {
switch ((*x) % 8) {
case 0:
__video_putc(' ', x, y);
case 7:
__video_putc(' ', x, y);
case 6:
__video_putc(' ', x, y);
case 5:
__video_putc(' ', x, y);
case 4:
__video_putc(' ', x, y);
case 3:
__video_putc(' ', x, y);
case 2:
__video_putc(' ', x, y);
case 1:
__video_putc(' ', x, y);
}
} else if (c == '\f') {
int i;
for (i=0;i<lines*cols*2;i+=2) {
vidmem[i] = 0;
}
(*x) = 0;
(*y) = 0;
} else {
vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c;
if ( ++(*x) >= cols ) {
(*x) = 0;
if ( ++(*y) >= lines ) {
scroll();
(*y)--;
}
}
}
}
static void video_putc(const char c)
{
int x,y,pos;
x = orig_x;
y = orig_y;
__video_putc(c, &x, &y);
orig_x = x;
orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
}
static void video_puts(const char *s)
{
int x,y,pos;
char c;
x = orig_x;
y = orig_y;
while ( ( c = *s++ ) != '\0' ) {
__video_putc(c, &x, &y);
}
orig_x = x;
orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
}
int video_init(void)
{
u16 pos;
static device_t vga_dev;
static device_t kbd_dev;
vidmem = (char *) 0xb8000;
vidport = 0x3d4;
lines = 25;
cols = 80;
outb_p(14, vidport);
pos = inb_p(vidport+1);
pos <<= 8;
outb_p(15, vidport);
pos |= inb_p(vidport+1);
orig_x = pos%cols;
orig_y = pos/cols;
#if 0
printf("pos %x %d %d\n", pos, orig_x, orig_y);
#endif
if (orig_y > lines) {
orig_x = orig_y =0;
}
memset(&vga_dev, 0, sizeof(vga_dev));
strcpy(vga_dev.name, "vga");
vga_dev.ext = 0;
vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
vga_dev.putc = video_putc; /* 'putc' function */
vga_dev.puts = video_puts; /* 'puts' function */
vga_dev.tstc = NULL; /* 'tstc' function */
vga_dev.getc = NULL; /* 'getc' function */
if (device_register(&vga_dev) == 0) {
return 1;
}
if (i8042_kbd_init()) {
return 1;
}
memset(&kbd_dev, 0, sizeof(kbd_dev));
strcpy(kbd_dev.name, "kbd");
kbd_dev.ext = 0;
kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
kbd_dev.putc = NULL; /* 'putc' function */
kbd_dev.puts = NULL; /* 'puts' function */
kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
kbd_dev.getc = i8042_getc; /* 'getc' function */
if (device_register(&kbd_dev) == 0) {
return 1;
}
return 0;
}
int drv_video_init(void)
{
if (video_bios_init()) {
return 1;
}
return video_init();
}

221
lib_i386/video_bios.c Normal file
View file

@ -0,0 +1,221 @@
/*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
*
* 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 <pci.h>
#include <malloc.h>
#include <asm/ptrace.h>
#include <asm/realmode.h>
#include <asm/io.h>
#include <asm/pci.h>
#undef PCI_BIOS_DEBUG
#undef VGA_BIOS_DEBUG
#ifdef VGA_BIOS_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif
#ifdef CONFIG_PCI
#ifdef PCI_BIOS_DEBUG
#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
extern u32 num_pci_bios_present;
extern u32 num_pci_bios_find_device;
extern u32 num_pci_bios_find_class;
extern u32 num_pci_bios_generate_special_cycle;
extern u32 num_pci_bios_read_cfg_byte;
extern u32 num_pci_bios_read_cfg_word;
extern u32 num_pci_bios_read_cfg_dword;
extern u32 num_pci_bios_write_cfg_byte;
extern u32 num_pci_bios_write_cfg_word;
extern u32 num_pci_bios_write_cfg_dword;
extern u32 num_pci_bios_get_irq_routing;
extern u32 num_pci_bios_set_irq;
extern u32 num_pci_bios_unknown_function;
void print_bios_bios_stat(void)
{
printf("16 bit functions:\n");
printf("pci_bios_present: %d\n", RELOC_16(0xf000, num_pci_bios_present));
printf("pci_bios_find_device: %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
printf("pci_bios_find_class: %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
printf("pci_bios_read_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
printf("pci_bios_read_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
printf("pci_bios_read_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
printf("pci_bios_write_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
printf("pci_bios_write_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
printf("pci_bios_write_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
printf("pci_bios_get_irq_routing: %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
printf("pci_bios_set_irq: %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
printf("pci_bios_unknown_function: %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
}
#endif
#define PCI_CLASS_VIDEO 3
#define PCI_CLASS_VIDEO_STD 0
#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
static u32 probe_pci_video(void)
{
pci_dev_t devbusfn;
if ((devbusfn = pci_find_class(PCI_CLASS_VIDEO,
PCI_CLASS_VIDEO_STD,
PCI_CLASS_VIDEO_PROG_IF_VGA, 0)) != -1) {
u32 old;
u32 addr;
/* PCI video device detected */
printf("Found PCI VGA device at %02x.%02x.%x\n",
PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
/* Enable I/O decoding as well, PCI viudeo boards
* support I/O accesses, but they provide no
* bar register for this since the ports are fixed.
*/
pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
/* Test the ROM decoder, do the device support a rom? */
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
if (!addr) {
printf("PCI VGA have no ROM?\n");
return 0;
}
/* device have a rom */
if (pci_shadow_rom(devbusfn, (void*)0xc0000)) {
printf("Shadowing of PCI VGA BIOS failed\n");
return 0;
}
/* Now enable lagacy VGA port access */
if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
printf("PCI VGA enable failed\n");
return 0;
}
/* return the pci device info, that we'll need later */
return PCI_BUS(devbusfn) << 8 |
PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
}
return 0;
}
#endif
static int probe_isa_video(void)
{
u32 ptr;
char *buf;
if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
return -1;
}
if (NULL == (buf=malloc(0x8000))) {
isa_unmap_rom(ptr);
return -1;
}
if (readw(ptr) != 0xaa55) {
free(buf);
isa_unmap_rom(ptr);
return -1;
}
/* shadow the rom */
memcpy(buf, (void*)ptr, 0x8000);
isa_unmap_rom(ptr);
memcpy((void*)0xc0000, buf, 0x8000);
free(buf);
return 0;
}
int video_bios_init(void)
{
struct pt_regs regs;
/* clear the video bios area in case we warmbooted */
memset((void*)0xc0000, 0, 0x8000);
memset(&regs, 0, sizeof(struct pt_regs));
if (probe_isa_video()) {
/* No ISA board found, try the PCI bus */
regs.eax = probe_pci_video();
}
/* Did we succeed in mapping any video bios */
if (readw(0xc0000) == 0xaa55) {
int size;
int i;
u8 sum;
PRINTF("Found video bios signature\n");
size = 512*readb(0xc0002);
PRINTF("size %d\n", size);
sum=0;
for (i=0;i<size;i++) {
sum += readb(0xc0000 + i);
}
PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
if (sum) {
return 1;
}
/* some video bioses (ATI Mach64) seem to think that
* the original int 10 handler is always at
* 0xf000:0xf065 , place an iret instruction there
*/
writeb(0xcf, 0xff065);
regs.esp = 0x8000;
regs.xss = 0x2000;
enter_realmode(0xc000, 3, &regs, &regs);
PRINTF("INT 0x10 vector after: %04x:%04x\n",
readw(0x42), readw(0x40));
PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
#ifdef PCI_BIOS_DEBUG
print_bios_bios_stat();
#endif
return (regs.eflags & 1);
}
return 1;
}

View file

@ -220,8 +220,8 @@ void boot_zimage(void *setup_base)
memset(&regs, 0, sizeof(struct pt_regs));
regs.xds = (u32)setup_base >> 4;
regs.xss = 0x8e00;
regs.esp = 0x200;
regs.xss = 0x9000;
regs.esp = 0x9000;
regs.eflags = 0;
enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, &regs, &regs);
}

View file

@ -84,11 +84,11 @@ RarpRequest (void)
rarp = (ARP_t *)pkt;
rarp->ar_hrd = ARP_ETHER;
rarp->ar_pro = PROT_IP;
rarp->ar_hrd = htons (ARP_ETHER);
rarp->ar_pro = htons (PROT_IP);
rarp->ar_hln = 6;
rarp->ar_pln = 4;
rarp->ar_op = RARPOP_REQUEST;
rarp->ar_op = htons (RARPOP_REQUEST);
memcpy (&rarp->ar_data[0], NetOurEther, 6); /* source ET addr */
memcpy (&rarp->ar_data[6], &NetOurIP, 4); /* source IP addr */
memcpy (&rarp->ar_data[10], NetOurEther, 6); /* dest ET addr = source ET addr ??*/