mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
* 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:
parent
3b57fe0a70
commit
7a8e9bed17
86 changed files with 9858 additions and 3239 deletions
28
CHANGELOG
28
CHANGELOG
|
@ -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
11
MAKEALL
|
@ -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}
|
||||
|
|
15
Makefile
15
Makefile
|
@ -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
|
||||
|
|
|
@ -36,6 +36,3 @@ getline(char *buf,int *num,int max_num)
|
|||
line_pointer = line_pointer + *num;
|
||||
len = len - *num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -22,4 +22,4 @@
|
|||
#
|
||||
|
||||
|
||||
TEXT_BASE = 0x387e0000
|
||||
TEXT_BASE = 0x387c0000
|
||||
|
|
|
@ -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
458
board/sc520_cdp/flash_old.c
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
47
board/sc520_spunk/Makefile
Normal file
47
board/sc520_spunk/Makefile
Normal 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
|
||||
|
||||
#########################################################################
|
25
board/sc520_spunk/config.mk
Normal file
25
board/sc520_spunk/config.mk
Normal 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
813
board/sc520_spunk/flash.c
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
|
686
board/sc520_spunk/sc520_spunk.c
Normal file
686
board/sc520_spunk/sc520_spunk.c
Normal 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);
|
||||
}
|
||||
|
82
board/sc520_spunk/sc520_spunk_asm.S
Normal file
82
board/sc520_spunk/sc520_spunk_asm.S
Normal 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
|
||||
|
84
board/sc520_spunk/sc520_spunk_asm16.S
Normal file
84
board/sc520_spunk/sc520_spunk_asm16.S
Normal 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
|
||||
|
85
board/sc520_spunk/u-boot.lds
Normal file
85
board/sc520_spunk/u-boot.lds
Normal 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
|
@ -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
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
157
common/cmd_portio.c
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
176
doc/README.nand
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
142
drivers/ds1722.c
Normal 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
|
|
@ -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
242
drivers/mw_eeprom.c
Normal 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
668
drivers/ti_pci1410a.c
Normal 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
354
examples/82559_eeprom.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
52
include/cmd_portio.h
Normal 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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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() */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
212
include/configs/sc520_spunk.h
Normal file
212
include/configs/sc520_spunk.h
Normal 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 */
|
32
include/configs/sc520_spunk_rel.h
Normal file
32
include/configs/sc520_spunk_rel.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
135
lib_i386/bios.S
135
lib_i386/bios.S
|
@ -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
94
lib_i386/bios.h
Normal 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
411
lib_i386/bios_pci.S
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
156
lib_i386/pci.c
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
238
lib_i386/video.c
Normal 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
221
lib_i386/video_bios.c
Normal 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(®s, 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, ®s, ®s);
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -220,8 +220,8 @@ void boot_zimage(void *setup_base)
|
|||
|
||||
memset(®s, 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, ®s, ®s);
|
||||
}
|
||||
|
|
|
@ -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 ??*/
|
||||
|
|
Loading…
Reference in a new issue