From 5b1d713721c3ea02549940133f09236783dda1f9 Mon Sep 17 00:00:00 2001 From: wdenk Date: Sun, 3 Nov 2002 00:07:02 +0000 Subject: Initial revision --- board/RPXClassic/RPXClassic.c | 290 ++++++++++++++++++++++ board/RPXClassic/config.mk | 29 +++ board/RPXClassic/flash.c | 447 +++++++++++++++++++++++++++++++++ board/RPXlite/RPXlite.c | 195 +++++++++++++++ board/iphase4539/flash.c | 490 ++++++++++++++++++++++++++++++++++++ board/sixnet/sixnet.c | 563 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 2014 insertions(+) create mode 100644 board/RPXClassic/RPXClassic.c create mode 100644 board/RPXClassic/config.mk create mode 100644 board/RPXClassic/flash.c create mode 100644 board/RPXlite/RPXlite.c create mode 100644 board/iphase4539/flash.c create mode 100644 board/sixnet/sixnet.c (limited to 'board') diff --git a/board/RPXClassic/RPXClassic.c b/board/RPXClassic/RPXClassic.c new file mode 100644 index 0000000..4d2100b --- /dev/null +++ b/board/RPXClassic/RPXClassic.c @@ -0,0 +1,290 @@ +/* + * (C) Copyright 2001 + * Stäubli Faverges - + * Pierre AUBERT p.aubert@staubli.com + * U-Boot port on RPXClassic LF (CLLF_BW31) board + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); +static unsigned char aschex_to_byte (unsigned char *cp); + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFCC25 + +const uint sdram_table[] = +{ + /* + * Single Read. (Offset 00h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0X0CAFCC04, 0X03AFCC08, + 0x3FBFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Burst Read. (Offset 08h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88, + 0x3FBFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Single Write. (Offset 18h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00, + 0x3FFFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Burst Write. (Offset 20h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC80, 0x03FFCC8C, + 0x0CFFCC00, 0x33FFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, + + /* + * Refresh. (Offset 30h in UPMA RAM) + */ + 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24, + 0x3FFFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Exception. (Offset 3Ch in UPMA RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_ +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: RPXClassic\n"); + return (0); +} + +/*----------------------------------------------------------------------------- + * board_get_enetaddr -- Read the MAC Address in the I2C EEPROM + *----------------------------------------------------------------------------- + */ +void board_get_enetaddr (uchar * enet) +{ + int i; + char buff[256], *cp; + + /* Initialize I2C */ + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + + /* Read 256 bytes in EEPROM */ + i2c_read (0x54, 0, 1, buff, 128); + i2c_read (0x54, 128, 1, buff + 128, 128); + + /* Retrieve MAC address in buffer (key EA) */ + for (cp = buff;;) { + if (cp[0] == 'E' && cp[1] == 'A') { + cp += 3; + /* Read MAC address */ + for (i = 0; i < 6; i++, cp += 2) { + enet[i] = aschex_to_byte (cp); + } + } + /* Scan to the end of the record */ + while ((*cp != '\n') && (*cp != 0xff)) { + cp++; + } + /* If the next character is a \n, 0 or ff, we are done. */ + cp++; + if ((*cp == '\n') || (*cp == 0) || (*cp == 0xff)) + break; + } + +#ifdef CONFIG_FEC_ENET + /* The MAC address is the same as normal ethernet except the 3rd byte */ + /* (See the E.P. Planet Core Overview manual */ + enet[3] |= 0x80; + + /* Validate the fast ethernet tranceiver */ + *((volatile uchar *) BCSR2) &= ~BCSR2_MIICTL; + *((volatile uchar *) BCSR2) &= ~BCSR2_MIIPWRDWN; + *((volatile uchar *) BCSR2) |= BCSR2_MIIRST; + *((volatile uchar *) BCSR2) |= BCSR2_MIIPWRDWN; +#endif + + printf ("MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", + enet[0], enet[1], enet[2], enet[3], enet[4], enet[5]); + +} + +void rpxclassic_init (void) +{ + /* Enable NVRAM */ + *((uchar *) BCSR0) |= BCSR0_ENNVRAM; + +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size10; + + upmconfig (UPMA, (uint *) sdram_table, + sizeof (sdram_table) / sizeof (uint)); + + /* Refresh clock prescalar */ + memctl->memc_mptpr = CFG_MPTPR; + + memctl->memc_mar = 0x00000000; + + /* Map controller banks 1 to the SDRAM bank */ + memctl->memc_or1 = CFG_OR1_PRELIM; + memctl->memc_br1 = CFG_BR1_PRELIM; + + memctl->memc_mamr = CFG_MAMR_10COL & (~(MAMR_PTAE)); /* no refresh yet */ + + udelay (200); + + /* perform SDRAM initializsation sequence */ + + memctl->memc_mcr = 0x80002230; /* SDRAM bank 0 - refresh twice */ + udelay (1); + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay (1000); + + /* Check Bank 0 Memory Size + * try 10 column mode + */ + + size10 = dram_size (CFG_MAMR_10COL, (ulong *) SDRAM_BASE_PRELIM, + SDRAM_MAX_SIZE); + + return (size10); +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ + +static long int dram_size (long int mamr_value, long int *base, long int maxsize) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + memctl->memc_mamr = mamr_value; + + for (cnt = maxsize / sizeof (long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt <= maxsize / sizeof (long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + return (maxsize); +} +static unsigned char aschex_to_byte (unsigned char *cp) +{ + u_char byte, c; + + c = *cp++; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } else { + c -= '0'; + } + + byte = c * 16; + + c = *cp; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } else { + c -= '0'; + } + + byte += c; + + return (byte); +} diff --git a/board/RPXClassic/config.mk b/board/RPXClassic/config.mk new file mode 100644 index 0000000..ae455e1 --- /dev/null +++ b/board/RPXClassic/config.mk @@ -0,0 +1,29 @@ +# +# (C) Copyright 2001 +# Stäubli Faverges - +# Pierre AUBERT p.aubert@staubli.com +# U-Boot port on RPXClassic LF (CLLF_BW31) board +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +TEXT_BASE = 0xff000000 diff --git a/board/RPXClassic/flash.c b/board/RPXClassic/flash.c new file mode 100644 index 0000000..6293497 --- /dev/null +++ b/board/RPXClassic/flash.c @@ -0,0 +1,447 @@ +/* + * (C) Copyright 2001 + * Stäubli Faverges - + * Pierre AUBERT p.aubert@staubli.com + * U-Boot port on RPXClassic LF (CLLF_BW31) board + * + * RPXClassic uses Am29DL323B flash memory with 2 banks + * + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include +#include + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0 ; + int i; + + /* Init: no FLASHes known */ + for (i=0; i= CFG_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + + flash_info[0].size = size_b0; + + return (size_b0); +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x00010000; + info->start[3] = base + 0x00018000; + info->start[4] = base + 0x00020000; + info->start[5] = base + 0x00028000; + info->start[6] = base + 0x00030000; + info->start[7] = base + 0x00038000; + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i-7) * 0x00040000) ; + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AMDL323B: + printf ("AMDL323DB (16 Mbytes, bottom boot sect)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + ulong value; + ulong base = (ulong)addr; + + /* Reset flash componeny */ + addr [0] = 0xf0f0f0f0; + + /* Write auto select command: read Manufacturer ID */ + addr[0xAAA] = 0xAAAAAAAA ; + addr[0x555] = 0x55555555 ; + addr[0xAAA] = 0x90909090 ; + + value = addr[0] ; + + switch (value & 0x00FF00FF) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr[2] ; /* device ID */ + + switch (value & 0x00FF00FF) { + case (AMD_ID_DL323B & 0x00FF00FF): + info->flash_id += FLASH_AMDL323B; + info->sector_count = 71; + info->size = 0x01000000; /* 16 Mb */ + + break; + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + /* set up sector start address table */ + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x00010000; + info->start[3] = base + 0x00018000; + info->start[4] = base + 0x00020000; + info->start[5] = base + 0x00028000; + info->start[6] = base + 0x00030000; + info->start[7] = base + 0x00038000; + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i-7) * 0x00040000) ; + } + + /* check for protected sectors */ + for (i = 0; i < 23; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[4] & 1 ; + } + /* Check for protected sectors in the 2nd bank */ + addr[0x100AAA] = 0xAAAAAAAA ; + addr[0x100555] = 0x55555555 ; + addr[0x100AAA] = 0x90909090 ; + + for (i = 23; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[4] & 1 ; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr = (volatile unsigned long *)info->start[0]; + + *addr = 0xF0F0F0F0; /* reset bank 1 */ + addr = (volatile unsigned long *)info->start[23]; + + *addr = 0xF0F0F0F0; /* reset bank 2 */ + + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + vu_long *addr = (vu_long*)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + 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_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0xAAA] = 0xAAAAAAAA; + addr[0x555] = 0x55555555; + addr[0xAAA] = 0x80808080; + addr[0xAAA] = 0xAAAAAAAA; + addr[0x555] = 0x55555555; + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_long *)(info->start[sect]) ; + addr[0] = 0x30303030 ; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (vu_long *)(info->start[l_sect]); + while ((addr[0] & 0x80808080) != 0x80808080) { + 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 */ + putc ('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ + addr = (vu_long *)info->start[0]; + addr[0] = 0xF0F0F0F0; /* reset bank */ + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, 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; i0; ++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; + } + + /* + * 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); + } + + /* + * 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)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long *)(info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0xAAA] = 0xAAAAAAAA; + addr[0x555] = 0x55555555; + addr[0xAAA] = 0xA0A0A0A0; + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/RPXlite/RPXlite.c b/board/RPXlite/RPXlite.c new file mode 100644 index 0000000..a33357b --- /dev/null +++ b/board/RPXlite/RPXlite.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Yoo. Jonghoon, IPone, yooth@ipone.co.kr + * U-Boot port on RPXlite board + * + * DRAM related UPMA register values are modified. + * See RPXLite engineering note : 50MHz/60ns - UPM RAM WORDS + */ + +#include +#include + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFCC25 + +const uint sdram_table[] = +{ + /* + * Single Read. (Offset 00h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0X0CAFCC04, 0X03AFCC08, + 0x3FBFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Burst Read. (Offset 08h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88, + 0x3FBFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Single Write. (Offset 18h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00, + 0x3FFFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Burst Write. (Offset 20h in UPMA RAM) + */ + 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC80, 0x03FFCC8C, + 0x0CFFCC00, 0x33FFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, + + /* + * Refresh. (Offset 30h in UPMA RAM) + */ + 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24, + 0x3FFFCC27, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* + * Exception. (Offset 3Ch in UPMA RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_ +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: RPXlite\n") ; + return (0) ; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size10 ; + + upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + /* Refresh clock prescalar */ + memctl->memc_mptpr = CFG_MPTPR ; + + memctl->memc_mar = 0x00000000; + + /* Map controller banks 1 to the SDRAM bank */ + memctl->memc_or1 = CFG_OR1_PRELIM; + memctl->memc_br1 = CFG_BR1_PRELIM; + + memctl->memc_mamr = CFG_MAMR_10COL & (~(MAMR_PTAE)); /* no refresh yet */ + + udelay(200); + + /* perform SDRAM initializsation sequence */ + + memctl->memc_mcr = 0x80002230 ; /* SDRAM bank 0 - refresh twice */ + udelay(1); + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay (1000); + + /* Check Bank 0 Memory Size + * try 10 column mode + */ + + size10 = dram_size (CFG_MAMR_10COL, (ulong *)SDRAM_BASE_PRELIM, SDRAM_MAX_SIZE) ; + + return (size10); +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ + +static long int dram_size (long int mamr_value, long int *base, long int maxsize) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + memctl->memc_mamr = mamr_value; + + for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof(long)); + } + } + return (maxsize); +} diff --git a/board/iphase4539/flash.c b/board/iphase4539/flash.c new file mode 100644 index 0000000..401ffbe --- /dev/null +++ b/board/iphase4539/flash.c @@ -0,0 +1,490 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Adapted for Interphase 4539 by Wolfgang Grandegger . + * + * 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 +#include +#include +#include + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +extern int hwc_flash_size(void); +static ulong flash_get_size (u32 addr, flash_info_t *info); +static int flash_get_offsets (u32 base, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_reset (u32 addr); + +#define out8(a,v) *(volatile unsigned char*)(a) = v +#define in8(a) *(volatile unsigned char*)(a) +#define in32(a) *(volatile unsigned long*)(a) +#define iobarrier_rw() eieio() + +unsigned long flash_init (void) +{ + unsigned int i; + unsigned long flash_size = 0; + unsigned long bank_size; + unsigned int bank = 0; + + /* Init: no FLASHes known */ + for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + flash_info[i].sector_count = 0; + flash_info[i].size = 0; + } + + /* Initialise the BOOT Flash */ + if (bank == CFG_MAX_FLASH_BANKS) { + puts ("Warning: not all Flashes are initialised !"); + return flash_size; + } + + bank_size = flash_get_size (CFG_FLASH_BASE, flash_info + bank); + if (bank_size) { +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE && \ + CFG_MONITOR_BASE < CFG_FLASH_BASE + CFG_MAX_FLASH_SIZE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + flash_info + bank); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + flash_info + bank); +#endif + + /* HWC protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE + 0x10000 - 1, + flash_info + bank); + + flash_size += bank_size; + bank++; + } else { + puts ("Warning: the BOOT Flash is not initialised !"); + } + + return flash_size; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (u32 addr, flash_info_t *info) +{ + volatile uchar value; +#if 0 + int i; +#endif + + /* Write auto select command: read Manufacturer ID */ + out8(addr + 0x0555, 0xAA); + iobarrier_rw(); + udelay(10); + out8(addr + 0x02AA, 0x55); + iobarrier_rw(); + udelay(10); + out8(addr + 0x0555, 0x90); + iobarrier_rw(); + udelay(10); + + value = in8(addr); + iobarrier_rw(); + udelay(10); + switch (value | (value << 16)) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + flash_reset (addr); + return 0; + } + + value = in8(addr + 1); /* device ID */ + iobarrier_rw(); + + switch (value) { + case AMD_ID_LV033C: + info->flash_id += FLASH_AM033C; + info->size = hwc_flash_size(); + if (info->size > CFG_MAX_FLASH_SIZE) { + printf("U-Boot supports only %d MB\n", + CFG_MAX_FLASH_SIZE); + info->size = CFG_MAX_FLASH_SIZE; + } + info->sector_count = info->size / 0x10000; + break; /* => 4 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + flash_reset (addr); + return (0); /* => no or unknown flash */ + + } + + if (!flash_get_offsets (addr, info)) { + flash_reset (addr); + return 0; + } + +#if 0 + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + value = in8(info->start[i] + 2); + iobarrier_rw(); + info->protect[i] = (value & 1) != 0; + } +#endif + + /* + * Reset bank to read mode + */ + flash_reset (addr); + + return (info->size); +} + +static int flash_get_offsets (u32 base, flash_info_t *info) +{ + unsigned int i, size; + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM033C: + /* set sector offsets for uniform sector type */ + size = info->size / info->sector_count; + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + i * size; + } + break; + default: + return 0; + } + + return 1; +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile u32 addr = info->start[0]; + int flag, prot, sect, l_sect; + ulong start, now, last; + + 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_AMD_COMP) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0x80); + iobarrier_rw(); + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = info->start[sect]; + out8(addr, 0x30); + iobarrier_rw(); + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = info->start[l_sect]; + while ((in8(addr) & 0x80) != 0x80) { + 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 */ + putc ('.'); + last = now; + } + iobarrier_rw(); + } + +DONE: + /* reset to read mode */ + flash_reset (info->start[0]); + + printf (" done\n"); + return 0; +} + +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, 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; i0; ++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; + } + + /* + * 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); + } + + /* + * 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)); +} + +/* + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile u32 addr = info->start[0]; + ulong start; + int flag, i; + + /* Check if Flash is (sufficiently) erased */ + if ((in32(dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* first, perform an unlock bypass command to speed up flash writes */ + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0x20); + iobarrier_rw(); + + /* write each byte out */ + for (i = 0; i < 4; i++) { + char *data_ch = (char *)&data; + out8(addr, 0xA0); + iobarrier_rw(); + out8(dest+i, data_ch[i]); + iobarrier_rw(); + udelay(10); /* XXX */ + } + + /* we're done, now do an unlock bypass reset */ + out8(addr, 0x90); + iobarrier_rw(); + out8(addr, 0x00); + iobarrier_rw(); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((in32(dest) & 0x80808080) != (data & 0x80808080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + iobarrier_rw(); + } + + flash_reset (addr); + + return (0); +} + +/* + * Reset bank to read mode + */ +static void flash_reset (u32 addr) +{ + out8(addr, 0xF0); /* reset bank */ + iobarrier_rw(); +} + +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM033C: printf ("AM29LV033C (32 Mbit, uniform sectors)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + if (info->size % 0x100000 == 0) { + printf (" Size: %ld MB in %d Sectors\n", + info->size / 0x100000, info->sector_count); + } + else if (info->size % 0x400 == 0) { + printf (" Size: %ld KB in %d Sectors\n", + info->size / 0x400, info->sector_count); + } + else { + printf (" Size: %ld B in %d Sectors\n", + info->size, info->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); +} diff --git a/board/sixnet/sixnet.c b/board/sixnet/sixnet.c new file mode 100644 index 0000000..c65e809 --- /dev/null +++ b/board/sixnet/sixnet.c @@ -0,0 +1,563 @@ +/* + * (C) Copyright 2001, 2002 + * Dave Ellis, SIXNET, dge@sixnetio.com. + * Based on code by: + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * and other contributors to U-Boot. 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 +#include +#include +#include /* for eth_init() */ +#include +#include "sixnet.h" + +#define ORMASK(size) ((-size) & OR_AM_MSK) + +static long ram_size(ulong *, long); + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + * returns 0 if recognized, -1 if unknown + */ + +int checkboard (void) +{ + puts ("Board: SIXNET SXNI855T\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +#error "SXNI855T has no PCMCIA port" +#endif /* CFG_CMD_PCMCIA */ + +/* ------------------------------------------------------------------------- */ + +#define _not_used_ 0xffffffff + +/* UPMB table for dual UART. */ + +/* this table is for 50MHz operation, it should work at all lower speeds */ +const uint duart_table[] = +{ + /* single read. (offset 0 in upm RAM) */ + 0xfffffc04, 0x0ffffc04, 0x0ff3fc04, 0x0ff3fc04, + 0x0ff3fc00, 0x0ff3fc04, 0xfffffc04, 0xfffffc05, + + /* burst read. (offset 8 in upm RAM) */ + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* single write. (offset 18 in upm RAM) */ + 0xfffffc04, 0x0ffffc04, 0x00fffc04, 0x00fffc04, + 0x00fffc04, 0x00fffc00, 0xfffffc04, 0xfffffc05, + + /* burst write. (offset 20 in upm RAM) */ + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* refresh. (offset 30 in upm RAM) */ + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* exception. (offset 3c in upm RAM) */ + _not_used_, _not_used_, _not_used_, _not_used_, +}; + +/* Load FPGA very early in boot sequence, since it must be + * loaded before the 16C2550 serial channels can be used as + * console channels. + * + * Note: Much of the configuration is not complete. The + * stack is in DPRAM since SDRAM has not been initialized, + * so the stack must be kept small. Global variables + * are still in FLASH, so they cannot be written. + * Only the FLASH, DPRAM, immap and FPGA can be addressed, + * the other chip selects may not have been initialized. + * The clocks have been initialized, so udelay() can be + * used. + */ +#define FPGA_DONE 0x0080 /* PA8, input, high when FPGA load complete */ +#define FPGA_PROGRAM_L 0x0040 /* PA9, output, low to reset, high to start */ +#define FPGA_INIT_L 0x0020 /* PA10, input, low indicates not ready */ +#define fpga (*(volatile unsigned char *)(CFG_FPGA_PROG)) /* FPGA port */ + +int board_postclk_init (void) +{ + + /* the data to load to the XCSxxXL FPGA */ + static const unsigned char fpgadata[] = { +# include "fpgadata.c" + }; + + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; +#define porta (immap->im_ioport.iop_padat) + const unsigned char* pdata; + + /* /INITFPGA and DONEFPGA signals are inputs */ + immap->im_ioport.iop_padir &= ~(FPGA_INIT_L | FPGA_DONE); + + /* Force output pin to begin at 0, /PROGRAM asserted (0) resets FPGA */ + porta &= ~FPGA_PROGRAM_L; + + /* Set FPGA as an output */ + immap->im_ioport.iop_padir |= FPGA_PROGRAM_L; + + /* delay a little to make sure FPGA sees it, really + * only need less than a microsecond. + */ + udelay(10); + + /* unassert /PROGRAM */ + porta |= FPGA_PROGRAM_L; + + /* delay while FPGA does last erase, indicated by + * /INITFPGA going high. This should happen within a + * few milliseconds. + */ + /* ### FIXME - a timeout check would be good, maybe flash + * the status LED to indicate the error? + */ + while ((porta & FPGA_INIT_L) == 0) + ; /* waiting */ + + /* write program data to FPGA at the programming address + * so extra /CS1 strobes at end of configuration don't actually + * write to any registers. + */ + fpga = 0xff; /* first write is ignored */ + fpga = 0xff; /* fill byte */ + fpga = 0xff; /* fill byte */ + fpga = 0x4f; /* preamble code */ + fpga = 0x80; fpga = 0xaf; fpga = 0x9b; /* length (ignored) */ + fpga = 0x4b; /* field check code */ + + pdata = fpgadata; + /* while no error write out each of the 28 byte frames */ + while ((porta & (FPGA_INIT_L | FPGA_DONE)) == FPGA_INIT_L + && pdata < fpgadata + sizeof(fpgadata)) { + + fpga = 0x4f; /* preamble code */ + + /* 21 bytes of data in a frame */ + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); fpga = *(pdata++); + fpga = *(pdata++); + + fpga = 0x4b; /* field check code */ + fpga = 0xff; /* extended write cycle */ + fpga = 0x4b; /* extended write cycle + * (actually 0x4b from bitgen.exe) + */ + fpga = 0xff; /* extended write cycle */ + fpga = 0xff; /* extended write cycle */ + fpga = 0xff; /* extended write cycle */ + } + + fpga = 0xff; /* startup byte */ + fpga = 0xff; /* startup byte */ + fpga = 0xff; /* startup byte */ + fpga = 0xff; /* startup byte */ + +#if 0 /* ### FIXME */ + /* If didn't load all the data or FPGA_DONE is low the load failed. + * Maybe someday stop here and flash the status LED? The console + * is not configured, so can't print an error message. Can't write + * global variables to set a flag (except gd?). + * For now it must work. + */ +#endif + + /* Now that the FPGA is loaded, set up the Dual UART chip + * selects. Must be done here since it may be used as the console. + */ + upmconfig(UPMB, (uint *)duart_table, sizeof(duart_table)/sizeof(uint)); + + memctl->memc_mbmr = DUART_MBMR; + memctl->memc_or5 = DUART_OR_VALUE; + memctl->memc_br5 = DUART_BR5_VALUE; + memctl->memc_or6 = DUART_OR_VALUE; + memctl->memc_br6 = DUART_BR6_VALUE; + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +/* base address for SRAM, assume 32-bit port, valid */ +#define NVRAM_BR_VALUE (CFG_SRAM_BASE | BR_PS_32 | BR_V) + +/* up to 64MB - will be adjusted for actual size */ +#define NVRAM_OR_PRELIM (ORMASK(CFG_SRAM_SIZE) \ + | OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_EHTR) +/* + * Miscellaneous platform dependent initializations after running in RAM. + */ + +int misc_init_r (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + bd_t *bd = gd->bd; + + memctl->memc_or2 = NVRAM_OR_PRELIM; + memctl->memc_br2 = NVRAM_BR_VALUE; + + /* Is there any SRAM? Is it 16 or 32 bits wide? */ + + /* First look for 32-bit SRAM */ + bd->bi_sramsize = ram_size((ulong*)CFG_SRAM_BASE, CFG_SRAM_SIZE); + + if (bd->bi_sramsize == 0) { + /* no 32-bit SRAM, but there could be 16-bit SRAM since + * it would report size 0 when configured for 32-bit bus. + * Try again with a 16-bit bus. + */ + memctl->memc_br2 |= BR_PS_16; + bd->bi_sramsize = ram_size((ulong*)CFG_SRAM_BASE, CFG_SRAM_SIZE); + } + + if (bd->bi_sramsize == 0) { + memctl->memc_br2 = 0; /* disable select since nothing there */ + } + else { + /* adjust or2 for actual size of SRAM */ + memctl->memc_or2 |= ORMASK(bd->bi_sramsize); + bd->bi_sramstart = CFG_SRAM_BASE; + printf("SRAM: %lu KB\n", bd->bi_sramsize >> 10); + } + + + /* set standard MPC8xx clock so kernel will see the time + * even if it doesn't have a DS1306 clock driver. + * This helps with experimenting with standard kernels. + */ + { + ulong tim; + struct rtc_time tmp; + + rtc_get(&tmp); /* get time from DS1306 RTC */ + + /* convert to seconds since 1970 */ + tim = mktime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, + tmp.tm_hour, tmp.tm_min, tmp.tm_sec); + + immap->im_sitk.sitk_rtck = KAPWR_KEY; + immap->im_sit.sit_rtc = tim; + } + +#if 0 + /* The code below is no longer valid since the prototype of + * eth_init() and eth_halt() have been changed to support + * multi-ethernet feature in U-Boot; the eth_initialize() + * routine should be called before any access to the ethernet + * callbacks. + */ + + /* FIXME - for now init ethernet to force PHY special mode */ + eth_init(bd); + eth_halt(); +#endif + return (0); +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. + * + * The memory size MUST be a power of 2 for this to work. + * + * The only memory modified is 4 bytes at offset 0. This is important + * since for the SRAM this location is reserved for autosizing, so if + * it is modified and the board is reset before ram_size() completes + * no damage is done. Normally even the memory at 0 is preserved. The + * higher SRAM addresses may contain battery backed RAM disk data which + * must never be corrupted. + */ + +static long ram_size(ulong *base, long maxsize) +{ + volatile long *test_addr; + volatile long *base_addr = base; + volatile long *flash = (volatile long*)CFG_FLASH_BASE; + ulong ofs; /* byte offset from base_addr */ + ulong save; /* to make test non-destructive */ + ulong junk; + long ramsize = -1; /* size not determined yet */ + + save = *base_addr; /* save value at 0 so can restore */ + + /* is any SRAM present? */ + *base_addr = 0x5555aaaa; + + /* use flash read to modify data bus, since with no SRAM present + * the data bus may retain the value if our code is running + * completely in the cache. + */ + junk = *flash; + + if (*base_addr != 0x5555aaaa) + ramsize = 0; /* no RAM present, or defective */ + else { + *base_addr = 0xaaaa5555; + junk = *flash; /* use flash read to modify data bus */ + if (*base_addr != 0xaaaa5555) + ramsize = 0; /* no RAM present, or defective */ + } + + /* now size it if any is present */ + for (ofs = 4; ofs < maxsize && ramsize < 0; ofs <<= 1) { + test_addr = (long*)((long)base_addr + ofs); /* location to test */ + + *base_addr = ~*test_addr; + if (*base_addr == *test_addr) + ramsize = ofs; /* wrapped back to 0, so this is the size */ + } + + *base_addr = save; /* restore value at 0 */ + return (ramsize); +} + +/* ------------------------------------------------------------------------- */ +/* sdram table based on the FADS manual */ +/* for chip MB811171622A-100 */ + +/* this table is for 50MHz operation, it should work at all lower speeds */ + +const uint sdram_table[] = +{ + /* single read. (offset 0 in upm RAM) */ + 0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00, + 0x1ff77c47, + + /* precharge and Mode Register Set initialization (offset 5). + * This is also entered at offset 6 to do Mode Register Set + * without the precharge. + */ + 0x1ff77c34, 0xefeabc34, 0x1fb57c35, + + /* burst read. (offset 8 in upm RAM) */ + 0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00, + 0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* single write. (offset 18 in upm RAM) */ + /* FADS had 0x1f27fc04, ... + * but most other boards have 0x1f07fc04, which + * sets GPL0 from A11MPC to 0 1/4 clock earlier, + * like the single read. + * This seems better so I am going with the change. + */ + 0x1f07fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* burst write. (offset 20 in upm RAM) */ + 0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00, + 0xf0affc00, 0xe1bbbc04, 0x1ff77c47, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* refresh. (offset 30 in upm RAM) */ + 0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04, + 0xfffffc84, 0xfffffc07, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* exception. (offset 3c in upm RAM) */ + 0x7ffffc07, _not_used_, _not_used_, _not_used_ }; + +/* ------------------------------------------------------------------------- */ + +#define SDRAM_MAX_SIZE 0x10000000 /* max 256 MB SDRAM */ + +/* precharge and set Mode Register */ +#define SDRAM_MCR_PRE (MCR_OP_RUN | MCR_UPM_A | /* select UPM */ \ + MCR_MB_CS3 | /* chip select */ \ + MCR_MLCF(1) | MCR_MAD(5)) /* 1 time at 0x05 */ + +/* set Mode Register, no precharge */ +#define SDRAM_MCR_MRS (MCR_OP_RUN | MCR_UPM_A | /* select UPM */ \ + MCR_MB_CS3 | /* chip select */ \ + MCR_MLCF(1) | MCR_MAD(6)) /* 1 time at 0x06 */ + +/* runs refresh loop twice so get 8 refresh cycles */ +#define SDRAM_MCR_REFR (MCR_OP_RUN | MCR_UPM_A | /* select UPM */ \ + MCR_MB_CS3 | /* chip select */ \ + MCR_MLCF(2) | MCR_MAD(0x30)) /* twice at 0x30 */ + +/* MAMR values work in either mamr or mbmr */ +/* 8 column SDRAM */ +#define SDRAM_MAMR_8COL /* refresh at 50MHz */ \ + ((195 << MAMR_PTA_SHIFT) | MAMR_PTAE \ + | MAMR_AMA_TYPE_0 /* Address MUX 0 */ \ + | MAMR_DSA_1_CYCL /* 1 cycle disable */ \ + | MAMR_G0CLA_A11 /* GPL0 A11[MPC] */ \ + | MAMR_RLFA_1X /* Read loop 1 time */ \ + | MAMR_WLFA_1X /* Write loop 1 time */ \ + | MAMR_TLFA_4X) /* Timer loop 4 times */ + +/* 9 column SDRAM */ +#define SDRAM_MAMR_9COL ((SDRAM_MAMR_8COL & (~MAMR_G0CLA_A11)) | MAMR_G0CLA_A10) + +/* base address 0, 32-bit port, SDRAM UPM, valid */ +#define SDRAM_BR_VALUE (BR_PS_32 | BR_MS_UPMA | BR_V) + +/* up to 256MB, SAM, G5LS - will be adjusted for actual size */ +#define SDRAM_OR_PRELIM (ORMASK(SDRAM_MAX_SIZE) | OR_CSNT_SAM | OR_G5LS) + +/* This is the Mode Select Register value for the SDRAM. + * Burst length: 4 + * Burst Type: sequential + * CAS Latency: 2 + * Write Burst Length: burst + */ +#define SDRAM_MODE 0x22 /* CAS latency 2, burst length 4 */ + +/* ------------------------------------------------------------------------- */ + +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + uint size_sdram = 0; + uint size_sdram9 = 0; + uint base = 0; /* SDRAM must start at 0 */ + int i; + + upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + /* Configure the refresh (mostly). This needs to be + * based upon processor clock speed and optimized to provide + * the highest level of performance. + * + * Preliminary prescaler for refresh. + * This value is selected for four cycles in 31.2 us, + * which gives 8192 cycles in 64 milliseconds. + * This may be too fast, but works for any memory. + * It is adjusted to 4096 cycles in 64 milliseconds if + * possible once we know what memory we have. + * + * We have to be careful changing UPM registers after we + * ask it to run these commands. + * + * PTA - periodic timer period for our design is + * 50 MHz x 31.2us + * --------------- = 195 + * 1 x 8 x 1 + * + * 50MHz clock + * 31.2us refresh interval + * SCCR[DFBRG] 0 + * PTP divide by 8 + * 1 chip select + */ + memctl->memc_mptpr = MPTPR_PTP_DIV8; /* 0x0800 */ + memctl->memc_mamr = SDRAM_MAMR_8COL & (~MAMR_PTAE); /* no refresh yet */ + + /* The SDRAM Mode Register value is shifted left 2 bits since + * A30 and A31 don't connect to the SDRAM for 32-bit wide memory. + */ + memctl->memc_mar = SDRAM_MODE << 2; /* MRS code */ + udelay(200); /* SDRAM needs 200uS before set it up */ + + /* Now run the precharge/nop/mrs commands. */ + memctl->memc_mcr = SDRAM_MCR_PRE; + udelay(2); + + /* Run 8 refresh cycles (2 sets of 4) */ + memctl->memc_mcr = SDRAM_MCR_REFR; /* run refresh twice */ + udelay(2); + + /* some brands want Mode Register set after the refresh + * cycles. This shouldn't hurt anything for the brands + * that were happy with the first time we set it. + */ + memctl->memc_mcr = SDRAM_MCR_MRS; + udelay(2); + + memctl->memc_mamr = SDRAM_MAMR_8COL; /* enable refresh */ + memctl->memc_or3 = SDRAM_OR_PRELIM; + memctl->memc_br3 = SDRAM_BR_VALUE + base; + + /* Some brands need at least 10 DRAM accesses to stabilize. + * It wont hurt the brands that don't. + */ + for (i=0; i<10; ++i) { + volatile ulong *addr = (volatile ulong *)base; + ulong val; + + val = *(addr + i); + *(addr + i) = val; + } + + /* Check SDRAM memory Size in 8 column mode. + * For a 9 column memory we will get half the actual size. + */ + size_sdram = ram_size((ulong *)0, SDRAM_MAX_SIZE); + + /* Check SDRAM memory Size in 9 column mode. + * For an 8 column memory we will see at most 4 megabytes. + */ + memctl->memc_mamr = SDRAM_MAMR_9COL; + size_sdram9 = ram_size((ulong *)0, SDRAM_MAX_SIZE); + + if (size_sdram < size_sdram9) /* leave configuration at 9 columns */ + size_sdram = size_sdram9; + else /* go back to 8 columns */ + memctl->memc_mamr = SDRAM_MAMR_8COL; + + /* adjust or3 for actual size of SDRAM + */ + memctl->memc_or3 |= ORMASK(size_sdram); + + /* Adjust refresh rate depending on SDRAM type. + * For types > 128 MBit (32 Mbyte for 2 x16 devices) leave + * it at the current (fast) rate. + * For 16, 64 and 128 MBit half the rate will do. + */ + if (size_sdram <= 32 * 1024 * 1024) + memctl->memc_mptpr = MPTPR_PTP_DIV16; /* 0x0400 */ + + return (size_sdram); +} + -- cgit v1.1