diff options
Diffstat (limited to 'board')
53 files changed, 15216 insertions, 0 deletions
diff --git a/board/RPXlite/flash.c b/board/RPXlite/flash.c new file mode 100644 index 0000000..78c1838 --- /dev/null +++ b/board/RPXlite/flash.c @@ -0,0 +1,524 @@ +/* + * (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 + * + * Some of flash control words are modified. (from 2x16bit device + * to 4x8bit device) + * RPXLite board I tested has only 4 AM29LV800BB devices. Other devices + * are not tested. + * + * (?) Does an RPXLite board which + * does not use AM29LV800 flash memory exist ? + * I don't know... + */ + +#include <common.h> +#include <mpc8xx.h> + +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) +{ +/* volatile immap_t *immap = (immap_t *)CFG_IMMR; */ +/* volatile memctl8xx_t *memctl = &immap->im_memctl; */ + unsigned long size_b0 ; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ +/* + size_b0 = flash_get_size((vu_long *)FLASH_BASE_DEBUG, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } +*/ + /* Remap FLASH according to real size */ +/*%%% + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000); + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; +%%%*/ + /* Re-do sizing to get full correct info */ + + size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_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; + + /* set up sector start address table */ + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00010000; + info->start[2] = base + 0x00018000; + info->start[3] = base + 0x00020000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + ((i-3) * 0x00040000) ; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00010000; + info->start[i--] = base + info->size - 0x00018000; + info->start[i--] = base + info->size - 0x00020000; + for (; i >= 0; i--) { + info->start[i] = base + i * 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; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\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; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * 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; + + /* Write auto select command: read Manufacturer ID */ + addr[0xAAA] = 0x00AA00AA ; + addr[0x555] = 0x00550055 ; + addr[0xAAA] = 0x00900090 ; + + value = addr[0] ; + + switch (value & 0x00FF00FF) { + 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; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr[2] ; /* device ID */ + + switch (value & 0x00FF00FF) { + case (AMD_ID_LV400T & 0x00FF00FF): + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV400B & 0x00FF00FF): + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV800T & 0x00FF00FF): + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (AMD_ID_LV800B & 0x00FF00FF): + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00400000; /*%%% Size doubled by yooth */ + break; /* => 4 MB */ + + case (AMD_ID_LV160T & 0x00FF00FF): + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (AMD_ID_LV160B & 0x00FF00FF): + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ +#if 0 /* enable when device IDs are available */ + case AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + /*%%% sector start address modified */ + /* set up sector start address table */ + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00010000; + info->start[2] = base + 0x00018000; + info->start[3] = base + 0x00020000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + ((i-3) * 0x00040000) ; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00010000; + info->start[i--] = base + info->size - 0x00018000; + info->start[i--] = base + info->size - 0x00020000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00040000; + } + } + + /* 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 */ + 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 */ + } + + 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; 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; + } + + /* + * 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/cogent/lcd.c b/board/cogent/lcd.c new file mode 100644 index 0000000..941ea65 --- /dev/null +++ b/board/cogent/lcd.c @@ -0,0 +1,231 @@ +/* most of this is taken from the file */ +/* hal/powerpc/cogent/current/src/hal_diag.c in the */ +/* Cygnus eCos source. Here is the copyright notice: */ +/* */ +/*============================================================================= */ +/* */ +/* hal_diag.c */ +/* */ +/* HAL diagnostic output code */ +/* */ +/*============================================================================= */ +/*####COPYRIGHTBEGIN#### */ +/* */ +/* ------------------------------------------- */ +/* The contents of this file are subject to the Cygnus eCos Public License */ +/* Version 1.0 (the "License"); you may not use this file except in */ +/* compliance with the License. You may obtain a copy of the License at */ +/* http://sourceware.cygnus.com/ecos */ +/* */ +/* Software distributed under the License is distributed on an "AS IS" */ +/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the */ +/* License for the specific language governing rights and limitations under */ +/* the License. */ +/* */ +/* The Original Code is eCos - Embedded Cygnus Operating System, released */ +/* September 30, 1998. */ +/* */ +/* The Initial Developer of the Original Code is Cygnus. Portions created */ +/* by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. */ +/* ------------------------------------------- */ +/* */ +/*####COPYRIGHTEND#### */ +/*============================================================================= */ +/*#####DESCRIPTIONBEGIN#### */ +/* */ +/* Author(s): nickg, jskov */ +/* Contributors: nickg, jskov */ +/* Date: 1999-03-23 */ +/* Purpose: HAL diagnostic output */ +/* Description: Implementations of HAL diagnostic output support. */ +/* */ +/*####DESCRIPTIONEND#### */ +/* */ +/*============================================================================= */ + +/*----------------------------------------------------------------------------- */ +/* Cogent board specific LCD code */ + +#include <common.h> +#include <stdarg.h> +#include <board/cogent/lcd.h> + +static char lines[2][LCD_LINE_LENGTH+1]; +static int curline; +static int linepos; +static int heartbeat_active; +/* make the next two strings exactly LCD_LINE_LENGTH (16) chars long */ +/* pad to the right with spaces if necessary */ +static char init_line0[LCD_LINE_LENGTH+1] = "U-Boot Cogent "; +static char init_line1[LCD_LINE_LENGTH+1] = "mjj, 11 Aug 2000"; + +static inline unsigned char +lcd_read_status(cma_mb_lcd *clp) +{ + /* read the Busy Status Register */ + return (cma_mb_reg_read(&clp->lcd_bsr)); +} + +static inline void +lcd_wait_not_busy(cma_mb_lcd *clp) +{ + /* + * wait for not busy + * Note: It seems that the LCD isn't quite ready to process commands + * when it clears the BUSY flag. Reading the status address an extra + * time seems to give it enough breathing room. + */ + + while (lcd_read_status(clp) & LCD_STAT_BUSY) + ; + + (void)lcd_read_status(clp); +} + +static inline void +lcd_write_command(cma_mb_lcd *clp, unsigned char cmd) +{ + lcd_wait_not_busy(clp); + + /* write the Command Register */ + cma_mb_reg_write(&clp->lcd_cmd, cmd); +} + +static inline void +lcd_write_data(cma_mb_lcd *clp, unsigned char data) +{ + lcd_wait_not_busy(clp); + + /* write the Current Character Register */ + cma_mb_reg_write(&clp->lcd_ccr, data); +} + +static inline void +lcd_dis(int addr, char *string) +{ + cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; + int pos, linelen; + + linelen = LCD_LINE_LENGTH; + if (heartbeat_active && addr == LCD_LINE0) + linelen--; + + lcd_write_command(clp, LCD_CMD_ADD + addr); + for (pos = 0; *string != '\0' && pos < linelen; pos++) + lcd_write_data(clp, *string++); +} + +void +lcd_init(void) +{ + cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; + int i; + + /* configure the lcd for 8 bits/char, 2 lines and 5x7 dot matrix */ + lcd_write_command(clp, LCD_CMD_MODE); + + /* turn the LCD display on */ + lcd_write_command(clp, LCD_CMD_DON); + + curline = 0; + linepos = 0; + + for (i = 0; i < LCD_LINE_LENGTH; i++) { + lines[0][i] = init_line0[i]; + lines[1][i] = init_line1[i]; + } + + lines[0][LCD_LINE_LENGTH] = lines[1][LCD_LINE_LENGTH] = 0; + + lcd_dis(LCD_LINE0, lines[0]); + lcd_dis(LCD_LINE1, lines[1]); + + printf("HD44780 2 line x %d char display\n", LCD_LINE_LENGTH); +} + +void +lcd_write_char(const char c) +{ + int i, linelen; + + /* ignore CR */ + if (c == '\r') + return; + + linelen = LCD_LINE_LENGTH; + if (heartbeat_active && curline == 0) + linelen--; + + if (c == '\n') { + lcd_dis(LCD_LINE0, &lines[curline^1][0]); + lcd_dis(LCD_LINE1, &lines[curline][0]); + + /* Do a line feed */ + curline ^= 1; + linelen = LCD_LINE_LENGTH; + if (heartbeat_active && curline == 0) + linelen--; + linepos = 0; + + for (i = 0; i < linelen; i++) + lines[curline][i] = ' '; + + return; + } + + /* Only allow to be output if there is room on the LCD line */ + if (linepos < linelen) + lines[curline][linepos++] = c; +} + +void +lcd_flush(void) +{ + lcd_dis(LCD_LINE1, &lines[curline][0]); +} + +void +lcd_write_string(const char *s) +{ + char *p; + + for (p = (char *)s; *p != '\0'; p++) + lcd_write_char(*p); +} + +void +lcd_printf(const char *fmt, ...) +{ + va_list args; + char buf[CFG_PBSIZE]; + + va_start(args, fmt); + (void)vsprintf(buf, fmt, args); + va_end(args); + + lcd_write_string(buf); +} + +void +lcd_heartbeat(void) +{ + cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; +#if 0 + static char rotchars[] = { '|', '/', '-', '\\' }; +#else + /* HD44780 Rom Code A00 has no backslash */ + static char rotchars[] = { '|', '/', '-', '\315' }; +#endif + static int rotator_index = 0; + + heartbeat_active = 1; + + /* write the address */ + lcd_write_command(clp, LCD_CMD_ADD + LCD_LINE0 + (LCD_LINE_LENGTH - 1)); + + /* write the next char in the sequence */ + lcd_write_data(clp, rotchars[rotator_index]); + + if (++rotator_index >= (sizeof rotchars / sizeof rotchars[0])) + rotator_index = 0; +} diff --git a/board/cogent/lcd.h b/board/cogent/lcd.h new file mode 100644 index 0000000..1056eea --- /dev/null +++ b/board/cogent/lcd.h @@ -0,0 +1,84 @@ +/* most of this is taken from the file */ +/* hal/powerpc/cogent/current/src/hal_diag.c in the */ +/* Cygnus eCos source. Here is the copyright notice: */ +/* */ +/*============================================================================= */ +/* */ +/* hal_diag.c */ +/* */ +/* HAL diagnostic output code */ +/* */ +/*============================================================================= */ +/*####COPYRIGHTBEGIN#### */ +/* */ +/* ------------------------------------------- */ +/* The contents of this file are subject to the Cygnus eCos Public License */ +/* Version 1.0 (the "License"); you may not use this file except in */ +/* compliance with the License. You may obtain a copy of the License at */ +/* http://sourceware.cygnus.com/ecos */ +/* */ +/* Software distributed under the License is distributed on an "AS IS" */ +/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the */ +/* License for the specific language governing rights and limitations under */ +/* the License. */ +/* */ +/* The Original Code is eCos - Embedded Cygnus Operating System, released */ +/* September 30, 1998. */ +/* */ +/* The Initial Developer of the Original Code is Cygnus. Portions created */ +/* by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. */ +/* ------------------------------------------- */ +/* */ +/*####COPYRIGHTEND#### */ +/*============================================================================= */ +/*#####DESCRIPTIONBEGIN#### */ +/* */ +/* Author(s): nickg, jskov */ +/* Contributors: nickg, jskov */ +/* Date: 1999-03-23 */ +/* Purpose: HAL diagnostic output */ +/* Description: Implementations of HAL diagnostic output support. */ +/* */ +/*####DESCRIPTIONEND#### */ +/* */ +/*============================================================================= */ + +/* FEMA 162B 16 character x 2 line LCD */ + +/* status register bit definitions */ +#define LCD_STAT_BUSY 0x80 /* 1 = display busy */ +#define LCD_STAT_ADD 0x7F /* bits 0-6 return current display address */ + +/* command register definitions */ +#define LCD_CMD_RST 0x01 /* clear entire display and reset display addr */ +#define LCD_CMD_HOME 0x02 /* reset display address and reset any shifting */ +#define LCD_CMD_ECL 0x04 /* move cursor left one pos on next data write */ +#define LCD_CMD_ESL 0x05 /* shift display left one pos on next data write */ +#define LCD_CMD_ECR 0x06 /* move cursor right one pos on next data write */ +#define LCD_CMD_ESR 0x07 /* shift disp right one pos on next data write */ +#define LCD_CMD_DOFF 0x08 /* display off, cursor off, blinking off */ +#define LCD_CMD_BL 0x09 /* blink character at current cursor position */ +#define LCD_CMD_CUR 0x0A /* enable cursor on */ +#define LCD_CMD_DON 0x0C /* turn display on */ +#define LCD_CMD_CL 0x10 /* move cursor left one position */ +#define LCD_CMD_SL 0x14 /* shift display left one position */ +#define LCD_CMD_CR 0x18 /* move cursor right one position */ +#define LCD_CMD_SR 0x1C /* shift display right one position */ +#define LCD_CMD_MODE 0x38 /* sets 8 bits, 2 lines, 5x7 characters */ +#define LCD_CMD_ACG 0x40 /* bits 0-5 sets character generator address */ +#define LCD_CMD_ADD 0x80 /* bits 0-6 sets display data addr to line 1 + */ + +/* LCD status values */ +#define LCD_OK 0x00 +#define LCD_ERR 0x01 + +#define LCD_LINE0 0x00 +#define LCD_LINE1 0x40 + +#define LCD_LINE_LENGTH 16 + +extern void lcd_init(void); +extern void lcd_write_char(const char); +extern void lcd_flush(void); +extern void lcd_write_string(const char *); +extern void lcd_printf(const char *, ...); diff --git a/board/cray/L1/flash.c b/board/cray/L1/flash.c new file mode 100644 index 0000000..6d66905 --- /dev/null +++ b/board/cray/L1/flash.c @@ -0,0 +1,471 @@ +/* + * (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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +/* + * Modified July 20, 2001 + * Strip down to support ONLY the AMD29F032B. + * Dave Updegraff - Cray, Inc. dave@cray.com + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +/* The flash chip we use... */ +#define AMD_ID_F032B 0x41 /* 29F032B ID 32 Mbit,64 64Kx8 sectors */ +#define FLASH_AM320B 0x0009 + + +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); + +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned char + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0, size_b1; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + /* Only one bank */ + if (CFG_MAX_FLASH_BANKS == 1) + { + /* Setup offsets */ + flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); + +#if 0 + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE0_PRELIM, + FLASH_BASE0_PRELIM+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + size_b1 = 0 ; + flash_info[0].size = size_b0; + } + + return (size_b0 + size_b1); +} + + + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + 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_AM320B:printf ("AM29F032B (32 Mbit 64x64KB uniform sectors)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) + { + if (*flash++ != 0xffffffff) + { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf ("\n "); + + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + 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; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + + value = addr2[0]; + + switch (value) { + case (FLASH_WORD_SIZE)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 = addr2[1]; /* device ID */ + + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_F032B: + info->flash_id += FLASH_AM320B; + info->sector_count = 64; + info->size = 0x0400000; /* => 4 MB */ + break; + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + /* set up sector start address table */ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + + /* 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 */ + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + info->protect[i] = addr2[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + + return (info->size); +} + +int wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + 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 */ + putc ('.'); + last = now; + } + } + return 0; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + + 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) { + 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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); + printf("Erasing sector %p\n", addr2); + + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + wait_for_DQ7(info, sect); + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* 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; 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; + } + + /* + * 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 FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest; + volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data; + ulong start; + int flag; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *)dest) & + (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] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/cray/L1/init.S b/board/cray/L1/init.S new file mode 100644 index 0000000..acc5205 --- /dev/null +++ b/board/cray/L1/init.S @@ -0,0 +1,147 @@ +/*------------------------------------------------------------------------------+ */ +/* */ +/* This source code has been made available to you by IBM on an AS-IS */ +/* basis. Anyone receiving this source is licensed under IBM */ +/* copyrights to use it in any way he or she deems fit, including */ +/* copying it, modifying it, compiling it, and redistributing it either */ +/* with or without modifications. No license under IBM patents or */ +/* patent applications is to be implied by the copyright license. */ +/* */ +/* Any user of this software should understand that IBM cannot provide */ +/* technical support for this software and will not be responsible for */ +/* any consequences resulting from the use of this software. */ +/* */ +/* Any person who transfers this source code or any derivative work */ +/* must include the IBM copyright notice, this paragraph, and the */ +/* preceding two paragraphs in the transferred software. */ +/* */ +/* COPYRIGHT I B M CORPORATION 1995 */ +/* LICENSED MATERIAL - PROGRAM PROPERTY OF I B M */ +/*------------------------------------------------------------------------------- */ + +/*----------------------------------------------------------------------------- */ +/* Function: ext_bus_cntlr_init */ +/* Description: Initializes the External Bus Controller for the external */ +/* peripherals. IMPORTANT: For pass1 this code must run from */ +/* cache since you can not reliably change a peripheral banks */ +/* timing register (pbxap) while running code from that bank. */ +/* For ex., since we are running from ROM on bank 0, we can NOT */ +/* execute the code that modifies bank 0 timings from ROM, so */ +/* we run it from cache. */ +/* Bank 0 - Flash and SRAM */ +/* Bank 1 - NVRAM/RTC */ +/* Bank 2 - Keyboard/Mouse controller */ +/* Bank 3 - IR controller */ +/* Bank 4 - not used */ +/* Bank 5 - not used */ +/* Bank 6 - not used */ +/* Bank 7 - FPGA registers */ +/*-----------------------------------------------------------------------------#include <config.h> */ +#include <ppc4xx.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +/* CRAY - L1: only nominally a 'walnut', since ext.Bus.Cntlr is all empty */ +/* except for #1 which we use for DMA'ing to IOCA-like things, so the */ +/* control registers to set that up are determined by what we've */ +/* empirically discovered work there. */ + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 10; used to prefetch */ + mtctr r4 /* 10 cache lines to fit this function */ + /* in cache (gives us 8x10=80 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 10 cache lines */ + + /*------------------------------------------------------------------- */ + /* Delay to ensure all accesses to ROM are complete before changing */ + /* bank 0 timings. 200usec should be enough. */ + /* 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles */ + /*------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 /* ensure 200usec have passed since reset */ + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + + /*---------------------------------------------------------------------- */ + /* Peripheral Bank 0 (Flash) initialization */ + /*---------------------------------------------------------------------- */ + /* 0x7F8FFE80 slowest boot */ + addi r4,0,pb0ap + mtdcr ebccfga,r4 + addis r4,0,0x9B01 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + addis r4,0,0xFFC5 /* BAS=0xFFC,BS=0x4(4MB),BU=0x3(R/W), */ + ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + + blr + + /*---------------------------------------------------------------------- */ + /* Peripheral Bank 1 (NVRAM/RTC) initialization */ + /* CRAY:the L1 has NOT this bank, it is tied to SV2/IOCA/etc/ instead */ + /* and we do DMA on it. The ConfigurationRegister part is threfore */ + /* almost arbitrary, except that our linux driver needs to know the */ + /* address, but it can query, it.. */ + /* */ + /* The AccessParameter is CRITICAL, */ + /* thouch, since it needs to agree with the electrical timings on the */ + /* IOCA parallel interface. That value is: 0x0185,4380 */ + /* BurstModeEnable BME=0 */ + /* TransferWait TWT=3 */ + /* ChipSelectOnTiming CSN=1 */ + /* OutputEnableOnTimimg OEN=1 */ + /* WriteByteEnableOnTiming WBN=1 */ + /* WriteByteEnableOffTiming WBF=0 */ + /* TransferHold TH=1 */ + /* ReadyEnable RE=1 */ + /* SampleOnReady SOR=1 */ + /* ByteEnableMode BEM=0 */ + /* ParityEnable PEN=0 */ + /* all reserved bits=0 */ + /*---------------------------------------------------------------------- */ + /*---------------------------------------------------------------------- */ + addi r4,0,pb1ap + mtdcr ebccfga,r4 + addis r4,0,0x0185 /* hiword */ + ori r4,r4,0x4380 /* loword */ + mtdcr ebccfgd,r4 + + addi r4,0,pb1cr + mtdcr ebccfga,r4 + addis r4,0,0xF001 /* BAS=0xF00,BS=0x0(1MB),BU=0x3(R/W), */ + ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + + blr + +/*----------------------------------------------------------------------------- */ +/* Function: sdram_init */ +/* Description: Configures SDRAM memory banks. */ +/* NOTE: for CrayL1 we have ECC memory, so enable it. */ +/*....now done in C in L1.c:init_sdram for readability. */ +/*----------------------------------------------------------------------------- */ + .globl sdram_init + +sdram_init: + blr diff --git a/board/dnp1110/config.mk b/board/dnp1110/config.mk new file mode 100644 index 0000000..72ba595 --- /dev/null +++ b/board/dnp1110/config.mk @@ -0,0 +1,17 @@ +# +# DNP/1110 board with SA1100 cpu +# +# http://www.dilnetpc.com +# + +# +# DILNETPC has 1 banks of 32 MB DRAM +# +# c000'0000 +# +# Linux-Kernel is expected to be at c000'8000, entry c000'8000 +# +# we load ourself to c1f0'0000, the upper 1 MB of the first (only) bank +# + +TEXT_BASE = 0xc1f00000 diff --git a/board/dnp1110/memsetup.S b/board/dnp1110/memsetup.S new file mode 100644 index 0000000..bebd697 --- /dev/null +++ b/board/dnp1110/memsetup.S @@ -0,0 +1,96 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +MEM_BASE: .long 0xa0000000 +MEM_START: .long 0xc0000000 + +#define MDCNFG 0x00 +#define MDCAS0 0x04 +#define MDCAS1 0x08 +#define MDCAS2 0x0c +#define MSC0 0x10 +#define MSC1 0x14 +#define MECR 0x18 + +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +/* mdcnfg: .long 0x0bb2bcbf */ +mdcnfg: .long 0x0334b22f @ alt +/* mcs0: .long 0xfff8fff8 */ +msc0: .long 0xad8c4888 @ alt +mecr: .long 0x00060006 +/* mecr: .long 0x994a994a @ alt */ + +/* setting up the memory */ + +.globl memsetup +memsetup: + ldr r0, MEM_BASE + + /* Setup the flash memory */ + ldr r1, msc0 + str r1, [r0, #MSC0] + + /* Set up the DRAM */ + + /* MDCAS0 */ + ldr r1, mdcas0 + str r1, [r0, #MDCAS0] + + /* MDCAS1 */ + ldr r1, mdcas1 + str r1, [r0, #MDCAS1] + + /* MDCAS2 */ + ldr r1, mdcas2 + str r1, [r0, #MDCAS2] + + /* MDCNFG */ + ldr r1, mdcnfg + str r1, [r0, #MDCNFG] + + /* Set up PCMCIA space */ + ldr r1, mecr + str r1, [r0, #MECR] + + /* Load something to activate bank */ + ldr r1, MEM_START + +.rept 8 + ldr r0, [r1] +.endr + + /* everything is fine now */ + mov pc, lr + diff --git a/board/ebony/flash.c b/board/ebony/flash.c new file mode 100644 index 0000000..6efd566 --- /dev/null +++ b/board/ebony/flash.c @@ -0,0 +1,736 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 Jun Gu <jung@artesyncp.com> + * Add support for Am29F016D and dynamic switch setting. + * + * 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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + + +#undef DEBUG +#ifdef DEBUG +#define DEBUGF(x...) printf(x) +#else +#define DEBUGF(x...) +#endif /* DEBUG */ + +#define BOOT_SMALL_FLASH 32 /* 00100000 */ +#define FLASH_ONBD_N 2 /* 00000010 */ +#define FLASH_SRAM_SEL 1 /* 00000001 */ + +#define BOOT_SMALL_FLASH_VAL 4 +#define FLASH_ONBD_N_VAL 2 +#define FLASH_SRAM_SEL_VAL 1 + + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +static unsigned long flash_addr_table[8][CFG_MAX_FLASH_BANKS] = { + {0xffc00000, 0xffe00000, 0xff880000}, /* 0:000: configuraton 3 */ + {0xffc00000, 0xffe00000, 0xff800000}, /* 1:001: configuraton 4 */ + {0xffc00000, 0xffe00000, 0x00000000}, /* 2:010: configuraton 7 */ + {0xffc00000, 0xffe00000, 0x00000000}, /* 3:011: configuraton 8 */ + {0xff800000, 0xffa00000, 0xfff80000}, /* 4:100: configuraton 1 */ + {0xff800000, 0xffa00000, 0xfff00000}, /* 5:101: configuraton 2 */ + {0xffc00000, 0xffe00000, 0x00000000}, /* 6:110: configuraton 5 */ + {0xffc00000, 0xffe00000, 0x00000000} /* 7:111: configuraton 6 */ +}; + +/*----------------------------------------------------------------------- + * 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); +#if 0 +static void flash_get_offsets (ulong base, flash_info_t *info); +#endif + +#ifdef CONFIG_ADCIOP +#define ADDR0 0x0aa9 +#define ADDR1 0x0556 +#define FLASH_WORD_SIZE unsigned char +#endif + +#ifdef CONFIG_CPCI405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short +#endif + +#ifdef CONFIG_WALNUT405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned char +#endif + +#ifdef CONFIG_EBONY +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned char +#endif + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) { + unsigned long total_b = 0; + unsigned long size_b[CFG_MAX_FLASH_BANKS]; + unsigned char * fpga_base = (unsigned char *)CFG_FPGA_BASE; + unsigned char switch_status; + unsigned short index = 0; + int i; + + + /* read FPGA base register FPGA_REG0 */ + switch_status = *fpga_base; + + /* check the bitmap of switch status */ + if (switch_status & BOOT_SMALL_FLASH) { + index += BOOT_SMALL_FLASH_VAL; + } + if (switch_status & FLASH_ONBD_N) { + index += FLASH_ONBD_N_VAL; + } + if (switch_status & FLASH_SRAM_SEL) { + index += FLASH_SRAM_SEL_VAL; + } + + DEBUGF("\n"); + DEBUGF("FLASH: Index: %d\n", index); + + /* 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 = -1; + flash_info[i].size = 0; + + /* check whether the address is 0 */ + if (flash_addr_table[index][i] == 0) { + continue; + } + + /* call flash_get_size() to initialize sector address */ + size_b[i] = flash_get_size( + (vu_long *)flash_addr_table[index][i], &flash_info[i]); + flash_info[i].size = size_b[i]; + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", + i, size_b[i], size_b[i]<<20); + flash_info[i].sector_count = -1; + flash_info[i].size = 0; + } + + total_b += flash_info[i].size; + } + + return total_b; +} + + + +/*----------------------------------------------------------------------- + */ +#if 0 +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040) || + (info->flash_id == FLASH_AMD016)) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } +} +#endif /* 0 */ + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + 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_SST: printf ("SST "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AMD016: printf ("AM29F016D (16 Mbit, uniform sector size)\n"); + break; + case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n"); + break; + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) + { + if (*flash++ != 0xffffffff) + { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " " + ); + } + printf ("\n"); + return; + } + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + static ulong flash_get_size (vu_long *addr, flash_info_t *info) + { + short i; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr ); + + /* Write auto select command: read Manufacturer ID */ + udelay(10000); + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + udelay(1000); + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + udelay(1000); + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + udelay(1000); + +#ifdef CONFIG_ADCIOP + value = addr2[2]; +#else + value = addr2[0]; +#endif + + DEBUGF("FLASH MANUFACT: %x\n", value); + + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + +#ifdef CONFIG_ADCIOP + value = addr2[0]; /* device ID */ + debug ("\ndev_code=%x\n", value); +#else + value = addr2[1]; /* device ID */ +#endif + + DEBUGF("\nFLASH DEVICEID: %x\n", value); + + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_F016D: + info->flash_id += FLASH_AMD016; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ +#if 0 /* enable when device IDs are available */ + case (FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040) || + (info->flash_id == FLASH_AMD016)) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } + + /* 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 */ +#ifdef CONFIG_ADCIOP + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + info->protect[i] = addr2[4] & 1; +#else + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; +#endif + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { +#if 0 /* test-only */ +#ifdef CONFIG_ADCIOP + addr2 = (volatile unsigned char *)info->start[0]; + addr2[ADDR0] = 0xAA; + addr2[ADDR1] = 0x55; + addr2[ADDR0] = 0xF0; /* reset bank */ +#else + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif +#else /* test-only */ + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif /* test-only */ + } + + return (info->size); + } + + int wait_for_DQ7(flash_info_t *info, int sect) + { + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + 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 */ + putc ('.'); + last = now; + } + } + return 0; + } + +/*----------------------------------------------------------------------- + */ + + int flash_erase (flash_info_t *info, int s_first, int s_last) + { + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + int i; + + 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) { + 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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); + printf("Erasing sector %p\n", addr2); + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ + for (i=0; i<50; i++) + udelay(1000); /* wait 1 ms */ + } else { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + } + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + wait_for_DQ7(info, sect); + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + +#if 0 + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + wait_for_DQ7(info, l_sect); + + DONE: +#endif + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* 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; 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; + } + + /* + * 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 FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest; + volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data; + ulong start; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *) dest) & + (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) { + return (2); + } + + for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) { + int flag; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) != + (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) { + + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); + } + +/*----------------------------------------------------------------------- + */ diff --git a/board/eltec/mhpc/config.mk b/board/eltec/mhpc/config.mk new file mode 100644 index 0000000..607ebbc --- /dev/null +++ b/board/eltec/mhpc/config.mk @@ -0,0 +1,49 @@ +# +# (C) Copyright 2000 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# (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 +# + +# +# MHPC boards +# + +TEXT_BASE = 0xfe000000 +/*TEXT_BASE = 0x00200000 */ + + + + + + + + + + + + + + + + diff --git a/board/eric/flash.c b/board/eric/flash.c new file mode 100644 index 0000000..c3f6e15 --- /dev/null +++ b/board/eric/flash.c @@ -0,0 +1,1130 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + + +#ifdef CFG_FLASH_16BIT +#define FLASH_WORD_SIZE unsigned short +#define FLASH_ID_MASK 0xFFFF +#else +#define FLASH_WORD_SIZE unsigned long +#define FLASH_ID_MASK 0xFFFFFFFF +#endif + +/*----------------------------------------------------------------------- + * Functions + */ +/* stolen from esteem192e/flash.c */ +ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info); + +#ifndef CFG_FLASH_16BIT +static int write_word (flash_info_t *info, ulong dest, ulong data); +#else +static int write_short (flash_info_t *info, ulong dest, ushort data); +#endif +static void flash_get_offsets (ulong base, flash_info_t *info); + + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0, size_b1; + int i; + uint pbcr; + unsigned long base_b0, base_b1; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + /* Only one bank */ + if (CFG_MAX_FLASH_BANKS == 1) + { + /* Setup offsets */ + flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); + + /* Monitor protection ON by default */ +#if 0 /* sand: */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0, + FLASH_BASE0_PRELIM-1+size_b0, + &flash_info[0]); +#else + (void)flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + size_b1 = 0 ; + flash_info[0].size = size_b0; + } + + /* 2 banks */ + else + { + size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE1_PRELIM, &flash_info[1]); + + /* Re-do sizing to get full correct info */ + + if (size_b1) + { + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b1 = -size_b1; + pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + } + + if (size_b0) + { + mtdcr(ebccfga, pb1cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb1cr); + base_b0 = base_b1 - size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb0cr = %x\n", pbcr); */ + } + + size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b0, &flash_info[0]); + + flash_get_offsets (base_b0, &flash_info[0]); + + /* monitor protection ON by default */ +#if 0 /* sand: */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0, + FLASH_BASE0_PRELIM-1+size_b0, + &flash_info[0]); +#else + (void)flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + + if (size_b1) { + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]); + + flash_get_offsets (base_b1, &flash_info[1]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b1+size_b1-CFG_MONITOR_LEN, + base_b1+size_b1-1, + &flash_info[1]); + /* monitor protection OFF by default (one is enough) */ + (void)flash_protect(FLAG_PROTECT_CLEAR, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + } else { + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + }/* else 2 banks */ + return (size_b0 + size_b1); +} + + + +/*----------------------------------------------------------------------- + */ + +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start adress table */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F320J3A || + (info->flash_id & FLASH_TYPEMASK) == FLASH_28F640J3A || + (info->flash_id & FLASH_TYPEMASK) == FLASH_28F128J3A) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * info->size/info->sector_count); + } + } else if (info->flash_id & FLASH_BTYPE) { + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + +#ifndef CFG_FLASH_16BIT + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00008000; + info->start[3] = base + 0x0000C000; + info->start[4] = base + 0x00010000; + info->start[5] = base + 0x00014000; + info->start[6] = base + 0x00018000; + info->start[7] = base + 0x0001C000; + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00020000) - 0x000E0000; + } + } + else { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x0000C000; + info->start[3] = base + 0x00010000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00020000) - 0x00060000; + } + } +#else + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00002000; + info->start[2] = base + 0x00004000; + info->start[3] = base + 0x00006000; + info->start[4] = base + 0x00008000; + info->start[5] = base + 0x0000A000; + info->start[6] = base + 0x0000C000; + info->start[7] = base + 0x0000E000; + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00070000; + } + } + else { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } +#endif + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + +#ifndef CFG_FLASH_16BIT + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + info->start[i--] = base + info->size - 0x00014000; + info->start[i--] = base + info->size - 0x00018000; + info->start[i--] = base + info->size - 0x0001C000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + + } else { + + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + } +#else + info->start[i--] = base + info->size - 0x00002000; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000A000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x0000E000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + + } else { + + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } +#endif + } + + +} + +/*----------------------------------------------------------------------- + */ + +void flash_print_info (flash_info_t *info) +{ + int i; + uchar *boottype; + uchar botboot[]=", bottom boot sect)\n"; + uchar topboot[]=", top boot sector)\n"; + + 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_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("STM "); break; + case FLASH_MAN_INTEL: printf ("INTEL "); break; + default: printf ("Unknown Vendor "); break; + } + + if (info->flash_id & 0x0001 ) { + boottype = botboot; + } else { + boottype = topboot; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit%s",boottype); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit%s",boottype); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit%s",boottype); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit%s",boottype); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit%s",boottype); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit%s",boottype); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit%s",boottype); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit%s",boottype); + break; + case FLASH_INTEL800B: printf ("INTEL28F800B (8 Mbit%s",boottype); + break; + case FLASH_INTEL800T: printf ("INTEL28F800T (8 Mbit%s",boottype); + break; + case FLASH_INTEL160B: printf ("INTEL28F160B (16 Mbit%s",boottype); + break; + case FLASH_INTEL160T: printf ("INTEL28F160T (16 Mbit%s",boottype); + break; + case FLASH_INTEL320B: printf ("INTEL28F320B (32 Mbit%s",boottype); + break; + case FLASH_INTEL320T: printf ("INTEL28F320T (32 Mbit%s",boottype); + break; + +#if 0 /* enable when devices are available */ + + case FLASH_INTEL640B: printf ("INTEL28F640B (64 Mbit%s",boottype); + break; + case FLASH_INTEL640T: printf ("INTEL28F640T (64 Mbit%s",boottype); + break; +#endif + case FLASH_28F320J3A: printf ("INTEL28F320J3A (32 Mbit%s",boottype); + break; + case FLASH_28F640J3A: printf ("INTEL28F640J3A (64 Mbit%s",boottype); + break; + case FLASH_28F128J3A: printf ("INTEL28F128J3A (128 Mbit%s",boottype); + 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; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ +ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info) +{ + short i; + ulong base = (ulong)addr; + FLASH_WORD_SIZE value; + + /* Write auto select command: read Manufacturer ID */ + + +#ifndef CFG_FLASH_16BIT + + /* + * Note: if it is an AMD flash and the word at addr[0000] + * is 0x00890089 this routine will think it is an Intel + * flash device and may(most likely) cause trouble. + */ + + addr[0x0000] = 0x00900090; + if(addr[0x0000] != 0x00890089){ + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00900090; +#else + + /* + * Note: if it is an AMD flash and the word at addr[0000] + * is 0x0089 this routine will think it is an Intel + * flash device and may(most likely) cause trouble. + */ + + addr[0x0000] = 0x0090; + + if(addr[0x0000] != 0x0089){ + addr[0x0555] = 0x00AA; + addr[0x02AA] = 0x0055; + addr[0x0555] = 0x0090; +#endif + } + value = addr[0]; + + switch (value) { + case (AMD_MANUFACT & FLASH_ID_MASK): + info->flash_id = FLASH_MAN_AMD; + break; + case (FUJ_MANUFACT & FLASH_ID_MASK): + info->flash_id = FLASH_MAN_FUJ; + break; + case (STM_MANUFACT & FLASH_ID_MASK): + info->flash_id = FLASH_MAN_STM; + break; + case (SST_MANUFACT & FLASH_ID_MASK): + info->flash_id = FLASH_MAN_SST; + break; + case (INTEL_MANUFACT & FLASH_ID_MASK): + info->flash_id = FLASH_MAN_INTEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + + } + + value = addr[1]; /* device ID */ + + switch (value) { + + case (AMD_ID_LV400T & FLASH_ID_MASK): + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV400B & FLASH_ID_MASK): + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV800T & FLASH_ID_MASK): + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (AMD_ID_LV800B & FLASH_ID_MASK): + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (AMD_ID_LV160T & FLASH_ID_MASK): + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (AMD_ID_LV160B & FLASH_ID_MASK): + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ +#if 0 /* enable when device IDs are available */ + case (AMD_ID_LV320T & FLASH_ID_MASK): + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + + case (AMD_ID_LV320B & FLASH_ID_MASK): + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + + case (INTEL_ID_28F800B3T & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL800T; + info->sector_count = 23; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (INTEL_ID_28F800B3B & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL800B; + info->sector_count = 23; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (INTEL_ID_28F160B3T & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL160T; + info->sector_count = 39; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (INTEL_ID_28F160B3B & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL160B; + info->sector_count = 39; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (INTEL_ID_28F320B3T & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL320T; + info->sector_count = 71; + info->size = 0x00800000; + break; /* => 8 MB */ + + case (INTEL_ID_28F320B3B & FLASH_ID_MASK): + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00800000; + break; /* => 8 MB */ + +#if 0 /* enable when devices are available */ + case (INTEL_ID_28F320B3T & FLASH_ID_MASK): + info->flash_id += FLASH_INTEL320T; + info->sector_count = 135; + info->size = 0x01000000; + break; /* => 16 MB */ + + case (INTEL_ID_28F320B3B & FLASH_ID_MASK): + info->flash_id += FLASH_AM320B; + info->sector_count = 135; + info->size = 0x01000000; + break; /* => 16 MB */ +#endif + case (INTEL_ID_28F320J3A & FLASH_ID_MASK): + info->flash_id += FLASH_28F320J3A; + info->sector_count = 32; + info->size = 0x00400000; + break; /* => 32 MBit */ + case (INTEL_ID_28F640J3A & FLASH_ID_MASK): + info->flash_id += FLASH_28F640J3A; + info->sector_count = 64; + info->size = 0x00800000; + break; /* => 64 MBit */ + case (INTEL_ID_28F128J3A & FLASH_ID_MASK): + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 0x01000000; + break; /* => 128 MBit */ + + default: + /* FIXME*/ + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + } + + flash_get_offsets(base, info); + + /* 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 */ + addr = (volatile FLASH_WORD_SIZE *)(info->start[i]); + info->protect[i] = addr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr = (volatile FLASH_WORD_SIZE *)info->start[0]; + if( (info->flash_id & 0xFF00) == FLASH_MAN_INTEL){ + *addr = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */ + } else { + *addr = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */ + } + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + + volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]); + int flag, prot, sect, l_sect, barf; + ulong start, now, last; + int rcode = 0; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + ((info->flash_id > FLASH_AMD_COMP) && + ( (info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL ) ) ){ + 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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + if(info->flash_id < FLASH_AMD_COMP) { +#ifndef CFG_FLASH_16BIT + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00800080; + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; +#else + addr[0x0555] = 0x00AA; + addr[0x02AA] = 0x0055; + addr[0x0555] = 0x0080; + addr[0x0555] = 0x00AA; + addr[0x02AA] = 0x0055; +#endif + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]); + addr[0] = (0x00300030 & FLASH_ID_MASK); + 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 = (volatile FLASH_WORD_SIZE*)(info->start[l_sect]); + while ((addr[0] & (0x00800080&FLASH_ID_MASK)) != + (0x00800080&FLASH_ID_MASK) ) + { + 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 = (volatile FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */ + } else { + + + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + barf = 0; +#ifndef CFG_FLASH_16BIT + addr = (vu_long*)(info->start[sect]); + addr[0] = 0x00200020; + addr[0] = 0x00D000D0; + while(!(addr[0] & 0x00800080)); /* wait for error or finish */ + if( addr[0] & 0x003A003A) { /* check for error */ + barf = addr[0] & 0x003A0000; + if( barf ) { + barf >>=16; + } else { + barf = addr[0] & 0x0000003A; + } + } +#else + addr = (vu_short*)(info->start[sect]); + addr[0] = 0x0020; + addr[0] = 0x00D0; + while(!(addr[0] & 0x0080)); /* wait for error or finish */ + if( addr[0] & 0x003A) /* check for error */ + barf = addr[0] & 0x003A; +#endif + if(barf) { + printf("\nFlash error in sector at %lx\n",(unsigned long)addr); + if(barf & 0x0002) printf("Block locked, not erased.\n"); + if((barf & 0x0030) == 0x0030) + printf("Command Sequence error.\n"); + if((barf & 0x0030) == 0x0020) + printf("Block Erase error.\n"); + if(barf & 0x0008) printf("Vpp Low error.\n"); + rcode = 1; + } else printf("."); + l_sect = sect; + } + addr = (volatile FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (0x00FF00FF & FLASH_ID_MASK); /* reset bank */ + + } + + } + printf (" done\n"); + return rcode; +} + +/*----------------------------------------------------------------------- + */ + +/*flash_info_t *addr2info (ulong addr) +{ + flash_info_t *info; + int i; + + for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) { + if ((addr >= info->start[0]) && + (addr < (info->start[0] + info->size)) ) { + return (info); + } + } + + return (NULL); +} +*/ +/*----------------------------------------------------------------------- + * Copy memory to flash. + * Make sure all target addresses are within Flash bounds, + * and no protected sectors are hit. + * Returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - target range includes protected sectors + * 8 - target address not in Flash memory + */ + +/*int flash_write (uchar *src, ulong addr, ulong cnt) +{ + int i; + ulong end = addr + cnt - 1; + flash_info_t *info_first = addr2info (addr); + flash_info_t *info_last = addr2info (end ); + flash_info_t *info; + + if (cnt == 0) { + return (0); + } + + if (!info_first || !info_last) { + return (8); + } + + for (info = info_first; info <= info_last; ++info) { + ulong b_end = info->start[0] + info->size;*/ /* bank end addr */ +/* short s_end = info->sector_count - 1; + for (i=0; i<info->sector_count; ++i) { + ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; + + if ((end >= info->start[i]) && (addr < e_addr) && + (info->protect[i] != 0) ) { + return (4); + } + } + } + +*/ /* finally write data to flash */ +/* for (info = info_first; info <= info_last && cnt>0; ++info) { + ulong len; + + len = info->start[0] + info->size - addr; + if (len > cnt) + len = cnt; + if ((i = write_buff(info, src, addr, len)) != 0) { + return (i); + } + cnt -= len; + addr += len; + src += len; + } + 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) +{ +#ifndef CFG_FLASH_16BIT + ulong cp, wp, data; + int l; +#else + ulong cp, wp; + ushort data; +#endif + int i, rc; + +#ifndef CFG_FLASH_16BIT + + + 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); + } + + 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)); + +#else + wp = (addr & ~1); /* get lower word aligned address */ + + /* + * handle unaligned start byte + */ + if (addr - wp) { + data = 0; + data = (data << 8) | *src++; + --cnt; + if ((rc = write_short(info, wp, data)) != 0) { + return (rc); + } + wp += 2; + } + + /* + * handle word aligned part + */ +/* l = 0; used for debuging */ + while (cnt >= 2) { + data = 0; + for (i=0; i<2; ++i) { + data = (data << 8) | *src++; + } + +/* if(!l){ + printf("%x",data); + l = 1; + } used for debuging */ + + if ((rc = write_short(info, wp, data)) != 0) { + return (rc); + } + wp += 2; + cnt -= 2; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<2; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_short(info, wp, data)); + + +#endif +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +#ifndef CFG_FLASH_16BIT +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long*)(info->start[0]); + ulong start,barf; + 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(); + + if(info->flash_id > FLASH_AMD_COMP) { + /* AMD stuff */ + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00A000A0; + } else { + /* intel stuff */ + *addr = 0x00400040; + } + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + + if(info->flash_id > FLASH_AMD_COMP) { + + while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + + } else { + + while(!(addr[0] & 0x00800080)){ /* wait for error or finish */ + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + + if( addr[0] & 0x003A003A) { /* check for error */ + barf = addr[0] & 0x003A0000; + if( barf ) { + barf >>=16; + } else { + barf = addr[0] & 0x0000003A; + } + printf("\nFlash write error at address %lx\n",(unsigned long)dest); + if(barf & 0x0002) printf("Block locked, not erased.\n"); + if(barf & 0x0010) printf("Programming error.\n"); + if(barf & 0x0008) printf("Vpp Low error.\n"); + return(2); + } + + + } + + return (0); + +} + +#else + +static int write_short (flash_info_t *info, ulong dest, ushort data) +{ + vu_short *addr = (vu_short*)(info->start[0]); + ulong start,barf; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_short *)dest) & data) != data) { + return (2); + } + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + if(info->flash_id < FLASH_AMD_COMP) { + /* AMD stuff */ + addr[0x0555] = 0x00AA; + addr[0x02AA] = 0x0055; + addr[0x0555] = 0x00A0; + } else { + /* intel stuff */ + *addr = 0x00D0; + *addr = 0x0040; + } + *((vu_short *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + + if(info->flash_id < FLASH_AMD_COMP) { + /* AMD stuff */ + while ((*((vu_short *)dest) & 0x0080) != (data & 0x0080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + + } else { + /* intel stuff */ + while(!(addr[0] & 0x0080)){ /* wait for error or finish */ + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return (1); + } + + if( addr[0] & 0x003A) { /* check for error */ + barf = addr[0] & 0x003A; + printf("\nFlash write error at address %lx\n",(unsigned long)dest); + if(barf & 0x0002) printf("Block locked, not erased.\n"); + if(barf & 0x0010) printf("Programming error.\n"); + if(barf & 0x0008) printf("Vpp Low error.\n"); + return(2); + } + *addr = 0x00B0; + *addr = 0x0070; + while(!(addr[0] & 0x0080)){ /* wait for error or finish */ + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return (1); + } + + *addr = 0x00FF; + + } + + return (0); + +} + + +#endif + +/*----------------------------------------------------------------------- + */ + diff --git a/board/eric/init.S b/board/eric/init.S new file mode 100644 index 0000000..bdf90a5 --- /dev/null +++ b/board/eric/init.S @@ -0,0 +1,355 @@ +/*------------------------------------------------------------------------------+ */ +/* */ +/* This source code has been made available to you by IBM on an AS-IS */ +/* basis. Anyone receiving this source is licensed under IBM */ +/* copyrights to use it in any way he or she deems fit, including */ +/* copying it, modifying it, compiling it, and redistributing it either */ +/* with or without modifications. No license under IBM patents or */ +/* patent applications is to be implied by the copyright license. */ +/* */ +/* Any user of this software should understand that IBM cannot provide */ +/* technical support for this software and will not be responsible for */ +/* any consequences resulting from the use of this software. */ +/* */ +/* Any person who transfers this source code or any derivative work */ +/* must include the IBM copyright notice, this paragraph, and the */ +/* preceding two paragraphs in the transferred software. */ +/* */ +/* COPYRIGHT I B M CORPORATION 1995 */ +/* LICENSED MATERIAL - PROGRAM PROPERTY OF I B M */ +/*------------------------------------------------------------------------------- */ + +/*----------------------------------------------------------------------------- */ +/* Function: ext_bus_cntlr_init */ +/* Description: Initializes the External Bus Controller for the external */ +/* peripherals. IMPORTANT: For pass1 this code must run from */ +/* cache since you can not reliably change a peripheral banks */ +/* timing register (pbxap) while running code from that bank. */ +/* For ex., since we are running from ROM on bank 0, we can NOT */ +/* execute the code that modifies bank 0 timings from ROM, so */ +/* we run it from cache. */ +/* */ +/*----------------------------------------------------------------------------- */ +#include <config.h> +#include <ppc4xx.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 10; used to prefetch */ + mtctr r4 /* 10 cache lines to fit this function */ + /* in cache (gives us 8x10=80 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 10 cache lines */ + + /*------------------------------------------------------------------- */ + /* Delay to ensure all accesses to ROM are complete before changing */ + /* bank 0 timings. 200usec should be enough. */ + /* 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles */ + /*------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 /* ensure 200usec have passed since reset */ + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- */ + /* Memory Bank 0 (Flash) initialization (from openbios) */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb0ap + mtdcr ebccfga,r4 + addis r4,0,CS0_AP@h + ori r4,r4,CS0_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + addis r4,0,CS0_CR@h + ori r4,r4,CS0_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 1 (NVRAM/RTC) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb1ap + mtdcr ebccfga,r4 + addis r4,0,CS1_AP@h + ori r4,r4,CS1_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb1cr + mtdcr ebccfga,r4 + addis r4,0,CS1_CR@h + ori r4,r4,CS1_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 2 (A/D converter) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb2ap + mtdcr ebccfga,r4 + addis r4,0,CS2_AP@h + ori r4,r4,CS2_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb2cr + mtdcr ebccfga,r4 + addis r4,0,CS2_CR@h + ori r4,r4,CS2_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 3 (Ethernet PHY Reset) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb3ap + mtdcr ebccfga,r4 + addis r4,0,CS3_AP@h + ori r4,r4,CS3_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb3cr + mtdcr ebccfga,r4 + addis r4,0,CS3_CR@h + ori r4,r4,CS3_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 4 (PC-MIP PRSNT1#) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb4ap + mtdcr ebccfga,r4 + addis r4,0,CS4_AP@h + ori r4,r4,CS4_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb4cr + mtdcr ebccfga,r4 + addis r4,0,CS4_CR@h + ori r4,r4,CS4_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 5 (PC-MIP PRSNT2#) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb5ap + mtdcr ebccfga,r4 + addis r4,0,CS5_AP@h + ori r4,r4,CS5_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb5cr + mtdcr ebccfga,r4 + addis r4,0,CS5_CR@h + ori r4,r4,CS5_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 6 (CPU LED0) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb6ap + mtdcr ebccfga,r4 + addis r4,0,CS6_AP@h + ori r4,r4,CS6_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb6cr + mtdcr ebccfga,r4 + addis r4,0,CS6_CR@h + ori r4,r4,CS5_CR@l + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- */ + /* Memory Bank 7 (CPU LED1) initialization */ + /*----------------------------------------------------------------------- */ + + addi r4,0,pb7ap + mtdcr ebccfga,r4 + addis r4,0,CS7_AP@h + ori r4,r4,CS7_AP@l + mtdcr ebccfgd,r4 + + addi r4,0,pb7cr + mtdcr ebccfga,r4 + addis r4,0,CS7_CR@h + ori r4,r4,CS7_CR@l + mtdcr ebccfgd,r4 + +/* addis r4,r0,FPGA_BRDC@h */ +/* ori r4,r4,FPGA_BRDC@l */ +/* lbz r3,0(r4) //get FPGA board control reg */ +/* eieio */ +/* ori r3,r3,0x01 //set UART1 control to select CTS/RTS */ +/* stb r3,0(r4) */ + + nop /* pass2 DCR errata #8 */ + blr + +/*----------------------------------------------------------------------------- */ +/* Function: sdram_init */ +/* Description: Configures SDRAM memory banks on ERIC. */ +/* We do manually init our SDRAM. */ +/* If we have two SDRAM banks, simply undef SINGLE_BANK (ROLF :-) */ +/* It is assumed that a 32MB 12x8(2) SDRAM is used. */ +/*----------------------------------------------------------------------------- */ + .globl sdram_init + +sdram_init: + + mflr r31 + +#ifdef CFG_SDRAM_MANUALLY + /*------------------------------------------------------------------- */ + /* Set MB0CF for bank 0. (0-32MB) Address Mode 4 since 12x8(2) */ + /*------------------------------------------------------------------- */ + + addi r4,0,mem_mb0cf + mtdcr memcfga,r4 + addis r4,0,MB0CF@h + ori r4,r4,MB0CF@l + mtdcr memcfgd,r4 + + /*------------------------------------------------------------------- */ + /* Set MB1CF for bank 1. (32MB-64MB) Address Mode 4 since 12x8(2) */ + /*------------------------------------------------------------------- */ + + addi r4,0,mem_mb1cf + mtdcr memcfga,r4 + addis r4,0,MB1CF@h + ori r4,r4,MB1CF@l + mtdcr memcfgd,r4 + + /*------------------------------------------------------------------- */ + /* Set MB2CF for bank 2. off */ + /*------------------------------------------------------------------- */ + + addi r4,0,mem_mb2cf + mtdcr memcfga,r4 + addis r4,0,MB2CF@h + ori r4,r4,MB2CF@l + mtdcr memcfgd,r4 + + /*------------------------------------------------------------------- */ + /* Set MB3CF for bank 3. off */ + /*------------------------------------------------------------------- */ + + addi r4,0,mem_mb3cf + mtdcr memcfga,r4 + addis r4,0,MB3CF@h + ori r4,r4,MB3CF@l + mtdcr memcfgd,r4 + + /*------------------------------------------------------------------- */ + /* Set the SDRAM Timing reg, SDTR1 and the refresh timer reg, RTR. */ + /* To set the appropriate timings, we need to know the SDRAM speed. */ + /* We can use the PLB speed since the SDRAM speed is the same as */ + /* the PLB speed. The PLB speed is the FBK divider times the */ + /* 405GP reference clock, which on the Walnut board is 33Mhz. */ + /* Thus, if FBK div is 2, SDRAM is 66Mhz; if FBK div is 3, SDRAM is */ + /* 100Mhz; if FBK is 3, SDRAM is 133Mhz. */ + /* NOTE: The Walnut board supports SDRAM speeds of 66Mhz, 100Mhz, and */ + /* maybe 133Mhz. */ + /*------------------------------------------------------------------- */ + + mfdcr r5,strap /* determine FBK divider */ + /* via STRAP reg to calc PLB speed. */ + /* SDRAM speed is the same as the PLB */ + /* speed. */ + rlwinm r4,r5,4,0x3 /* get FBK divide bits */ + +..chk_66: + cmpi %cr0,0,r4,0x1 + bne ..chk_100 + addis r6,0,SDTR_66@h /* SDTR1 value for 66Mhz */ + ori r6,r6,SDTR_66@l + addis r7,0,RTR_66 /* RTR value for 66Mhz */ + b ..sdram_ok +..chk_100: + cmpi %cr0,0,r4,0x2 + bne ..chk_133 + addis r6,0,SDTR_100@h /* SDTR1 value for 100Mhz */ + ori r6,r6,SDTR_100@l + addis r7,0,RTR_100 /* RTR value for 100Mhz */ + b ..sdram_ok +..chk_133: + addis r6,0,0x0107 /* SDTR1 value for 133Mhz */ + ori r6,r6,0x4015 + addis r7,0,0x07F0 /* RTR value for 133Mhz */ + +..sdram_ok: + /*------------------------------------------------------------------- */ + /* Set SDTR1 */ + /*------------------------------------------------------------------- */ + addi r4,0,mem_sdtr1 + mtdcr memcfga,r4 + mtdcr memcfgd,r6 + + /*------------------------------------------------------------------- */ + /* Set RTR */ + /*------------------------------------------------------------------- */ + addi r4,0,mem_rtr + mtdcr memcfga,r4 + mtdcr memcfgd,r7 + + /*------------------------------------------------------------------- */ + /* Delay to ensure 200usec have elapsed since reset. Assume worst */ + /* case that the core is running 200Mhz: */ + /* 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles */ + /*------------------------------------------------------------------- */ + addis r3,0,0x0000 + ori r3,r3,0xA000 /* ensure 200usec have passed since reset */ + mtctr r3 +..spinlp2: + bdnz ..spinlp2 /* spin loop */ + + /*------------------------------------------------------------------- */ + /* Set memory controller options reg, MCOPT1. */ + /* Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst */ + /* read/prefetch. */ + /*------------------------------------------------------------------- */ + addi r4,0,mem_mcopt1 + mtdcr memcfga,r4 + addis r4,0,0x8080 /* set DC_EN=1 */ + ori r4,r4,0x0000 + mtdcr memcfgd,r4 + + /*------------------------------------------------------------------- */ + /* Delay to ensure 10msec have elapsed since reset. This is */ + /* required for the MPC952 to stabalize. Assume worst */ + /* case that the core is running 200Mhz: */ + /* 200,000,000 (cycles/sec) X .010 (sec) = 0x1E8480 cycles */ + /* This delay should occur before accessing SDRAM. */ + /*------------------------------------------------------------------- */ + addis r3,0,0x001E + ori r3,r3,0x8480 /* ensure 10msec have passed since reset */ + mtctr r3 +..spinlp3: + bdnz ..spinlp3 /* spin loop */ + +#else +/*fixme: do SDRAM Autoconfig from EEPROM here */ + +#endif + mtlr r31 /* restore lr */ + blr diff --git a/board/esd/ar405/flash.c b/board/esd/ar405/flash.c new file mode 100644 index 0000000..4fa6b27 --- /dev/null +++ b/board/esd/ar405/flash.c @@ -0,0 +1,126 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +/* + * include common flash code (for esd boards) + */ +#include "../common/flash.c" + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0, size_b1; + int i; + uint pbcr; + unsigned long base_b0, base_b1; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + base_b0 = FLASH_BASE0_PRELIM; + size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + base_b1 = FLASH_BASE1_PRELIM; + size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]); + + /* Re-do sizing to get full correct info */ + + if (size_b1) + { + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b1 = -size_b1; + pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + } + + if (size_b0) + { + mtdcr(ebccfga, pb1cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb1cr); + base_b0 = base_b1 - size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb0cr = %x\n", pbcr); */ + } + + size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]); + + flash_get_offsets (base_b0, &flash_info[0]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + + if (size_b1) { + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]); + + flash_get_offsets (base_b1, &flash_info[1]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b1+size_b1-CFG_MONITOR_LEN, + base_b1+size_b1-1, + &flash_info[1]); + /* monitor protection OFF by default (one is enough) */ + (void)flash_protect(FLAG_PROTECT_CLEAR, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + } else { + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + + return (size_b0 + size_b1); +} diff --git a/board/esd/canbt/flash.c b/board/esd/canbt/flash.c new file mode 100644 index 0000000..214948f --- /dev/null +++ b/board/esd/canbt/flash.c @@ -0,0 +1,84 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +/* + * include common flash code (for esd boards) + */ +#include "../common/flash.c" + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0; + int i; + uint pbcr; + unsigned long base_b0; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + /* Setup offsets */ + flash_get_offsets (-size_b0, &flash_info[0]); + + /* Re-do sizing to get full correct info */ + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b0 = -size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + -CFG_MONITOR_LEN, + 0xffffffff, + &flash_info[0]); + + flash_info[0].size = size_b0; + + return (size_b0); +} diff --git a/board/esd/cpciiser4/flash.c b/board/esd/cpciiser4/flash.c new file mode 100644 index 0000000..214948f --- /dev/null +++ b/board/esd/cpciiser4/flash.c @@ -0,0 +1,84 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +/* + * include common flash code (for esd boards) + */ +#include "../common/flash.c" + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0; + int i; + uint pbcr; + unsigned long base_b0; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + /* Setup offsets */ + flash_get_offsets (-size_b0, &flash_info[0]); + + /* Re-do sizing to get full correct info */ + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b0 = -size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + -CFG_MONITOR_LEN, + 0xffffffff, + &flash_info[0]); + + flash_info[0].size = size_b0; + + return (size_b0); +} diff --git a/board/esd/dasa_sim/eeprom.c b/board/esd/dasa_sim/eeprom.c new file mode 100644 index 0000000..59ef1d6 --- /dev/null +++ b/board/esd/dasa_sim/eeprom.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 + * + */ + +#include <common.h> +#include <command.h> + + +#define EEPROM_CAP 0x50000358 +#define EEPROM_DATA 0x5000035c + + +unsigned int eepromReadLong(int offs) +{ + unsigned int value; + volatile unsigned short ret; + int count; + + *(unsigned short *)EEPROM_CAP = offs; + + count = 0; + + for (;;) + { + count++; + ret = *(unsigned short *)EEPROM_CAP; + + if ((ret & 0x8000) != 0) + break; + } + + value = *(unsigned long *)EEPROM_DATA; + + return value; +} + + +unsigned char eepromReadByte(int offs) +{ + unsigned int valueLong; + unsigned char *ptr; + + valueLong = eepromReadLong(offs & ~3); + ptr = (unsigned char *)&valueLong; + + return ptr[offs & 3]; +} + + +void eepromWriteLong(int offs, unsigned int value) +{ + volatile unsigned short ret; + int count; + + count = 0; + + *(unsigned long *)EEPROM_DATA = value; + *(unsigned short *)EEPROM_CAP = 0x8000 + offs; + + for (;;) + { + count++; + ret = *(unsigned short *)EEPROM_CAP; + + if ((ret & 0x8000) == 0) + break; + } +} + + +void eepromWriteByte(int offs, unsigned char valueByte) +{ + unsigned int valueLong; + unsigned char *ptr; + + valueLong = eepromReadLong(offs & ~3); + ptr = (unsigned char *)&valueLong; + + ptr[offs & 3] = valueByte; + + eepromWriteLong(offs & ~3, valueLong); +} + + +void i2c_read (uchar *addr, int alen, uchar *buffer, int len) +{ + int i; + int len2, ptr; + + /* printf("\naddr=%x alen=%x buffer=%x len=%x", addr[0], addr[1], *(short *)addr, alen, buffer, len); // test-only */ + + ptr = *(short *)addr; + + /* + * Read till lword boundary + */ + len2 = 4 - (*(short *)addr & 0x0003); + for (i=0; i<len2; i++) + { + *buffer++ = eepromReadByte(ptr++); + } + + /* + * Read all lwords + */ + len2 = (len - len2) >> 2; + for (i=0; i<len2; i++) + { + *(unsigned int *)buffer = eepromReadLong(ptr); + buffer += 4; + ptr += 4; + } + + /* + * Read last bytes + */ + len2 = (*(short *)addr + len) & 0x0003; + for (i=0; i<len2; i++) + { + *buffer++ = eepromReadByte(ptr++); + } +} + +void i2c_write (uchar *addr, int alen, uchar *buffer, int len) +{ + int i; + int len2, ptr; + + /* printf("\naddr=%x alen=%x buffer=%x len=%x", addr[0], addr[1], *(short *)addr, alen, buffer, len); // test-only */ + + ptr = *(short *)addr; + + /* + * Write till lword boundary + */ + len2 = 4 - (*(short *)addr & 0x0003); + for (i=0; i<len2; i++) + { + eepromWriteByte(ptr++, *buffer++); + } + + /* + * Write all lwords + */ + len2 = (len - len2) >> 2; + for (i=0; i<len2; i++) + { + eepromWriteLong(ptr, *(unsigned int *)buffer); + buffer += 4; + ptr += 4; + } + + /* + * Write last bytes + */ + len2 = (*(short *)addr + len) & 0x0003; + for (i=0; i<len2; i++) + { + eepromWriteByte(ptr++, *buffer++); + } +} diff --git a/board/evb64260/ecctest.c b/board/evb64260/ecctest.c new file mode 100644 index 0000000..e7c58b3 --- /dev/null +++ b/board/evb64260/ecctest.c @@ -0,0 +1,91 @@ +#ifdef ECC_TEST +static inline void ecc_off(void) +{ + *(volatile int *)(INTERNAL_REG_BASE_ADDR+0x4b4) &= ~0x00200000; +} + +static inline void ecc_on(void) +{ + *(volatile int *)(INTERNAL_REG_BASE_ADDR+0x4b4) |= 0x00200000; +} + +static int putshex(const char *buf, int len) +{ + int i; + for (i=0;i<len;i++) { + printf("%02x", buf[i]); + } + return 0; +} + +static int char_memcpy(void *d, const void *s, int len) +{ + int i; + char *cd=d; + const char *cs=s; + for(i=0;i<len;i++) { + *(cd++)=*(cs++); + } + return 0; +} + +static int memory_test(char *buf) +{ + const char src[][16]={ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02}, + {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, + {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08}, + {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, + {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, + {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40}, + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, + {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55}, + {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} + }; + const int foo[] = {0}; + int i,j,a; + + printf("\ntest @ %d %p\n", foo[0], buf); + for(i=0;i<12;i++) { + for(a=0;a<8;a++) { + const char *s=src[i]+a; + int align=(unsigned)(s)&0x7; + /* ecc_off(); */ + memcpy(buf,s,8); + /* ecc_on(); */ + putshex(s,8); + if(memcmp(buf,s,8)) { + putc('\n'); + putshex(buf,8); + printf(" [FAIL] (%p) align=%d\n", s, align); + for(j=0;j<8;j++) { + s[j]==buf[j]?puts(" "):printf("%02x", (s[j])^(buf[j])); + } + putc('\n'); + } else { + printf(" [PASS] (%p) align=%d\n", s, align); + } + /* ecc_off(); */ + char_memcpy(buf,s,8); + /* ecc_on(); */ + putshex(s,8); + if(memcmp(buf,s,8)) { + putc('\n'); + putshex(buf,8); + printf(" [FAIL] (%p) align=%d\n", s, align); + for(j=0;j<8;j++) { + s[j]==buf[j]?puts(" "):printf("%02x", (s[j])^(buf[j])); + } + putc('\n'); + } else { + printf(" [PASS] (%p) align=%d\n", s, align); + } + } + } + + return 0; +} +#endif diff --git a/board/evb64260/eth.h b/board/evb64260/eth.h new file mode 100644 index 0000000..ecc3762 --- /dev/null +++ b/board/evb64260/eth.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __GT6426x_ETH_H__ +#define __GT6426x_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> + +typedef struct eth0_tx_desc_struct { + volatile __u32 bytecount_reserved; + volatile __u32 command_status; + volatile struct eth0_tx_desc_struct * next_desc; + /* Note - the following will not work for 64 bit addressing */ + volatile unsigned char * buff_pointer; +} eth0_tx_desc_single __attribute__ ((packed)); + +typedef struct eth0_rx_desc_struct { + volatile __u32 buff_size_byte_count; + volatile __u32 command_status; + volatile struct eth0_rx_desc_struct * next_desc; + volatile unsigned char * buff_pointer; +} eth0_rx_desc_single __attribute__ ((packed)); + +#define NT 20 /* Number of Transmit buffers */ +#define NR 20 /* Number of Receive buffers */ +#define MAX_BUFF_SIZE (1536+2*CACHE_LINE_SIZE) /* 1600 */ +#define ETHERNET_PORTS_DIFFERENCE_OFFSETS 0x400 + +unsigned long TDN_ETH0 , RDN_ETH0; /* Rx/Tx current Descriptor Number*/ +unsigned int EVB64260_ETH0_irq; + +#define CLOSED 0 +#define OPENED 1 + +#define PORT_ETH0 0 + +extern eth0_tx_desc_single *eth0_tx_desc; +extern eth0_rx_desc_single *eth0_rx_desc; +extern char *eth0_tx_buffer; +extern char *eth0_rx_buffer[NR]; +extern char *eth_data; + +extern int gt6426x_eth_poll(void *v); +extern int gt6426x_eth_transmit(void *v, volatile char *p, unsigned int s); +extern void gt6426x_eth_disable(void *v); +extern int gt6426x_eth_probe(void *v, bd_t *bis); + +#endif /* __GT64260x_ETH_H__ */ diff --git a/board/evb64260/mpsc.c b/board/evb64260/mpsc.c new file mode 100644 index 0000000..31a6a0d --- /dev/null +++ b/board/evb64260/mpsc.c @@ -0,0 +1,864 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * mpsc.c - driver for console over the MPSC. + */ + +#include <common.h> +#include <config.h> +#include <asm/cache.h> + +#include <malloc.h> +#include "mpsc.h" + +int (*mpsc_putchar)(char ch) = mpsc_putchar_early; + +static volatile unsigned int *rx_desc_base=NULL; +static unsigned int rx_desc_index=0; +static volatile unsigned int *tx_desc_base=NULL; +static unsigned int tx_desc_index=0; + +/* local function declarations */ +static int galmpsc_connect(int channel, int connect); +static int galmpsc_route_serial(int channel, int connect); +static int galmpsc_route_rx_clock(int channel, int brg); +static int galmpsc_route_tx_clock(int channel, int brg); +static int galmpsc_write_config_regs(int mpsc, int mode); +static int galmpsc_config_channel_regs(int mpsc); +static int galmpsc_set_char_length(int mpsc, int value); +static int galmpsc_set_stop_bit_length(int mpsc, int value); +static int galmpsc_set_parity(int mpsc, int value); +static int galmpsc_enter_hunt(int mpsc); +static int galmpsc_set_brkcnt(int mpsc, int value); +static int galmpsc_set_tcschar(int mpsc, int value); +static int galmpsc_set_snoop(int mpsc, int value); +static int galmpsc_shutdown(int mpsc); + +static int galsdma_set_RFT(int channel); +static int galsdma_set_SFM(int channel); +static int galsdma_set_rxle(int channel); +static int galsdma_set_txle(int channel); +static int galsdma_set_burstsize(int channel, unsigned int value); +static int galsdma_set_RC(int channel, unsigned int value); + +static int galbrg_set_CDV(int channel, int value); +static int galbrg_enable(int channel); +static int galbrg_disable(int channel); +static int galbrg_set_clksrc(int channel, int value); +static int galbrg_set_CUV(int channel, int value); + +static void galsdma_enable_rx(void); + +/* static int galbrg_reset(int channel); */ + +#define SOFTWARE_CACHE_MANAGEMENT + +#ifdef SOFTWARE_CACHE_MANAGEMENT +#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));} +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));} +#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));} +#else +#define FLUSH_DCACHE(a,b) +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) +#define INVALIDATE_DCACHE(a,b) +#endif + + +/* GT64240A errata: cant read MPSC/BRG registers... so make mirrors in ram for read/modify write */ +#define MIRROR_HACK ((struct _tag_mirror_hack *)&(gd->mirror_hack)) + +#define GT_REG_WRITE_MIRROR_G(a,d) {MIRROR_HACK->a ## _M = d; GT_REG_WRITE(a,d);} +#define GTREGREAD_MIRROR_G(a) (MIRROR_HACK->a ## _M) + +#define GT_REG_WRITE_MIRROR(a,i,g,d) {MIRROR_HACK->a ## _M[i] = d; GT_REG_WRITE(a + (i*g),d);} +#define GTREGREAD_MIRROR(a,i,g) (MIRROR_HACK->a ## _M[i]) + +/* make sure this isn't bigger than 16 long words (u-boot.h) */ +struct _tag_mirror_hack { + unsigned GALMPSC_PROTOCONF_REG_M[2]; /* 8008 */ + unsigned GALMPSC_CHANNELREG_1_M[2]; /* 800c */ + unsigned GALMPSC_CHANNELREG_2_M[2]; /* 8010 */ + unsigned GALBRG_0_CONFREG_M[2]; /* b200 */ + + unsigned GALMPSC_ROUTING_REGISTER_M; /* b400 */ + unsigned GALMPSC_RxC_ROUTE_M; /* b404 */ + unsigned GALMPSC_TxC_ROUTE_M; /* b408 */ + + unsigned int baudrate; /* current baudrate, for tsc delay calc */ +}; + +/* static struct _tag_mirror_hack *mh = NULL; */ + +/* special function for running out of flash. doesn't modify any + * global variables [josh] */ +int +mpsc_putchar_early(char ch) +{ + DECLARE_GLOBAL_DATA_PTR; + int mpsc=CHANNEL; + int temp=GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + galmpsc_set_tcschar(mpsc,ch); + GT_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp|0x200); + +#define MAGIC_FACTOR (10*1000000) + + udelay(MAGIC_FACTOR / MIRROR_HACK->baudrate); + return 0; +} + +/* This is used after relocation, see serial.c and mpsc_init2 */ +static int +mpsc_putchar_sdma(char ch) +{ + volatile unsigned int *p; + unsigned int temp; + + + /* align the descriptor */ + p = tx_desc_base; + memset((void *)p, 0, 8 * sizeof(unsigned int)); + + /* fill one 64 bit buffer */ + /* word swap, pad with 0 */ + p[4] = 0; /* x */ + p[5] = (unsigned int)ch; /* x */ + + /* CHANGED completely according to GT64260A dox - NTL */ + p[0] = 0x00010001; /* 0 */ + p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* 4 */ + p[2] = 0; /* 8 */ + p[3] = (unsigned int)&p[4]; /* c */ + +#if 0 + p[9] = DESC_FIRST | DESC_LAST; + p[10] = (unsigned int)&p[0]; + p[11] = (unsigned int)&p[12]; +#endif + + FLUSH_DCACHE(&p[0], &p[8]); + + GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&p[0]); + GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&p[0]); + + temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF)); + temp |= (TX_DEMAND | TX_STOP); + GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp); + + INVALIDATE_DCACHE(&p[1], &p[2]); + + while(p[1] & DESC_OWNER) { + udelay(100); + INVALIDATE_DCACHE(&p[1], &p[2]); + } + + return 0; +} + +char +mpsc_getchar(void) +{ + DECLARE_GLOBAL_DATA_PTR; + static unsigned int done = 0; + volatile char ch; + unsigned int len=0, idx=0, temp; + + volatile unsigned int *p; + + + do { + p=&rx_desc_base[rx_desc_index*8]; + + INVALIDATE_DCACHE(&p[0], &p[1]); + /* Wait for character */ + while (p[1] & DESC_OWNER){ + udelay(100); + INVALIDATE_DCACHE(&p[0], &p[1]); + } + + /* Handle error case */ + if (p[1] & (1<<15)) { + printf("oops, error: %08x\n", p[1]); + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,CHANNEL,GALMPSC_REG_GAP); + temp |= (1 << 23); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2, CHANNEL,GALMPSC_REG_GAP, temp); + + /* Can't poll on abort bit, so we just wait. */ + udelay(100); + + galsdma_enable_rx(); + } + + /* Number of bytes left in this descriptor */ + len = p[0] & 0xffff; + + if (len) { + /* Where to look */ + idx = 5; + if (done > 3) idx = 4; + if (done > 7) idx = 7; + if (done > 11) idx = 6; + + INVALIDATE_DCACHE(&p[idx], &p[idx+1]); + ch = p[idx] & 0xff; + done++; + } + + if (done < len) { + /* this descriptor has more bytes still + * shift down the char we just read, and leave the + * buffer in place for the next time around + */ + p[idx] = p[idx] >> 8; + FLUSH_DCACHE(&p[idx], &p[idx+1]); + } + + if (done == len) { + /* nothing left in this descriptor. + * go to next one + */ + p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST; + p[0] = 0x00100000; + FLUSH_DCACHE(&p[0], &p[1]); + /* Next descriptor */ + rx_desc_index = (rx_desc_index + 1) % RX_DESC; + done = 0; + } + } while (len==0); /* galileo bug.. len might be zero */ + + return ch; +} + +int +mpsc_test_char(void) +{ + volatile unsigned int *p=&rx_desc_base[rx_desc_index*8]; + + INVALIDATE_DCACHE(&p[1], &p[2]); + + if (p[1] & DESC_OWNER) return 0; + else return 1; +} + +int +mpsc_init(int baud) +{ + DECLARE_GLOBAL_DATA_PTR; + + memset(MIRROR_HACK, 0, sizeof(struct _tag_mirror_hack)); + MIRROR_HACK->GALMPSC_ROUTING_REGISTER_M=0x3fffffff; + + /* BRG CONFIG */ + galbrg_set_baudrate(CHANNEL, baud); +#ifdef CONFIG_ZUMA_V2 + galbrg_set_clksrc(CHANNEL,0x8); /* connect TCLK -> BRG */ +#else + galbrg_set_clksrc(CHANNEL,0); +#endif + galbrg_set_CUV(CHANNEL, 0); + galbrg_enable(CHANNEL); + + /* Set up clock routing */ + galmpsc_connect(CHANNEL, GALMPSC_CONNECT); + galmpsc_route_serial(CHANNEL, GALMPSC_CONNECT); + galmpsc_route_rx_clock(CHANNEL, CHANNEL); + galmpsc_route_tx_clock(CHANNEL, CHANNEL); + + /* reset MPSC state */ + galmpsc_shutdown(CHANNEL); + + /* SDMA CONFIG */ + galsdma_set_burstsize(CHANNEL, L1_CACHE_BYTES/8); /* in 64 bit words (8 bytes) */ + galsdma_set_txle(CHANNEL); + galsdma_set_rxle(CHANNEL); + galsdma_set_RC(CHANNEL, 0xf); + galsdma_set_SFM(CHANNEL); + galsdma_set_RFT(CHANNEL); + + /* MPSC CONFIG */ + galmpsc_write_config_regs(CHANNEL, GALMPSC_UART); + galmpsc_config_channel_regs(CHANNEL); + galmpsc_set_char_length(CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ + galmpsc_set_parity(CHANNEL, GALMPSC_PARITY_NONE); /* N */ + galmpsc_set_stop_bit_length(CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ + + /* COMM_MPSC CONFIG */ +#ifdef SOFTWARE_CACHE_MANAGEMENT + galmpsc_set_snoop(CHANNEL, 0); /* disable snoop */ +#else + galmpsc_set_snoop(CHANNEL, 1); /* enable snoop */ +#endif + + return 0; +} + +void +mpsc_init2(void) +{ + int i; + + mpsc_putchar = mpsc_putchar_sdma; + + /* RX descriptors */ + rx_desc_base = (unsigned int *)malloc(((RX_DESC+1)*8) * + sizeof(unsigned int)); + + /* align descriptors */ + rx_desc_base = (unsigned int *) + (((unsigned int)rx_desc_base+32) & 0xFFFFFFF0); + + rx_desc_index = 0; + + memset((void *)rx_desc_base, 0, (RX_DESC*8)*sizeof(unsigned int)); + + for (i = 0; i < RX_DESC; i++) { + rx_desc_base[i*8 + 3] = (unsigned int)&rx_desc_base[i*8 + 4]; /* Buffer */ + rx_desc_base[i*8 + 2] = (unsigned int)&rx_desc_base[(i+1)*8]; /* Next descriptor */ + rx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* Command & control */ + rx_desc_base[i*8] = 0x00100000; + } + rx_desc_base[(i-1)*8 + 2] = (unsigned int)&rx_desc_base[0]; + + FLUSH_DCACHE(&rx_desc_base[0], &rx_desc_base[RX_DESC*8]); + GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&rx_desc_base[0]); + + /* TX descriptors */ + tx_desc_base = (unsigned int *)malloc(((TX_DESC+1)*8) * + sizeof(unsigned int)); + + /* align descriptors */ + tx_desc_base = (unsigned int *) + (((unsigned int)tx_desc_base+32) & 0xFFFFFFF0); + + tx_desc_index = -1; + + memset((void *)tx_desc_base, 0, (TX_DESC*8)*sizeof(unsigned int)); + + for (i = 0; i < TX_DESC; i++) { + tx_desc_base[i*8 + 5] = (unsigned int)0x23232323; + tx_desc_base[i*8 + 4] = (unsigned int)0x23232323; + tx_desc_base[i*8 + 3] = (unsigned int)&tx_desc_base[i*8 + 4]; + tx_desc_base[i*8 + 2] = (unsigned int)&tx_desc_base[(i+1)*8]; + tx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST; + + /* set sbytecnt and shadow byte cnt to 1 */ + tx_desc_base[i*8] = 0x00010001; + } + tx_desc_base[(i-1)*8 + 2] = (unsigned int)&tx_desc_base[0]; + + FLUSH_DCACHE(&tx_desc_base[0], &tx_desc_base[TX_DESC*8]); + + udelay(100); + + galsdma_enable_rx(); + + return; +} + +int +galbrg_set_baudrate(int channel, int rate) +{ + DECLARE_GLOBAL_DATA_PTR; + int clock; + + galbrg_disable(channel); + +#ifdef CONFIG_ZUMA_V2 + /* from tclk */ + clock = (CFG_BUS_HZ/(16*rate)) - 1; +#else + clock = (3686400/(16*rate)) - 1; +#endif + + galbrg_set_CDV(channel, clock); + + galbrg_enable(channel); + + MIRROR_HACK->baudrate = rate; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Below are all the private functions that no one else needs */ + +static int +galbrg_set_CDV(int channel, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp &= 0xFFFF0000; + temp |= (value & 0x0000FFFF); + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel,GALBRG_REG_GAP, temp); + + return 0; +} + +static int +galbrg_enable(int channel) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp |= 0x00010000; + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_disable(int channel) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp &= 0xFFFEFFFF; + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_set_clksrc(int channel, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP); + temp &= 0xFF83FFFF; + temp |= (value << 18); + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_set_CUV(int channel, int value) +{ + GT_REG_WRITE(GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); + + return 0; +} + +#if 0 +static int +galbrg_reset(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x20000; + GT_REG_WRITE(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} +#endif + +static int +galsdma_set_RFT(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000001; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_SFM(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000002; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_rxle(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000040; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_txle(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000080; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_RC(int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp &= ~0x0000003c; + temp |= (value << 2); + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_burstsize(int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp &= 0xFFFFCFFF; + switch (value) { + case 8: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x3 << 12))); + break; + + case 4: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x2 << 12))); + break; + + case 2: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x1 << 12))); + break; + + case 1: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x0 << 12))); + break; + + default: + return -1; + break; + } + + return 0; +} + +static int +galmpsc_connect(int channel, int connect) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_ROUTING_REGISTER); + + if ((channel == 0) && connect) + temp &= ~0x00000007; + else if ((channel == 1) && connect) + temp &= ~(0x00000007 << 6); + else if ((channel == 0) && !connect) + temp |= 0x00000007; + else + temp |= (0x00000007 << 6); + + /* Just in case... */ + temp &= 0x3fffffff; + + GT_REG_WRITE_MIRROR_G(GALMPSC_ROUTING_REGISTER, temp); + + return 0; +} + +static int +galmpsc_route_serial(int channel, int connect) +{ + unsigned int temp; + + temp = GTREGREAD(GALMPSC_SERIAL_MULTIPLEX); + + if ((channel == 0) && connect) + temp |= 0x00000100; + else if ((channel == 1) && connect) + temp |= 0x00001000; + else if ((channel == 0) && !connect) + temp &= ~0x00000100; + else + temp &= ~0x00001000; + + GT_REG_WRITE(GALMPSC_SERIAL_MULTIPLEX,temp); + + return 0; +} + +static int +galmpsc_route_rx_clock(int channel, int brg) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_RxC_ROUTE); + + if (channel == 0) + temp |= brg; + else + temp |= (brg << 8); + + GT_REG_WRITE_MIRROR_G(GALMPSC_RxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_route_tx_clock(int channel, int brg) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_TxC_ROUTE); + + if (channel == 0) + temp |= brg; + else + temp |= (brg << 8); + + GT_REG_WRITE_MIRROR_G(GALMPSC_TxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_write_config_regs(int mpsc, int mode) +{ + if (mode == GALMPSC_UART) { + /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ + GT_REG_WRITE(GALMPSC_MCONF_LOW + (mpsc*GALMPSC_REG_GAP), + 0x000004c4); + + /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ + GT_REG_WRITE(GALMPSC_MCONF_HIGH +(mpsc*GALMPSC_REG_GAP), + 0x024003f8); + /* 22 2222 1111 */ + /* 54 3210 9876 */ + /* 0000 0010 0000 0000 */ + /* 1 */ + /* 098 7654 3210 */ + /* 0000 0011 1111 1000 */ + } else + return -1; + + return 0; +} + +static int +galmpsc_config_channel_regs(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, 0); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_3+(mpsc*GALMPSC_REG_GAP), 1); + GT_REG_WRITE(GALMPSC_CHANNELREG_4+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_5+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_6+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_7+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_8+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_9+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_10+(mpsc*GALMPSC_REG_GAP), 0); + + galmpsc_set_brkcnt(mpsc, 0x3); + galmpsc_set_tcschar(mpsc, 0xab); + + return 0; +} + +static int +galmpsc_set_brkcnt(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP); + temp &= 0x0000FFFF; + temp |= (value << 16); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_tcschar(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP); + temp &= 0xFFFF0000; + temp |= value; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_char_length(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP); + temp &= 0xFFFFCFFF; + temp |= (value << 12); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_stop_bit_length(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP); + temp |= (value << 14); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP,temp); + + return 0; +} + +static int +galmpsc_set_parity(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + if (value != -1) { + temp &= 0xFFF3FFF3; + temp |= ((value << 18) | (value << 2)); + temp |= ((value << 17) | (value << 1)); + } else { + temp &= 0xFFF1FFF1; + } + + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_enter_hunt(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + temp |= 0x80000000; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp); + + /* Should Poll on Enter Hunt bit, but the register is write-only */ + /* errata suggests pausing 100 system cycles */ + udelay(100); + + return 0; +} + + +static int +galmpsc_shutdown(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + /* cause RX abort (clears RX) */ + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; + temp &= ~MPSC_ENTER_HUNT; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP,temp); + + GT_REG_WRITE(GALSDMA_0_COM_REG, 0); + GT_REG_WRITE(GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); + + /* shut down the MPSC */ + GT_REG_WRITE(GALMPSC_MCONF_LOW, 0); + GT_REG_WRITE(GALMPSC_MCONF_HIGH, 0); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG, mpsc, GALMPSC_REG_GAP,0); + + udelay(100); + + /* shut down the sdma engines. */ + /* reset config to default */ + GT_REG_WRITE(GALSDMA_0_CONF_REG, 0x000000fc); + + udelay(100); + + /* clear the SDMA current and first TX and RX pointers */ + GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR, 0); + GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR, 0); + GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR, 0); + + udelay(100); + + return 0; +} + +static void +galsdma_enable_rx(void) +{ + int temp; + + /* Enable RX processing */ + temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF)); + temp |= RX_ENABLE; + GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp); + + galmpsc_enter_hunt(CHANNEL); +} + +static int +galmpsc_set_snoop(int mpsc, int value) +{ + int reg = mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : MPSC_0_ADDRESS_CONTROL_LOW; + int temp=GTREGREAD(reg); + if(value) + temp |= (1<< 6) | (1<<14) | (1<<22) | (1<<30); + else + temp &= ~((1<< 6) | (1<<14) | (1<<22) | (1<<30)); + GT_REG_WRITE(reg, temp); + return 0; +} diff --git a/board/evb64260/zuma_pbb.c b/board/evb64260/zuma_pbb.c new file mode 100644 index 0000000..10c4845 --- /dev/null +++ b/board/evb64260/zuma_pbb.c @@ -0,0 +1,200 @@ +#include <common.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) +#include <command.h> +#include <cmd_bsp.h> +#endif + +#include <pci.h> +#include <galileo/pci.h> +#include "zuma_pbb.h" + +#undef DEBUG + +#define PAT_LO 0x00010203 +#define PAT_HI 0x04050607 + +static PBB_DMA_REG_MAP *zuma_pbb_reg = NULL; + +static char test_buf1[2048]; +static char test_buf2[2048]; + +int zuma_test_dma (int cmd, int size) +{ + static const char *const test_legend[] = { + "write", "verify", + "copy", "compare", + "write inc", "verify inc" + }; + register int i, j; + unsigned int p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff); + unsigned int p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff); + volatile unsigned int *ps = (unsigned int *) p1; + volatile unsigned int *pd = (unsigned int *) p2; + unsigned int funct, pat_lo = PAT_LO, pat_hi = PAT_HI; + DMA_INT_STATUS stat; + int ret = 0; + + if (!zuma_pbb_reg) { + printf ("not initted\n"); + return -1; + } + + if (cmd < 0 || cmd > 5) { + printf ("inv cmd %d\n", cmd); + return -1; + } + + if (cmd == 2 || cmd == 3) { + /* not implemented */ + return 0; + } + + if (size <= 0 || size > 1024) + size = 1024; + + size &= (~7); /* throw away bottom 3 bits */ + + p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff); + p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff); + + memset ((void *) p1, 0, size); + memset ((void *) p2, 0, size); + + for (i = 0; i < size / 4; i += 2) { + ps[i] = pat_lo; + ps[i + 1] = pat_hi; + if (cmd == 4 || cmd == 5) { + unsigned char *pl = (unsigned char *) &pat_lo; + unsigned char *ph = (unsigned char *) &pat_hi; + + for (j = 0; j < 4; j++) { + pl[j] += 8; + ph[j] += 8; + } + } + } + + funct = (1 << 31) | (cmd << 24) | (size); + + zuma_pbb_reg->int_mask.pci_bits.chan0 = + EOF_RX_FLAG | EOF_TX_FLAG | EOB_TX_FLAG; + + zuma_pbb_reg->debug_57 = PAT_LO; /* patl */ + zuma_pbb_reg->debug_58 = PAT_HI; /* path */ + + zuma_pbb_reg->debug_54 = cpu_to_le32 (p1); /* src 0x01b0 */ + zuma_pbb_reg->debug_55 = cpu_to_le32 (p2); /* dst 0x01b8 */ + zuma_pbb_reg->debug_56 = cpu_to_le32 (funct); /* func, 0x01c0 */ + + /* give DMA time to chew on things.. dont use DRAM or PCI */ + /* if you can avoid it. */ + do { + for (i = 0; i < 1000 * 10; i++); + } while (le32_to_cpu (zuma_pbb_reg->debug_56) & (1 << 31)); + + stat.word = zuma_pbb_reg->status.word; + zuma_pbb_reg->int_mask.word = 0; + + printf ("stat: %08x (%x)\n", stat.word, stat.pci_bits.chan0); + + printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56)); + printf ("src @%08x: %08x %08x %08x %08x\n", p1, ps[0], ps[1], ps[2], + ps[3]); + printf ("dst @%08x: %08x %08x %08x %08x\n", p2, pd[0], pd[1], pd[2], + pd[3]); + printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56)); + + + if (cmd == 0 || cmd == 4) { + /* this is a write */ + if (!(stat.pci_bits.chan0 & EOF_RX_FLAG) || /* not done */ + (memcmp ((void *) ps, (void *) pd, size) != 0)) { /* cmp error */ + for (i = 0; i < size / 4; i += 2) { + if ((ps[i] != pd[i]) || (ps[i + 1] != pd[i + 1])) { + printf ("s @%p:%08x %08x\n", &ps[i], ps[i], ps[i + 1]); + printf ("d @%p:%08x %08x\n", &pd[i], pd[i], pd[i + 1]); + } + } + ret = -1; + } + } else { + /* this is a verify */ + if (!(stat.pci_bits.chan0 & EOF_TX_FLAG) || /* not done */ + (stat.pci_bits.chan0 & EOB_TX_FLAG)) { /* cmp error */ + printf ("%08x: %08x %08x\n", + le32_to_cpu (zuma_pbb_reg->debug_63), + zuma_pbb_reg->debug_61, zuma_pbb_reg->debug_62); + ret = -1; + } + } + + printf ("%s cmd %d, %d bytes: %s!\n", test_legend[cmd], cmd, size, + (ret == 0) ? "PASSED" : "FAILED"); + return 0; +} + +void zuma_init_pbb (void) +{ + unsigned int iobase; + pci_dev_t dev = + pci_find_device (VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0); + + if (dev == -1) { + printf ("no zuma pbb\n"); + return; + } + + pci_read_config_dword (dev, PCI_BASE_ADDRESS_0, &iobase); + + zuma_pbb_reg = + (PBB_DMA_REG_MAP *) (iobase & PCI_BASE_ADDRESS_MEM_MASK); + + if (!zuma_pbb_reg) { + printf ("zuma pbb bar none! (hah hah, get it?)\n"); + return; + } + + zuma_pbb_reg->int_mask.word = 0; + + printf ("pbb @ %p v%d.%d, timestamp %08x\n", zuma_pbb_reg, + zuma_pbb_reg->version.pci_bits.rev_major, + zuma_pbb_reg->version.pci_bits.rev_minor, + zuma_pbb_reg->timestamp); + +} + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +static int last_cmd = 4; /* write increment */ +static int last_size = 64; + +int +do_zuma_init_pbb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + zuma_init_pbb (); + return 0; +} + +int +do_zuma_test_dma (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc > 1) { + last_cmd = simple_strtoul (argv[1], NULL, 10); + } + if (argc > 2) { + last_size = simple_strtoul (argv[2], NULL, 10); + } + zuma_test_dma (last_cmd, last_size); + return 0; +} + +int +do_zuma_init_mbox (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + zuma_mbox_init (); + return 0; +} + +#endif /* CFG_CMD_BSP */ diff --git a/board/evb64260/zuma_pbb_mbox.c b/board/evb64260/zuma_pbb_mbox.c new file mode 100644 index 0000000..5131339 --- /dev/null +++ b/board/evb64260/zuma_pbb_mbox.c @@ -0,0 +1,187 @@ +#include <common.h> +#include <galileo/pci.h> +#include <net.h> +#include <pci.h> + +#include "zuma_pbb.h" +#include "zuma_pbb_mbox.h" + + +struct _zuma_mbox_dev zuma_mbox_dev; + + +static int zuma_mbox_write(struct _zuma_mbox_dev *dev, unsigned int data) +{ + unsigned int status, count = 0, i; + + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + + while((status & OUT_PENDING) && count < 1000) { + count++; + for(i=0;i<1000;i++); + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + } + if(count < 1000) { + /* if SET it means msg pending */ + /* printf("mbox real write %08x\n",data); */ + dev->sip->mbox_out = cpu_to_le32(data); + return 4; + } + + printf("mbox tx timeout\n"); + return 0; +} + +static int zuma_mbox_read(struct _zuma_mbox_dev *dev, unsigned int *data) +{ + unsigned int status, count = 0, i; + + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + + while(!(status & IN_VALID) && count < 1000) { + count++; + for(i=0;i<1000;i++); + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + } + if(count < 1000) { + /* if SET it means msg pending */ + *data=le32_to_cpu(dev->sip->mbox_in); + /*printf("mbox real read %08x\n", *data); */ + return 4; + } + printf("mbox rx timeout\n"); + return 0; +} + +static int zuma_mbox_do_one_mailbox(unsigned int out, unsigned int *in) +{ + int ret; + ret=zuma_mbox_write(&zuma_mbox_dev,out); + /*printf("write 0x%08x (%d bytes)\n", out, ret); */ + if(ret!=4) return -1; + ret=zuma_mbox_read(&zuma_mbox_dev,in); + /*printf("read 0x%08x (%d bytes)\n", *in, ret); */ + if(ret!=4) return -1; + return 0; +} + + +#define RET_IF_FAILED(x) if ((x) == -1) return -1 + +static int zuma_mbox_do_all_mailbox(void) +{ + unsigned int data_in; + unsigned short sdata_in; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_START, &data_in)); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACL, &data_in)); + memcpy(zuma_acc_mac+2,&data_in,4); + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACH, &data_in)); + sdata_in=data_in&0xffff; + memcpy(zuma_acc_mac,&sdata_in,2); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_IP, &data_in)); + zuma_ip=data_in; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_SLOT, &data_in)); + zuma_slot_bac=data_in>>3; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_BAUD, &data_in)); + zuma_console_baud = data_in & 0xffff; + zuma_debug_baud = data_in >> 16; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_ENG_PRV_MACL, &data_in)); + memcpy(zuma_prv_mac+2,&data_in,4); + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_ENG_PRV_MACH, &data_in)); + sdata_in=data_in&0xffff; + memcpy(zuma_prv_mac,&sdata_in,2); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_DONE, &data_in)); + + return 0; +} + + +static void +zuma_mbox_dump(void) +{ + printf("ACC MAC=%04x%08x\n",*(unsigned short *)(&zuma_acc_mac),*(unsigned int *)((char *)&zuma_acc_mac+2)); + printf("PRV MAC=%04x%08x\n",*(unsigned short *)(&zuma_prv_mac),*(unsigned int *)((char *)&zuma_prv_mac+2)); + printf("slot:bac=%d:%d\n",(zuma_slot_bac>>2)&0xf, zuma_slot_bac & 0x3); + printf("BAUD1=%d BAUD2=%d\n",zuma_console_baud,zuma_debug_baud); +} + + +static void +zuma_mbox_setenv(void) +{ + unsigned char *data, buf[32]; + unsigned char save = 0; + + data = getenv("baudrate"); + + if(!data || (zuma_console_baud != simple_strtoul(data, NULL, 10))) { + sprintf(buf, "%6d", zuma_console_baud); + setenv("baudrate", buf); + save=1; + printf("baudrate doesn't match from mbox\n"); + } + + ip_to_string(zuma_ip, buf); + setenv("ipaddr", buf); + + sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x", + zuma_prv_mac[0], + zuma_prv_mac[1], + zuma_prv_mac[2], + zuma_prv_mac[3], + zuma_prv_mac[4], + zuma_prv_mac[5]); + setenv("ethaddr", buf); + + sprintf(buf,"%02x",zuma_slot_bac); + setenv("bacslot", buf); + + if(save) + saveenv(); +} + +/** + * zuma_mbox_init: + */ + +int zuma_mbox_init(void) +{ + unsigned int iobase; + memset(&zuma_mbox_dev, 0, sizeof(struct _zuma_mbox_dev)); + + zuma_mbox_dev.dev = pci_find_device(VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0); + + if(zuma_mbox_dev.dev == -1) { + printf("no zuma pbb\n"); + return -1; + } + + pci_read_config_dword(zuma_mbox_dev.dev, PCI_BASE_ADDRESS_0, &iobase); + + zuma_mbox_dev.sip = (PBB_DMA_REG_MAP *) (iobase & PCI_BASE_ADDRESS_MEM_MASK); + + zuma_mbox_dev.sip->int_mask.word=0; + + printf("pbb @ %p v%d.%d, timestamp %08x\n", zuma_mbox_dev.sip, + zuma_mbox_dev.sip->version.pci_bits.rev_major, + zuma_mbox_dev.sip->version.pci_bits.rev_minor, + zuma_mbox_dev.sip->timestamp); + + if (zuma_mbox_do_all_mailbox() == -1) { + printf("mailbox failed.. no ACC?\n"); + return -1; + } + + zuma_mbox_dump(); + + zuma_mbox_setenv(); + + return 0; +} diff --git a/board/fads/fads.c b/board/fads/fads.c new file mode 100644 index 0000000..3b97f51 --- /dev/null +++ b/board/fads/fads.c @@ -0,0 +1,876 @@ +/* + * (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 <common.h> +#include <config.h> +#include <mpc8xx.h> +#include "fads.h" + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFFFFF + +#if defined(CONFIG_DRAM_50MHZ) +/* 50MHz tables */ +const uint dram_60ns[] = +{ 0x8fffec24, 0x0fffec04, 0x0cffec04, 0x00ffec04, + 0x00ffec00, 0x37ffec47, 0xffffffff, 0xffffffff, + 0x8fffec24, 0x0fffec04, 0x08ffec04, 0x00ffec0c, + 0x03ffec00, 0x00ffec44, 0x00ffcc08, 0x0cffcc44, + 0x00ffec0c, 0x03ffec00, 0x00ffec44, 0x00ffcc00, + 0x3fffc847, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x11bfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xc0ffcc84, 0x00ffcc04, 0x07ffcc04, 0x3fffcc06, + 0xffffcc85, 0xffffcc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint dram_70ns[] = +{ 0x8fffcc24, 0x0fffcc04, 0x0cffcc04, 0x00ffcc04, + 0x00ffcc00, 0x37ffcc47, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0fffcc04, 0x0cffcc04, 0x00ffcc04, + 0x00ffcc08, 0x0cffcc44, 0x00ffec0c, 0x03ffec00, + 0x00ffec44, 0x00ffcc08, 0x0cffcc44, 0x00ffec04, + 0x00ffec00, 0x3fffec47, 0xffffffff, 0xffffffff, + 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x11bfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xe0ffcc84, 0x00ffcc04, 0x00ffcc04, 0x0fffcc04, + 0x7fffcc06, 0xffffcc85, 0xffffcc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint edo_60ns[] = +{ 0x8ffbec24, 0x0ff3ec04, 0x0cf3ec04, 0x00f3ec04, + 0x00f3ec00, 0x37f7ec47, 0xffffffff, 0xffffffff, + 0x8fffec24, 0x0ffbec04, 0x0cf3ec04, 0x00f3ec0c, + 0x0cf3ec00, 0x00f3ec4c, 0x0cf3ec00, 0x00f3ec4c, + 0x0cf3ec00, 0x00f3ec44, 0x03f3ec00, 0x3ff7ec47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x11bfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xc0ffcc84, 0x00ffcc04, 0x07ffcc04, 0x3fffcc06, + 0xffffcc85, 0xffffcc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint edo_70ns[] = +{ 0x8ffbcc24, 0x0ff3cc04, 0x0cf3cc04, 0x00f3cc04, + 0x00f3cc00, 0x37f7cc47, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc0c, + 0x03f3cc00, 0x00f3cc44, 0x00f3ec0c, 0x0cf3ec00, + 0x00f3ec4c, 0x03f3ec00, 0x00f3ec44, 0x00f3cc00, + 0x33f7cc47, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x11bfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c, + 0x0cafcc00, 0x33bfcc47, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xe0ffcc84, 0x00ffcc04, 0x00ffcc04, 0x0fffcc04, + 0x7fffcc04, 0xffffcc86, 0xffffcc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +#elif defined(CONFIG_DRAM_25MHZ) + +/* 25MHz tables */ + +const uint dram_60ns[] = +{ 0x0fffcc04, 0x08ffcc00, 0x33ffcc47, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fffcc24, 0x0fffcc04, 0x08ffcc00, 0x03ffcc4c, + 0x08ffcc00, 0x03ffcc4c, 0x08ffcc00, 0x03ffcc4c, + 0x08ffcc00, 0x33ffcc47, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fafcc04, 0x08afcc00, 0x3fbfcc47, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fafcc04, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00, + 0x01afcc4c, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00, + 0x31bfcc43, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x80ffcc84, 0x13ffcc04, 0xffffcc87, 0xffffcc05, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint dram_70ns[] = +{ 0x0fffec04, 0x08ffec04, 0x00ffec00, 0x3fffcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fffcc24, 0x0fffcc04, 0x08ffcc00, 0x03ffcc4c, + 0x08ffcc00, 0x03ffcc4c, 0x08ffcc00, 0x03ffcc4c, + 0x08ffcc00, 0x33ffcc47, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fafcc04, 0x08afcc00, 0x3fbfcc47, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fafcc04, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00, + 0x01afcc4c, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00, + 0x31bfcc43, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xc0ffcc84, 0x01ffcc04, 0x7fffcc86, 0xffffcc05, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint edo_60ns[] = +{ 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc00, 0x33f7cc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0ffbcc04, 0x09f3cc0c, 0x09f3cc0c, 0x09f3cc0c, + 0x08f3cc00, 0x3ff7cc47, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fefcc04, 0x08afcc04, 0x00afcc00, 0x3fbfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fefcc04, 0x08afcc00, 0x07afcc48, 0x08afcc48, + 0x08afcc48, 0x39bfcc47, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x80ffcc84, 0x13ffcc04, 0xffffcc87, 0xffffcc05, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + +const uint edo_70ns[] = +{ 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc00, 0x33f7cc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0ffbec04, 0x08f3ec04, 0x03f3ec48, 0x08f3cc00, + 0x0ff3cc4c, 0x08f3cc00, 0x0ff3cc4c, 0x08f3cc00, + 0x3ff7cc47, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fefcc04, 0x08afcc04, 0x00afcc00, 0x3fbfcc47, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0fefcc04, 0x08afcc00, 0x07afcc4c, 0x08afcc00, + 0x07afcc4c, 0x08afcc00, 0x07afcc4c, 0x08afcc00, + 0x37bfcc47, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xc0ffcc84, 0x01ffcc04, 0x7fffcc86, 0xffffcc05, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff }; + + +#else +#error dram not correct defined - use CONFIG_DRAM_25MHZ or CONFIG_DRAM_50MHZ +#endif + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + uint k; + + puts ("Board: "); + +#ifdef CONFIG_FADS + k = (*((uint *)BCSR3) >> 24) & 0x3f; + + switch(k) { + case 0x03 : + case 0x20 : + case 0x21 : + case 0x22 : + case 0x23 : + case 0x24 : + case 0x3f : + puts ("FADS"); + break; + + default : + printf("unknown board (0x%02x)\n", k); + return -1; + } + + printf(" with db "); + + switch(k) { + case 0x03 : + puts ("MPC823"); + break; + case 0x20 : + puts ("MPC801"); + break; + case 0x21 : + puts ("MPC850"); + break; + case 0x22 : + puts ("MPC821, MPC860 / MPC860SAR / MPC860T"); + break; + case 0x23 : + puts ("MPC860SAR"); + break; + case 0x24 : + puts ("MPC860T"); + break; + case 0x3f : + puts ("MPC850SAR"); + break; + } + + printf(" rev "); + + k = (((*((uint *)BCSR3) >> 23) & 1) << 3) + | (((*((uint *)BCSR3) >> 19) & 1) << 2) + | (((*((uint *)BCSR3) >> 16) & 3)); + + switch(k) { + case 0x01 : + puts ("ENG or PILOT\n"); + break; + + default: + printf("unknown (0x%x)\n", k); + return -1; + } + + return 0; +#endif /* CONFIG_FADS */ + +#ifdef CONFIG_ADS + printf("ADS rev "); + + k = (((*((uint *)BCSR3) >> 23) & 1) << 3) + | (((*((uint *)BCSR3) >> 19) & 1) << 2) + | (((*((uint *)BCSR3) >> 16) & 3)); + + switch(k) { + case 0x00 : puts ("ENG - this board sucks, check the errata, not supported\n"); + return -1; + case 0x01 : puts ("PILOT - warning, read errata \n"); break; + case 0x02 : puts ("A - warning, read errata \n"); break; + case 0x03 : puts ("B \n"); break; + default : printf ("unknown revision (0x%x)\n", k); return -1; + } + + return 0; +#endif /* CONFIG_ADS */ + +} + +/* ------------------------------------------------------------------------- */ +int _draminit(uint base, uint noMbytes, uint edo, uint delay) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + /* init upm */ + + switch(delay) + { + case 70: + { + if(edo) + { + upmconfig(UPMA, (uint *) edo_70ns, sizeof(edo_70ns)/sizeof(uint)); + } + else + { + upmconfig(UPMA, (uint *) dram_70ns, sizeof(dram_70ns)/sizeof(uint)); + } + + break; + } + + case 60: + { + if(edo) + { + upmconfig(UPMA, (uint *) edo_60ns, sizeof(edo_60ns)/sizeof(uint)); + } + else + { + upmconfig(UPMA, (uint *) dram_60ns, sizeof(dram_60ns)/sizeof(uint)); + } + + break; + } + + default : + return -1; + } + + memctl->memc_mptpr = 0x0400; /* divide by 16 */ + + switch(noMbytes) + { + + case 8: /* 8 Mbyte uses both CS3 and CS2 */ + { + memctl->memc_mamr = 0x13a01114; + memctl->memc_or3 = 0xffc00800; + memctl->memc_br3 = 0x00400081 + base; + memctl->memc_or2 = 0xffc00800; + break; + } + + case 4: /* 4 Mbyte uses only CS2 */ + { + memctl->memc_mamr = 0x13a01114; + memctl->memc_or2 = 0xffc00800; + break; + } + + case 32: /* 32 Mbyte uses both CS3 and CS2 */ + { + memctl->memc_mamr = 0x13b01114; + memctl->memc_or3 = 0xff000800; + memctl->memc_br3 = 0x01000081 + base; + memctl->memc_or2 = 0xff000800; + break; + } + + case 16: /* 16 Mbyte uses only CS2 */ + { +#ifdef CONFIG_ADS + memctl->memc_mamr = 0x60b21114; +#else + memctl->memc_mamr = 0x13b01114; +#endif + memctl->memc_or2 = 0xff000800; + break; + } + + default: + return -1; + } + + memctl->memc_br2 = 0x81 + base; /* use upma */ + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void _dramdisable(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + memctl->memc_br2 = 0x00000000; + memctl->memc_br3 = 0x00000000; + + /* maybe we should turn off upma here or something */ +} + +#if defined(CONFIG_SDRAM_100MHZ) + +/* ------------------------------------------------------------------------- */ +/* sdram table by Dan Malek */ + +/* This has the stretched early timing so the 50 MHz + * processor can make the 100 MHz timing. This will + * work at all processor speeds. + */ + +#define SDRAM_MPTPRVALUE 0x0400 + +#define SDRAM_MBMRVALUE0 0xc3802114 /* (16-14) 50 MHz */ +#define SDRAM_MBMRVALUE1 SDRAM_MBMRVALUE0 + +#define SDRAM_OR4VALUE 0xffc00a00 +#define SDRAM_BR4VALUE 0x000000c1 /* base address will be or:ed on */ + +#define SDRAM_MARVALUE 0x88 + +#define SDRAM_MCRVALUE0 0x80808111 /* run pattern 0x11 */ +#define SDRAM_MCRVALUE1 SDRAM_MCRVALUE0 + + +const uint sdram_table[] = +{ + /* single read. (offset 0 in upm RAM) */ + 0xefebfc24, 0x1f07fc24, 0xeeaefc04, 0x11adfc04, + 0xefbbbc00, 0x1ff77c45, 0xffffffff, 0xffffffff, + + /* burst read. (offset 8 in upm RAM) */ + 0xefebfc24, 0x1f07fc24, 0xeeaefc04, 0x10adfc04, + 0xf0affc00, 0xf0affc00, 0xf1affc00, 0xefbbbc00, + 0x1ff77c45, 0xeffbbc04, 0x1ff77c34, 0xefeabc34, + 0x1fb57c35, 0xffffffff, 0xffffffff, 0xffffffff, + + /* single write. (offset 18 in upm RAM) */ + 0xefebfc24, 0x1f07fc24, 0xeeaebc00, 0x01b93c04, + 0x1ff77c45, 0xffffffff, 0xffffffff, 0xffffffff, + + /* burst write. (offset 20 in upm RAM) */ + 0xefebfc24, 0x1f07fc24, 0xeeaebc00, 0x10ad7c00, + 0xf0affc00, 0xf0affc00, 0xe1bbbc04, 0x1ff77c45, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + + /* refresh. (offset 30 in upm RAM) */ + 0xeffafc84, 0x1ff5fc04, 0xfffffc04, 0xfffffc04, + 0xfffffc84, 0xfffffc07, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + + /* exception. (offset 3c in upm RAM) */ + 0xeffffc06, 0x1ffffc07, 0xffffffff, 0xffffffff }; + +#elif defined(CONFIG_SDRAM_50MHZ) + +/* ------------------------------------------------------------------------- */ +/* sdram table stolen from the fads manual */ +/* for chip MB811171622A-100 */ + +/* this table is for 32-50MHz operation */ + +#define _not_used_ 0xffffffff + +#define SDRAM_MPTPRVALUE 0x0400 + +#define SDRAM_MBMRVALUE0 0x80802114 /* refresh at 32MHz */ +#define SDRAM_MBMRVALUE1 0x80802118 + +#define SDRAM_OR4VALUE 0xffc00a00 +#define SDRAM_BR4VALUE 0x000000c1 /* base address will be or:ed on */ + +#define SDRAM_MARVALUE 0x88 + +#define SDRAM_MCRVALUE0 0x80808105 +#define SDRAM_MCRVALUE1 0x80808130 + +const uint sdram_table[] = +{ + /* single read. (offset 0 in upm RAM) */ + 0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00, + 0x1ff77c47, + + /* MRS initialization (offset 5) */ + + 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) */ + 0x1f27fc04, 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_ }; + +/* ------------------------------------------------------------------------- */ +#else +#error SDRAM not correctly configured +#endif + +int _initsdram(uint base, uint noMbytes) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + if(noMbytes != 4) + { + return -1; + } + + upmconfig(UPMB, (uint *)sdram_table,sizeof(sdram_table)/sizeof(uint)); + + memctl->memc_mptpr = SDRAM_MPTPRVALUE; + + /* Configure the refresh (mostly). This needs to be + * based upon processor clock speed and optimized to provide + * the highest level of performance. For multiple banks, + * this time has to be divided by the number of banks. + * Although it is not clear anywhere, it appears the + * refresh steps through the chip selects for this UPM + * on each refresh cycle. + * We have to be careful changing + * UPM registers after we ask it to run these commands. + */ + + memctl->memc_mbmr = SDRAM_MBMRVALUE0; + memctl->memc_mar = SDRAM_MARVALUE; /* MRS code */ + + udelay(200); + + /* Now run the precharge/nop/mrs commands. + */ + + memctl->memc_mcr = 0x80808111; /* run pattern 0x11 */ + + udelay(200); + + /* Run 8 refresh cycles */ + + memctl->memc_mcr = SDRAM_MCRVALUE0; + + udelay(200); + + memctl->memc_mbmr = SDRAM_MBMRVALUE1; + memctl->memc_mcr = SDRAM_MCRVALUE1; + + udelay(200); + + memctl->memc_mbmr = SDRAM_MBMRVALUE0; + + memctl->memc_or4 = SDRAM_OR4VALUE; + memctl->memc_br4 = SDRAM_BR4VALUE | base; + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void _sdramdisable(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + memctl->memc_br4 = 0x00000000; + + /* maybe we should turn off upmb here or something */ +} + +/* ------------------------------------------------------------------------- */ + +int initsdram(uint base, uint *noMbytes) +{ + uint m = 4; + + *((uint *)BCSR1) |= BCSR1_SDRAM_EN; /* enable sdram */ + /* _fads_sdraminit needs access to sdram */ + *noMbytes = m; + + if(!_initsdram(base, m)) + { + + return 0; + } + else + { + *((uint *)BCSR1) &= ~BCSR1_SDRAM_EN; /* disable sdram */ + + _sdramdisable(); + + return -1; + } +} + +long int initdram (int board_type) +{ +#ifdef CONFIG_ADS + /* ADS: has no SDRAM, so start DRAM at 0 */ + uint base = (unsigned long)0x0; +#else + /* FADS: has 4MB SDRAM, put DRAM above it */ + uint base = (unsigned long)0x00400000; +#endif + uint k, m, s; + + k = (*((uint *)BCSR2) >> 23) & 0x0f; + + m = 0; + + switch(k & 0x3) + { + /* "MCM36100 / MT8D132X" */ + case 0x00 : + m = 4; + break; + + /* "MCM36800 / MT16D832X" */ + case 0x01 : + m = 32; + break; + /* "MCM36400 / MT8D432X" */ + case 0x02 : + m = 16; + break; + /* "MCM36200 / MT16D832X ?" */ + case 0x03 : + m = 8; + break; + + } + + switch(k >> 2) + { + case 0x02 : + k = 70; + break; + + case 0x03 : + k = 60; + break; + + default : + printf("unknown dramdelay (0x%x) - defaulting to 70 ns", k); + k = 70; + } + +#ifdef CONFIG_FADS + /* the FADS is missing this bit, all rams treated as non-edo */ + s = 0; +#else + s = (*((uint *)BCSR2) >> 27) & 0x01; +#endif + + if(!_draminit(base, m, s, k)) + { +#ifdef CONFIG_FADS + uint sdramsz; +#endif + *((uint *)BCSR1) &= ~BCSR1_DRAM_EN; /* enable dram */ + +#ifdef CONFIG_FADS + if (!initsdram(0x00000000, &sdramsz)) { + m += sdramsz; + printf("(%u MB SDRAM) ", sdramsz); + } else { + _dramdisable(); + + /******************************** + *DRAM ERROR, HALT PROCESSOR + *********************************/ + while(1); + + return -1; + } +#endif + + return (m << 20); + } + else + { + _dramdisable(); + + /******************************** + *DRAM ERROR, HALT PROCESSOR + *********************************/ + while(1); + + return -1; + } +} + +/* ------------------------------------------------------------------------- */ + +int testdram (void) +{ + /* TODO: XXX XXX XXX */ + printf ("test: 16 MB - ok\n"); + + return (0); +} + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) + +#ifdef CFG_PCMCIA_MEM_ADDR +volatile unsigned char *pcmcia_mem = (unsigned char*)CFG_PCMCIA_MEM_ADDR; +#endif + +int pcmcia_init(void) +{ + volatile pcmconf8xx_t *pcmp; + uint v, slota, slotb; + + /* + ** Enable the PCMCIA for a Flash card. + */ + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + +#if 0 + pcmp->pcmc_pbr0 = CFG_PCMCIA_MEM_ADDR; + pcmp->pcmc_por0 = 0xc00ff05d; +#endif + + /* Set all slots to zero by default. */ + pcmp->pcmc_pgcra = 0; + pcmp->pcmc_pgcrb = 0; +#ifdef PCMCIA_SLOT_A + pcmp->pcmc_pgcra = 0x40; +#endif +#ifdef PCMCIA_SLOT_B + pcmp->pcmc_pgcrb = 0x40; +#endif + + /* enable PCMCIA buffers */ + *((uint *)BCSR1) &= ~BCSR1_PCCEN; + + /* Check if any PCMCIA card is plugged in. */ + + slota = (pcmp->pcmc_pipr & 0x18000000) == 0 ; + slotb = (pcmp->pcmc_pipr & 0x00001800) == 0 ; + + if (!(slota || slotb)) + { + printf("No card present\n"); +#ifdef PCMCIA_SLOT_A + pcmp->pcmc_pgcra = 0; +#endif +#ifdef PCMCIA_SLOT_B + pcmp->pcmc_pgcrb = 0; +#endif + return -1; + } + else + printf("Card present ("); + + v = 0; + + /* both the ADS and the FADS have a 5V keyed pcmcia connector (?) + ** + ** Paolo - Yes, but i have to insert some 3.3V card in that slot on + ** my FADS... :-) + */ + +#if defined(CONFIG_MPC860) + switch( (pcmp->pcmc_pipr >> 30) & 3 ) +#elif defined(CONFIG_MPC823) || defined(CONFIG_MPC850) + switch( (pcmp->pcmc_pipr >> 14) & 3 ) +#endif + { + case 0x00 : + printf("5V"); + v = 5; + break; + case 0x01 : + printf("5V and 3V"); +#ifdef CONFIG_FADS + v = 3; /* User lower voltage if supported! */ +#else + v = 5; +#endif + break; + case 0x03 : + printf("5V, 3V and x.xV"); +#ifdef CONFIG_FADS + v = 3; /* User lower voltage if supported! */ +#else + v = 5; +#endif + break; + } + + switch(v){ +#ifdef CONFIG_FADS + case 3: + printf("; using 3V"); + /* + ** Enable 3 volt Vcc. + */ + *((uint *)BCSR1) &= ~BCSR1_PCCVCC1; + *((uint *)BCSR1) |= BCSR1_PCCVCC0; + break; +#endif + case 5: + printf("; using 5V"); +#ifdef CONFIG_ADS + /* + ** Enable 5 volt Vcc. + */ + *((uint *)BCSR1) &= ~BCSR1_PCCVCCON; +#endif +#ifdef CONFIG_FADS + /* + ** Enable 5 volt Vcc. + */ + *((uint *)BCSR1) &= ~BCSR1_PCCVCC0; + *((uint *)BCSR1) |= BCSR1_PCCVCC1; +#endif + break; + + default: + *((uint *)BCSR1) |= BCSR1_PCCEN; /* disable pcmcia */ + + printf("; unknown voltage"); + return -1; + } + printf(")\n"); + /* disable pcmcia reset after a while */ + + udelay(20); + +#ifdef MPC860 + pcmp->pcmc_pgcra = 0; +#elif MPC823 + pcmp->pcmc_pgcrb = 0; +#endif + + /* If you using a real hd you should give a short + * spin-up time. */ +#ifdef CONFIG_DISK_SPINUP_TIME + udelay(CONFIG_DISK_SPINUP_TIME); +#endif + + return 0; +} + +#endif /* CFG_CMD_PCMCIA */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CFG_PC_IDE_RESET + +void ide_set_reset(int on) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + /* + * Configure PC for IDE Reset Pin + */ + if (on) { /* assert RESET */ + immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET); + } else { /* release RESET */ + immr->im_ioport.iop_pcdat |= CFG_PC_IDE_RESET; + } + + /* program port pin as GPIO output */ + immr->im_ioport.iop_pcpar &= ~(CFG_PC_IDE_RESET); + immr->im_ioport.iop_pcso &= ~(CFG_PC_IDE_RESET); + immr->im_ioport.iop_pcdir |= CFG_PC_IDE_RESET; +} + +#endif /* CFG_PC_IDE_RESET */ +/* ------------------------------------------------------------------------- */ diff --git a/board/genietv/genietv.c b/board/genietv/genietv.c new file mode 100644 index 0000000..8f32ad7 --- /dev/null +++ b/board/genietv/genietv.c @@ -0,0 +1,375 @@ +/* + * genietv/genietv.c + * + * The GENIETV is using the following physical memorymap (copied from + * the FADS configuration): + * + * ff020000 -> ff02ffff : pcmcia + * ff010000 -> ff01ffff : BCSR connected to CS1, setup by 8xxROM + * ff000000 -> ff00ffff : IMAP internal in the cpu + * 02800000 -> 0287ffff : flash connected to CS0 + * 00000000 -> nnnnnnnn : sdram setup by U-Boot + * + * CS pins are connected as follows: + * + * CS0 -512Kb boot flash + * CS1 - SDRAM #1 + * CS2 - SDRAM #2 + * CS3 - Flash #1 + * CS4 - Flash #2 + * CS5 - LON (if present) + * CS6 - PCMCIA #1 + * CS7 - PCMCIA #2 + * + * Ports are configured as follows: + * + * PA7 - SDRAM banks enable + */ + +#include <common.h> +#include <mpc8xx.h> + +#define CFG_PA7 0x0100 + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFFFFF + +const uint sdram_table[] = +{ + /* + * Single Read. (Offset 0 in UPMB RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBEEC00, + 0x1FFDDC47, /* last */ + /* + * SDRAM Initialization (offset 5 in UPMB RAM) + * + * This is no UPM entry point. The following definition uses + * the remaining space to establish an initialization + * sequence, which is executed by a RUN command. + * + */ + 0x1FFDDC34, 0xEFEEAC34, 0x1FBD5C35, /* last */ + /* + * Burst Read. (Offset 8 in UPMB RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, + 0xF0AFFC00, 0xF1AFFC00, 0xEFBEEC00, 0x1FFDDC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPMB RAM) + */ + 0x1F2DFC04, 0xEEAFAC00, 0x01BE4C04, 0x1FFDDC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPMB RAM) + */ + 0x1F0DFC04, 0xEEAFAC00, 0x10AF5C00, 0xF0AFFC00, + 0xF0AFFC00, 0xE1BEEC04, 0x1FFDDC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPMB RAM) + */ + 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, + 0xFFFFFC84, 0xFFFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPMB RAM) + */ + 0x7FFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity + */ + +int checkboard (void) +{ + puts ("Board: GenieTV\n"); + return 0; +} + +#if 0 +static void PrintState(void) +{ + volatile immap_t *im = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &im->im_memctl; + + printf("\n0 - FLASH: B=%08x O=%08x", memctl->memc_br0, memctl->memc_or0); + printf("\n1 - SDRAM: B=%08x O=%08x", memctl->memc_br1, memctl->memc_or1); + printf("\n2 - SDRAM: B=%08x O=%08x", memctl->memc_br2, memctl->memc_or2); +} +#endif + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *im = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &im->im_memctl; + long int size_b0, size_b1, size8; + + /* Enable SDRAM */ + + /* Configuring PA7 for general purpouse output pin */ + im->im_ioport.iop_papar &= ~CFG_PA7 ; /* 0 = general purpouse */ + im->im_ioport.iop_padir |= CFG_PA7 ; /* 1 = output */ + + /* Enable SDRAM - PA7 = 1 */ + im->im_ioport.iop_padat |= CFG_PA7 ; /* value of PA7 */ + + /* + * Preliminary prescaler for refresh (depends on number of + * banks): This value is selected for four cycles every 62.4 us + * with two SDRAM banks or four cycles every 31.2 us with one + * bank. It will be adjusted after memory sizing. + */ + memctl->memc_mptpr = CFG_MPTPR_2BK_4K ; + + memctl->memc_mbmr = CFG_MBMR_8COL; + + upmconfig(UPMB, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + /* + * Map controller banks 1 and 2 to the SDRAM banks 1 and 2 at + * preliminary addresses - these have to be modified after the + * SDRAM size has been determined. + */ + + memctl->memc_or1 = 0xF0000000 | CFG_OR_TIMING_SDRAM; + memctl->memc_br1 = ((SDRAM_BASE1_PRELIM & BR_BA_MSK) | BR_MS_UPMB | BR_V); + + memctl->memc_or2 = 0xF0000000 | CFG_OR_TIMING_SDRAM; + memctl->memc_br2 = ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMB | BR_V); + + /* perform SDRAM initialization sequence */ + memctl->memc_mar = 0x00000088; + + memctl->memc_mcr = 0x80802105; /* SDRAM bank 0 */ + + memctl->memc_mcr = 0x80804105; /* SDRAM bank 1 */ + + /* Execute refresh 8 times */ + memctl->memc_mbmr = (CFG_MBMR_8COL & ~MAMR_TLFB_MSK) | MAMR_TLFB_8X ; + + memctl->memc_mcr = 0x80802130; /* SDRAM bank 0 - execute twice */ + + memctl->memc_mcr = 0x80804130; /* SDRAM bank 1 - execute twice */ + + /* Execute refresh 4 times */ + memctl->memc_mbmr = CFG_MBMR_8COL; + + /* + * Check Bank 0 Memory Size for re-configuration + * + * try 8 column mode + */ + +#if 0 + PrintState(); +#endif +/* printf ("\nChecking bank1..."); */ + size8 = dram_size (CFG_MBMR_8COL, (ulong *)SDRAM_BASE1_PRELIM, SDRAM_MAX_SIZE); + + size_b0 = size8 ; + +/* printf ("\nChecking bank2..."); */ + size_b1 = dram_size (memctl->memc_mbmr, (ulong *)SDRAM_BASE2_PRELIM,SDRAM_MAX_SIZE); + + /* + * Final mapping: map bigger bank first + */ + + memctl->memc_or1 = ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMB | BR_V; + + if (size_b1 > 0) + { + /* + * Position Bank 1 immediately above Bank 0 + */ + memctl->memc_or2 = ((-size_b1) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br2 = ((CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMB | BR_V) + + (size_b0 & BR_BA_MSK); + } + else + { + /* + * No bank 1 + * + * invalidate bank + */ + memctl->memc_br2 = 0; + /* adjust refresh rate depending on SDRAM type, one bank */ + memctl->memc_mptpr = CFG_MPTPR_1BK_4K; + } + + /* If no memory detected, disable SDRAM */ + if ((size_b0 + size_b1) == 0) + { + printf("disabling SDRAM!\n"); + /* Disable SDRAM - PA7 = 1 */ + im->im_ioport.iop_padat &= ~CFG_PA7 ; /* value of PA7 */ + } +/* else */ +/* printf("done! (%08lx)\n", size_b0 + size_b1); */ + +#if 0 + PrintState(); +#endif + return (size_b0 + size_b1); +} + +/* ------------------------------------------------------------------------- */ + +/* + * 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 mbmr_value, long int *base, long int maxsize) +{ + volatile long int *addr; + long int cnt, val; + + /*memctl->memc_mbmr = mbmr_value; */ + + for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + printf("(0)"); + return (0); + } + + for (cnt = 1; ; cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + if (val != (~cnt)) { +/* printf("(%08lx)", cnt*sizeof(long)); */ + return (cnt * sizeof(long)); + } + } + /* NOTREACHED */ + return (0); +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) + +#ifdef CFG_PCMCIA_MEM_ADDR +volatile unsigned char *pcmcia_mem = (unsigned char*)CFG_PCMCIA_MEM_ADDR; +#endif + +int pcmcia_init(void) +{ + volatile pcmconf8xx_t *pcmp; + uint v, slota, slotb; + + /* + ** Enable the PCMCIA for a Flash card. + */ + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + +#if 0 + pcmp->pcmc_pbr0 = CFG_PCMCIA_MEM_ADDR; + pcmp->pcmc_por0 = 0xc00ff05d; +#endif + + /* Set all slots to zero by default. */ + pcmp->pcmc_pgcra = 0; + pcmp->pcmc_pgcrb = 0; +#ifdef PCMCIA_SLOT_A + pcmp->pcmc_pgcra = 0x40; +#endif +#ifdef PCMCIA_SLOT_B + pcmp->pcmc_pgcrb = 0x40; +#endif + + /* Check if any PCMCIA card is luged in. */ + slota = (pcmp->pcmc_pipr & 0x18000000) == 0 ; + slotb = (pcmp->pcmc_pipr & 0x00001800) == 0 ; + + if (!(slota || slotb)) + { + printf("No card present\n"); +#ifdef PCMCIA_SLOT_A + pcmp->pcmc_pgcra = 0; +#endif +#ifdef PCMCIA_SLOT_B + pcmp->pcmc_pgcrb = 0; +#endif + return -1; + } + else + printf("Unknown card ("); + + v = 0; + + switch( (pcmp->pcmc_pipr >> 14) & 3 ) + { + case 0x00 : + printf("5V"); + v = 5; + break; + case 0x01 : + printf("5V and 3V"); + v = 3; + break; + case 0x03 : + printf("5V, 3V and x.xV"); + v = 3; + break; + } + + switch(v){ + case 3: + printf("; using 3V"); + /* Enable 3 volt Vcc. */ + + break; + + default: + printf("; unknown voltage"); + return -1; + } + printf(")\n"); + /* disable pcmcia reset after a while */ + + udelay(20); + + pcmp->pcmc_pgcrb = 0; + + /* If you using a real hd you should give a short + * spin-up time. */ +#ifdef CONFIG_DISK_SPINUP_TIME + udelay(CONFIG_DISK_SPINUP_TIME); +#endif + + return 0; +} +#endif /* CFG_CMD_PCMCIA */ diff --git a/board/lart/config.mk b/board/lart/config.mk new file mode 100644 index 0000000..8f1a62b --- /dev/null +++ b/board/lart/config.mk @@ -0,0 +1,23 @@ +# +# LART board with SA1100 cpu +# +# see http://www.lart.tudelft.nl/ for more information on LART +# + +# +# LART has 4 banks of 8 MB DRAM +# +# c000'0000 +# c100'0000 +# c800'0000 +# c900'0000 +# +# Linux-Kernel is expected to be at c000'8000, entry c000'8000 +# +# we load ourself to c170'0000, the upper 1 MB of second bank +# +# download areas is c800'0000 +# + + +TEXT_BASE = 0xc1700000 diff --git a/board/lart/memsetup.S b/board/lart/memsetup.S new file mode 100644 index 0000000..bebd697 --- /dev/null +++ b/board/lart/memsetup.S @@ -0,0 +1,96 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +MEM_BASE: .long 0xa0000000 +MEM_START: .long 0xc0000000 + +#define MDCNFG 0x00 +#define MDCAS0 0x04 +#define MDCAS1 0x08 +#define MDCAS2 0x0c +#define MSC0 0x10 +#define MSC1 0x14 +#define MECR 0x18 + +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +/* mdcnfg: .long 0x0bb2bcbf */ +mdcnfg: .long 0x0334b22f @ alt +/* mcs0: .long 0xfff8fff8 */ +msc0: .long 0xad8c4888 @ alt +mecr: .long 0x00060006 +/* mecr: .long 0x994a994a @ alt */ + +/* setting up the memory */ + +.globl memsetup +memsetup: + ldr r0, MEM_BASE + + /* Setup the flash memory */ + ldr r1, msc0 + str r1, [r0, #MSC0] + + /* Set up the DRAM */ + + /* MDCAS0 */ + ldr r1, mdcas0 + str r1, [r0, #MDCAS0] + + /* MDCAS1 */ + ldr r1, mdcas1 + str r1, [r0, #MDCAS1] + + /* MDCAS2 */ + ldr r1, mdcas2 + str r1, [r0, #MDCAS2] + + /* MDCNFG */ + ldr r1, mdcnfg + str r1, [r0, #MDCNFG] + + /* Set up PCMCIA space */ + ldr r1, mecr + str r1, [r0, #MECR] + + /* Load something to activate bank */ + ldr r1, MEM_START + +.rept 8 + ldr r0, [r1] +.endr + + /* everything is fine now */ + mov pc, lr + diff --git a/board/lubbock/memsetup.S b/board/lubbock/memsetup.S new file mode 100644 index 0000000..c027834 --- /dev/null +++ b/board/lubbock/memsetup.S @@ -0,0 +1,749 @@ +/* + * Most of this taken from Redboot hal_platform_setup.h with cleanup + * + * NOTE: I haven't clean this up considerably, just enough to get it + * running. See hal_platform_setup.h for the source. See + * board/cradle/memsetup.S for another PXA250 setup that is + * much cleaner. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/pxa-regs.h> + +DRAM_SIZE: .long CFG_DRAM_SIZE + +/* wait for coprocessor write complete */ + .macro CPWAIT reg + mrc p15,0,\reg,c2,c0,0 + mov \reg,\reg + sub pc,pc,#4 + .endm + + +.globl memsetup +memsetup: + + mov r10, lr + + /* Set up GPIO pins first */ + + ldr r0, =GPSR0 + ldr r1, =CFG_GPSR0_VAL + str r1, [r0] + + ldr r0, =GPSR1 + ldr r1, =CFG_GPSR1_VAL + str r1, [r0] + + ldr r0, =GPSR2 + ldr r1, =CFG_GPSR2_VAL + str r1, [r0] + + ldr r0, =GPCR0 + ldr r1, =CFG_GPCR0_VAL + str r1, [r0] + + ldr r0, =GPCR1 + ldr r1, =CFG_GPCR1_VAL + str r1, [r0] + + ldr r0, =GPCR2 + ldr r1, =CFG_GPCR2_VAL + str r1, [r0] + + ldr r0, =GPDR0 + ldr r1, =CFG_GPDR0_VAL + str r1, [r0] + + ldr r0, =GPDR1 + ldr r1, =CFG_GPDR1_VAL + str r1, [r0] + + ldr r0, =GPDR2 + ldr r1, =CFG_GPDR2_VAL + str r1, [r0] + + ldr r0, =GAFR0_L + ldr r1, =CFG_GAFR0_L_VAL + str r1, [r0] + + ldr r0, =GAFR0_U + ldr r1, =CFG_GAFR0_U_VAL + str r1, [r0] + + ldr r0, =GAFR1_L + ldr r1, =CFG_GAFR1_L_VAL + str r1, [r0] + + ldr r0, =GAFR1_U + ldr r1, =CFG_GAFR1_U_VAL + str r1, [r0] + + ldr r0, =GAFR2_L + ldr r1, =CFG_GAFR2_L_VAL + str r1, [r0] + + ldr r0, =GAFR2_U + ldr r1, =CFG_GAFR2_U_VAL + str r1, [r0] + + /* enable GPIO pins */ + ldr r0, =PSSR + ldr r1, =CFG_PSSR_VAL + str r1, [r0] + + ldr r3, =MSC1 /* low - bank 2 Lubbock Registers / SRAM */ + ldr r2, =CFG_MSC1_VAL /* high - bank 3 Ethernet Controller */ + str r2, [r3] /* need to set MSC1 before trying to write to the HEX LEDs */ + ldr r2, [r3] /* need to read it back to make sure the value latches (see MSC section of manual) */ + + ldr r1, =LED_BLANK + mov r0, #0xFF + str r0, [r1] /* turn on hex leds */ + +loop: + ldr r0, =0xB0070001 + ldr r1, =_LED + str r0, [r1] /* hex display */ + +/********************************************************************* + Initlialize Memory Controller + The sequence below is based on the recommended init steps detailed + in the EAS, chapter 5 (Chapter 10, Operating Systems Developers Guide) + + + pause for 200 uSecs- allow internal clocks to settle + *Note: only need this if hard reset... doing it anyway for now +*/ + + @ ---- Wait 200 usec + ldr r3, =OSCR @ reset the OS Timer Count to zero + mov r2, #0 + str r2, [r3] + ldr r4, =0x300 @ really 0x2E1 is about 200usec, so 0x300 should be plenty +1: + ldr r2, [r3] + cmp r4, r2 + bgt 1b + +mem_init: + @ get memory controller base address + ldr r1, =MEMC_BASE + +@**************************************************************************** +@ Step 1 +@ + + @ write msc0, read back to ensure data latches + @ + ldr r2, =CFG_MSC0_VAL + str r2, [r1, #MSC0_OFFSET] + ldr r2, [r1, #MSC0_OFFSET] + + @ write msc1 + ldr r2, =CFG_MSC1_VAL + str r2, [r1, #MSC1_OFFSET] + ldr r2, [r1, #MSC1_OFFSET] + + @ write msc2 + ldr r2, =CFG_MSC2_VAL + str r2, [r1, #MSC2_OFFSET] + ldr r2, [r1, #MSC2_OFFSET] + + @ write mecr + ldr r2, =CFG_MECR_VAL + str r2, [r1, #MECR_OFFSET] + + @ write mcmem0 + ldr r2, =CFG_MCMEM0_VAL + str r2, [r1, #MCMEM0_OFFSET] + + @ write mcmem1 + ldr r2, =CFG_MCMEM1_VAL + str r2, [r1, #MCMEM1_OFFSET] + + @ write mcatt0 + ldr r2, =CFG_MCATT0_VAL + str r2, [r1, #MCATT0_OFFSET] + + @ write mcatt1 + ldr r2, =CFG_MCATT1_VAL + str r2, [r1, #MCATT1_OFFSET] + + @ write mcio0 + ldr r2, =CFG_MCIO0_VAL + str r2, [r1, #MCIO0_OFFSET] + + @ write mcio1 + ldr r2, =CFG_MCIO1_VAL + str r2, [r1, #MCIO1_OFFSET] + + @------------------------------------------------------- + @ 3rd bullet, Step 1 + @ + + @ get the mdrefr settings + ldr r3, =CFG_MDREFR_VAL_100 + + @ extract DRI field (we need a valid DRI field) + @ + ldr r2, =0xFFF + + @ valid DRI field in r3 + @ + and r3, r3, r2 + + @ get the reset state of MDREFR + @ + ldr r4, [r1, #MDREFR_OFFSET] + + @ clear the DRI field + @ + bic r4, r4, r2 + + @ insert the valid DRI field loaded above + @ + orr r4, r4, r3 + + @ write back mdrefr + @ + str r4, [r1, #MDREFR_OFFSET] + + @ *Note: preserve the mdrefr value in r4 * + +@**************************************************************************** +@ Step 2 +@ + /* This should be for SRAM, why is it commented out??? */ + + @ fetch sxcnfg value + @ + @ldr r2, =0 + @ write back sxcnfg + @str r2, [r1, #SXCNFG_OFFSET] + +/* @if sxcnfg=0, don't program for synch-static memory */ + @cmp r2, #0 + @beq 1f + + @program sxmrs + @ldr r2, =SXMRS_SETTINGS + @str r2, [r1, #SXMRS_OFFSET] + + +@**************************************************************************** +@ Step 3 +@ + + @ Assumes previous mdrefr value in r4, if not then read current mdrefr + + @ clear the free-running clock bits + @ (clear K0Free, K1Free, K2Free + @ + bic r4, r4, #(0x00800000 | 0x01000000 | 0x02000000) + + @ set K1RUN if bank 0 installed + @ + orr r4, r4, #0x00010000 + + + +#ifdef THIS +@<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!< +@<!<!<!<!<!<!<!<!<!<!<! Begin INSERT 1 <!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!< + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ Lubbock: Allow the user to select the {T/R/M} with predetermined + @ SDCLK. Based on Table 3-1 in PXA250 and PXA210 Dev Man. + @ + @ * = Must set MDREFR.K1DB2 to halve the MemClk for desired SDCLK[1] + @ + @ S25, S26 used to provide all 400 MHz BIN values for Cotulla (0,0 - 1,3) + @ S25, S26 used to provide all 200 MHz BIN values for Sabinal + @ + @ S23: Force the halving of MemClk when deriving SDCLK[1] + @ DOT: no override !DOT: halve (if not already forced half) +/* @ *For certain MemClks, SDCLK's derivation is forced to be halved */ + @ + @ S24: Run/Turbo. + @ DOT: Run mode !DOT: Turbo mode + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + @ + @ Allow the user to control K1DB2 where applicable + @ + @ Get the value of S23: @ 1 = DOT (unity), 0 = !DOT (halve it) + @ + @ DOT: set K1DB2 (SDCLD = MemClk) + @ !DOT: clear K1DB2 (SDCLK = MemClk/2) + @ + @ldr r2, =FPGA_REGS_BASE_PHYSICAL + + bl GET_S23 @ r3, r2 @ get the value of S23 in R0, i put the base adx of fpga in r3 + + cmp r3, #0x0 @ is !DOT? + orreq r4, r4, #0x00020000 @ SDClk[1] = MemClk/2 + bicne r4, r4, #0x00020000 @ SDClk[1] = MemClk + + @ + @ Next, we need to look for S25,S26 selections that necessitate the + @ halving of MemClk to derive SDCLK[1]: (S25,S26)={03-0C, 10-13} + @ Override above S23-based selection accordingly. + @ + ldr r2, =FPGA_REGS_BASE_PHYSICAL + bl GET_S25 @ r0, r2 + @ get the value of S25 in R0, i put the base adx of fpga in r2 + + + + ldr r2, =FPGA_REGS_BASE_PHYSICAL + BL GET_S26 @ r3, r2 + @ get the value of S26 in R1, i put the base adx of fpga in r2 + + orr r0, r0, r3 @ concatenate S25 & S26 vals + and r0, r0, #0xFF + + @ Set K1DB2 for the frequencies that require it + @ + cmp r0, #0x03 + cmpne r0, #0x04 + cmpne r0, #0x05 + cmpne r0, #0x06 + cmpne r0, #0x07 + cmpne r0, #0x08 + cmpne r0, #0x09 + cmpne r0, #0x0A + cmpne r0, #0x0B + cmpne r0, #0x0C + cmpne r0, #0x10 + cmpne r0, #0x11 + cmpne r0, #0x12 + cmpne r0, #0x13 + orreq r4, r4, #0x00020000 @ SDCLK[1] = (MemClk)/2 for 03 - 0C @ 10 - 13 + + @ + @ *Must make MSC0&1 adjustments now for MEMClks > 100MHz. + @ + @ Adjust MSC0 for MemClks > 100 MHz + @ + ldreq r0, [r1, #MSC0_OFFSET] + ldreq r3, =0x7F007F00 + biceq r0, r0, r3 @ clear MSC0[14:12, 11:8] (RRR, RDN) + ldreq r3, =0x46004600 + orreq r0, r0, r3 @ set MSC0[14, 10:9] (doubling RRR, RDN) + streq r0, [r1, #MSC0_OFFSET] + ldreq r0, [r1, #MSC0_OFFSET] @ read it back to ensure that the data latches + + @ + @ Adjust MSC1.LH for MemClks > 100 MHz + @ + ldreq r0, [r1, #MSC1_OFFSET] + ldreq r3, =0x7FF0 + biceq r0, r0, r3 @ clear MSC1[14:12, 11:8, 7:4] (RRR, RDN, RDF) + ldreq r3, =0x4880 + orreq r0, r0, r3 @ set MSC1[14, 11, 7] (doubling RRR, RDN, RDF) + streq r0, [r1, #MSC1_OFFSET] + ldreq r0, [r1, #MSC1_OFFSET] @ read it back to ensure that the data latches + + @ @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#endif + +@<!<!<!<!<!<!<!<!<!<!<! End INSERT 1 <!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!< +@<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!<!< + + + @ write back mdrefr + @ + str r4, [r1, #MDREFR_OFFSET] + ldr r4, [r1, #MDREFR_OFFSET] + + @ deassert SLFRSH + @ + bic r4, r4, #0x00400000 + + @ write back mdrefr + @ + str r4, [r1, #MDREFR_OFFSET] + + @ assert E1PIN + @ + orr r4, r4, #0x00008000 + + @ write back mdrefr + @ + str r4, [r1, #MDREFR_OFFSET] + ldr r4, [r1, #MDREFR_OFFSET] + nop + nop + + +@**************************************************************************** +@ Step 4 +@ + + @ fetch platform value of mdcnfg + @ + ldr r2, =CFG_MDCNFG_VAL + + @ disable all sdram banks + @ + bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1) + bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3) + + @ program banks 0/1 for bus width + @ + bic r2, r2, #MDCNFG_DWID0 @0=32-bit + + + @ write initial value of mdcnfg, w/o enabling sdram banks + @ + str r2, [r1, #MDCNFG_OFFSET] + +@ **************************************************************************** +@ Step 5 +@ + + @ pause for 200 uSecs + @ + ldr r3, =OSCR @reset the OS Timer Count to zero + mov r2, #0 + str r2, [r3] + ldr r4, =0x300 @really 0x2E1 is about 200usec, so 0x300 should be plenty +1: + ldr r2, [r3] + cmp r4, r2 + bgt 1b + + +@**************************************************************************** +@ Step 6 +@ + + mov r0, #0x78 @turn everything off + mcr p15, 0, r0, c1, c0, 0 @(caches off, MMU off, etc.) + + +@ **************************************************************************** +@ Step 7 +@ + @ Access memory *not yet enabled* for CBR refresh cycles (8) + @ - CBR is generated for all banks + + ldr r2, =CFG_DRAM_BASE + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + + +@ **************************************************************************** +@ Step 8: NOP (enable dcache if you wanna... we dont) +@ + + +@ **************************************************************************** +@ Step 9 +@ + + + @get memory controller base address + @ + ldr r1, =MEMC_BASE + + @fetch current mdcnfg value + @ + ldr r3, [r1, #MDCNFG_OFFSET] + + @enable sdram bank 0 if installed (must do for any populated bank) + @ + orr r3, r3, #MDCNFG_DE0 + + @write back mdcnfg, enabling the sdram bank(s) + @ + str r3, [r1, #MDCNFG_OFFSET] + + +@**************************************************************************** +@ Step 10 +@ + + @ write mdmrs + @ + ldr r2, =CFG_MDMRS_VAL + str r2, [r1, #MDMRS_OFFSET] + + +@**************************************************************************** +@ Step 11: Final Step +@ + +@INITINTC + @******************************************************************** + @ Disable (mask) all interrupts at the interrupt controller + @ + + @ clear the interrupt level register (use IRQ, not FIQ) + @ + mov r1, #0 + ldr r2, =ICLR + str r1, [r2] + + @ mask all interrupts at the controller + @ + ldr r2, =ICMR + str r1, [r2] + + +@INITCLKS + @ ******************************************************************** + @ Disable the peripheral clocks, and set the core clock + @ frequency (hard-coding at 398.12MHz for now). + @ + + @ Turn Off ALL on-chip peripheral clocks for re-configuration + @ *Note: See label 'ENABLECLKS' for the re-enabling + @ + ldr r1, =CKEN + mov r2, #0 + str r2, [r1] + + + @ default value in case no valid rotary switch setting is found + ldr r2, =(CCCR_L27 | CCCR_M2 | CCCR_N10) @ DEFAULT: {200/200/100} + + + @... and write the core clock config register + @ + ldr r1, =CCCR + str r2, [r1] + +/* @ enable the 32Khz oscillator for RTC and PowerManager + @ + ldr r1, =OSCC + mov r2, #OSCC_OON + str r2, [r1] + + + @ NOTE: spin here until OSCC.OOK get set, + @ meaning the PLL has settled. + @ +60: + ldr r2, [r1] + ands r2, r2, #1 + beq 60b +*/ + +@OSCC_OON_DONE + + +#ifdef A0_COTULLA + @**************************************************************************** + @ !!! Take care of A0 Errata Sighting #4 -- + @ after a frequency change, the memory controller must be restarted + @ + + @ get memory controller base address + ldr r1, =MEMC_BASE + + @ get the current state of MDREFR + @ + ldr r2, [r1, #MDREFR_OFFSET] + + @ clear E0PIN, E1PIN + @ + bic r3, r2, #(MDREFR_E0PIN | MDREFR_E1PIN) + + @ write MDREFR with E0PIN, E1PIN cleared (disable sdclk[0,1]) + @ + str r3, [r1, #MDREFR_OFFSET] + + @ then write MDREFR with E0PIN, E1PIN set (enable sdclk[0,1]) + @ + str r2, [r1, #MDREFR_OFFSET] + + @ get the current state of MDCNFG + @ + ldr r3, [r1, #MDCNFG_OFFSET] + + @ disable all SDRAM banks + @ + bic r3, r3, #(MDCNFG_DE0 | MDCNFG_DE1) + bic r3, r3, #(MDCNFG_DE2 | MDCNFG_DE3) + + @ write back MDCNFG + @ + ldr r3, [r1, #MDCNFG_OFFSET] + + @ Access memory not yet enabled for CBR refresh cycles (8) + @ - CBR is generated for *all* banks + ldr r2, =CFG_DRAM_BASE + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + str r2, [r2] + + @ fetch current mdcnfg value + @ + ldr r3, [r1, #MDCNFG_OFFSET] + + @ enable sdram bank 0 if installed + @ + orr r3, r3, #MDCNFG_DE0 + + @ write back mdcnfg, enabling the sdram bank(s) + @ + str r3, [r1, #MDCNFG_OFFSET] + + @ write mdmrs + @ + ldr r2, =CFG_MDMRS_VAL + str r2, [r1, #MDMRS_OFFSET] + + + + /* @ errata: don't enable auto power-down */ + @ get current value of mdrefr + @ldr r3, [r1, #MDREFR_OFFSET] + @ enable auto-power down + @orr r3, r3, #MDREFR_APD + @write back mdrefr + @str r3, [r1, #MDREFR_OFFSET] + +#endif A0_Cotulla + + + ldr r0, =0x000C0dE3 + ldr r1, =_LED + str r0, [r1] /* hex display */ + +@ ^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^% +@ ^%^%^%^%^%^%^%^%^% above could be replaced by prememLLI ^%^%^%^%^%^%^%^%^% +@ ^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^%^% + + + /* Save SDRAM size */ + ldr r1, =DRAM_SIZE + str r8, [r1] + + ldr r0, =0xC0DE0006 + ldr r1, =_LED + str r0, [r1] /* hex display */ + + /* Interrupt init */ + /* Mask all interrupts */ + ldr r0, =ICMR /* enable no sources */ + mov r1, #0 + str r1, [r0] + +#define NODEBUG +#ifdef NODEBUG + /*Disable software and data breakpoints */ + mov r0,#0 + mcr p15,0,r0,c14,c8,0 /* ibcr0 */ + mcr p15,0,r0,c14,c9,0 /* ibcr1 */ + mcr p15,0,r0,c14,c4,0 /* dbcon */ + + /*Enable all debug functionality */ + mov r0,#0x80000000 + mcr p14,0,r0,c10,c0,0 /* dcsr */ + +#endif + + ldr r0, =0xBEEF001D + ldr r1, =_LED + str r0, [r1] /* hex display */ + + mov pc, r10 + +@ End memsetup + +@ %%%%%%%%%%% Useful subroutines +GET_S23: + @ This macro will read S23 and return its value in r3 + @ r2 contains the base address of the Lubbock user registers + ldr r2, =FPGA_REGS_BASE_PHYSICAL + + /*@ read S23's value */ + ldr r3, [r2, #USER_SWITCHES_OFFSET] + + @ mask out irrelevant bits + and r3, r3, #0x200 + + @ get bit into position 0 + mov r3, r3, LSR #9 + + mov pc, lr +@ End GET_S23 + + +GET_S24: + @ This macro will read S24 and return its value in r0 + @ r2 contains the base address of the Lubbock user registers + ldr r2, =FPGA_REGS_BASE_PHYSICAL + + /*@ read S24's value */ + ldr r0, [r2, #USER_SWITCHES_OFFSET] + + @ mask out irrelevant bits + and r0, r0, #0x100 + + @ get bit into position 0 + mov r0, r0, LSR #8 + + mov pc, lr +@ End GET_S23 + + +GET_S25: + @ This macro will read rotary S25 and return its value in r0 + @ r2 contains the base address of the Lubbock user registers + @ read the user switches register + ldr r0, [r2, #USER_SWITCHES_OFFSET] + + @ mask out irrelevant bits + and r0, r0, #0xF0 + + mov pc, lr +@ End subroutine + + +GET_S26: + @ This macro will read rotary S26 and return its value in r3 + @ r2 contains the base address of the Lubbock user registers + @ read the user switches register + ldr r3, [r2, #USER_SWITCHES_OFFSET] + + @ mask out irrelevant bits + and r3, r3, #0x0F + + mov pc, lr +@ End subroutine GET_S26 + + diff --git a/board/mbx8xx/config.mk b/board/mbx8xx/config.mk new file mode 100644 index 0000000..d5e8ed2 --- /dev/null +++ b/board/mbx8xx/config.mk @@ -0,0 +1,33 @@ +# +# (C) Copyright 2000 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# (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 +# + +# +# MBX8xx boards +# + +TEXT_BASE = 0xfe000000 +/*TEXT_BASE = 0x00200000 */ diff --git a/board/ml2/flash.c b/board/ml2/flash.c new file mode 100644 index 0000000..77e0931 --- /dev/null +++ b/board/ml2/flash.c @@ -0,0 +1,301 @@ +/* + * flash.c: Support code for the flash chips on the Xilinx ML2 board + * + * Copyright 2002 Mind NV + * + * http://www.mind.be/ + * + * Author : Peter De Schrijver (p2@mind.be) + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire program + * is licensed under the GPL. + * + */ + +#include <common.h> +#include <asm/u-boot.h> +#include <configs/ML2.h> + +#define FLASH_BANK_SIZE (64*1024*1024) + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +#define SECT_SIZE (512*1024) + +#define CMD_READ_ARRAY 0x00FF00FF00FF00FULL +#define CMD_IDENTIFY 0x0090009000900090ULL +#define CMD_ERASE_SETUP 0x0020002000200020ULL +#define CMD_ERASE_CONFIRM 0x00D000D000D000D0ULL +#define CMD_PROGRAM 0x0040004000400040ULL +#define CMD_RESUME 0x00D000D000D000D0ULL +#define CMD_SUSPEND 0x00B000B000B000B0ULL +#define CMD_STATUS_READ 0x0070007000700070ULL +#define CMD_STATUS_RESET 0x0050005000500050ULL + +#define BIT_BUSY 0x0080008000800080ULL +#define BIT_ERASE_SUSPEND 0x004000400400040ULL +#define BIT_ERASE_ERROR 0x0020002000200020ULL +#define BIT_PROGRAM_ERROR 0x0010001000100010ULL +#define BIT_VPP_RANGE_ERROR 0x0008000800080008ULL +#define BIT_PROGRAM_SUSPEND 0x0004000400040004ULL +#define BIT_PROTECT_ERROR 0x0002000200020002ULL +#define BIT_UNDEFINED 0x0001000100010001ULL + +#define BIT_SEQUENCE_ERROR 0x0030003000300030ULL + +#define BIT_TIMEOUT 0x80000000 + + +inline void eieio(void) { + + __asm__ __volatile__ ("eieio" : : : "memory"); + +} + +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 = (INTEL_MANUFACT & FLASH_VENDMASK) | + (INTEL_ID_28F128J3A & 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 = CFG_FLASH_BASE; + else + panic("configured to many flash banks!\n"); + for (j = 0; j < flash_info[i].sector_count; j++) + flash_info[i].start[j]=flashbase + j * SECT_SIZE; + + size += flash_info[i].size; + } + + 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: "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case (INTEL_ID_28F128J3A & FLASH_TYPEMASK): + printf("4x 28F128J3A (128Mbit)\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; i < info->sector_count; i++) { + if ((i % 5) == 0) + printf("\n "); + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); +} + +int flash_error (unsigned long long code) { + + if (code & BIT_TIMEOUT) { + printf ("Timeout\n"); + return ERR_TIMOUT; + } + + if (~code & BIT_BUSY) { + printf ("Busy\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_VPP_RANGE_ERROR) { + printf ("Vpp range error\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_PROTECT_ERROR) { + printf ("Device protect error\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_SEQUENCE_ERROR) { + printf ("Command seqence error\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_ERASE_ERROR) { + printf ("Block erase error\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_PROGRAM_ERROR) { + printf ("Program error\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_ERASE_SUSPEND) { + printf ("Block erase suspended\n"); + return ERR_PROG_ERROR; + } + + if (code & BIT_PROGRAM_SUSPEND) { + printf ("Program suspended\n"); + return ERR_PROG_ERROR; + } + + return ERR_OK; + +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) { + + int rc = ERR_OK; + int sect; + unsigned long long result; + + 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) != (INTEL_MANUFACT & FLASH_VENDMASK)) + return ERR_UNKNOWN_FLASH_VENDOR; + + for (sect=s_first; sect<=s_last; ++sect) + if (info->protect[sect]) + return ERR_PROTECTED; + + for (sect = s_first; sect<=s_last && !ctrlc(); sect++) { + volatile unsigned long long *addr= + (unsigned long long *)(info->start[sect]); + + printf("Erasing sector %2d ... ", sect); + + *addr=CMD_STATUS_RESET; + eieio(); + *addr=CMD_ERASE_SETUP; + eieio(); + *addr=CMD_ERASE_CONFIRM; + eieio(); + + do { + result = *addr; + } while(~result & BIT_BUSY); + + *addr=CMD_READ_ARRAY; + + if ((rc = flash_error(result)) == ERR_OK) + printf("ok.\n"); + else + break; + } + + if (ctrlc()) + printf("User Interrupt!\n"); + + return rc; +} + +volatile static int write_word (flash_info_t *info, ulong dest, unsigned long long data) { + + volatile unsigned long long *addr=(unsigned long long *)dest; + unsigned long long result; + int rc = ERR_OK; + + result=*addr; + if ((result & data) != data) + return ERR_NOT_ERASED; + + *addr=CMD_STATUS_RESET; + eieio(); + *addr=CMD_PROGRAM; + eieio(); + *addr=data; + eieio(); + + do { + result=*addr; + } while(~result & BIT_BUSY); + + *addr=CMD_READ_ARRAY; + + rc = flash_error(result); + + return rc; + +} + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) { + + ulong cp, wp; + unsigned long long data; + int l; + int i,rc; + + wp=(addr & ~7); + + if((l=addr-wp) != 0) { + data=0; + for(i=0,cp=wp;i<l;++i,++cp) + data = (data >> 8) | (*(uchar *)cp << 24); + + for (; i<8 && cnt>0; ++i) { + data = (data >> 8) | (*src++ << 24); + --cnt; + ++cp; + } + + for (; i<8; ++i, ++cp) + data = (data >> 8) | (*(uchar *)cp << 24); + + if ((rc = write_word(info, wp, data)) != 0) + return rc; + + wp+=8; + } + + while(cnt>=8) { + data=*((unsigned long long *)src); + if ((rc = write_word(info, wp, data)) != 0) + return rc; + src+=8; + wp+=8; + cnt-=8; + } + + if(cnt == 0) + return ERR_OK; + + data = 0; + for (i=0, cp=wp; i<8 && cnt>0; ++i, ++cp) { + data = (data >> 8) | (*src++ << 24); + --cnt; + } + for (; i<8; ++i, ++cp) { + data = (data >> 8) | (*(uchar *)cp << 24); + } + + return write_word(info, wp, data); + +} + diff --git a/board/ml2/init.S b/board/ml2/init.S new file mode 100644 index 0000000..2386c2a --- /dev/null +++ b/board/ml2/init.S @@ -0,0 +1,34 @@ +/* + * init.S: Stubs for U-Boot initialization + * + * Copyright 2002 Mind NV + * + * http://www.mind.be/ + * + * Author : Peter De Schrijver (p2@mind.be) + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#include <ppc4xx.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + blr + + .globl sdram_init +sdram_init: + blr diff --git a/board/ml2/ml2.c b/board/ml2/ml2.c new file mode 100644 index 0000000..a89a8f9 --- /dev/null +++ b/board/ml2/ml2.c @@ -0,0 +1,67 @@ +/* + * ml2.c: U-Boot platform support for Xilinx ML2 board + * + * Copyright 2002 Mind NV + * + * http://www.mind.be/ + * + * Author : Peter De Schrijver (p2@mind.be) + * + * Derived from : Other platform support files in this tree + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL) version 2, incorporated herein by + * reference. Drivers based on or derived from this code fall under the GPL + * and must retain the authorship, copyright and this license notice. This + * file is not a complete program and may only be used when the entire + * program is licensed under the GPL. + * + */ + +#include <common.h> +#include <asm/processor.h> + + + +int board_pre_init (void) +{ + return 0; +} + + +int checkboard (void) +{ + unsigned char *s = getenv ("serial#"); + unsigned char *e; + + if (!s || strncmp (s, "ML2", 9)) { + printf ("### No HW ID - assuming ML2"); + } else { + for (e = s; *e; ++e) { + if (*e == ' ') + break; + } + + for (; s < e; ++s) { + putc (*s); + } + } + + + putc ('\n'); + + return (0); +} + + +long int initdram (int board_type) +{ + return 32 * 1024 * 1024; +} + +int testdram (void) +{ + printf ("test: xxx MB - ok\n"); + + return (0); +} diff --git a/board/mousse/README b/board/mousse/README new file mode 100644 index 0000000..ef072bd --- /dev/null +++ b/board/mousse/README @@ -0,0 +1,350 @@ + +U-Boot for MOUSSE/MPC8240 (KAHLUA) +---------------------------------- +James Dougherty (jfd@broadcom.com), 09/10/01 + +The Broadcom/Vooha Mousse board is a 3U Compact PCI system board +which uses the MPC8240, a 64MB SDRAM SIMM, and has onboard +DEC 21143, NS16550 UART, an SGS M48T59Y TOD, and 4MB FLASH. +See also: http://www.vooha.com/ + +* NVRAM setenv/printenv/savenv supported. +* Date Command +* Serial Console support +* Network support +* FLASH of kernel images is supported. +* FLASH of U-Boot to onboard and PLCC boot region. +* Kernel command line options from NVRAM is supported. +* IP PNP options supported. + +U-Boot Loading... + + + +U-Boot 1.0.5 (Sep 10 2001 - 00:22:25) + +CPU: MPC8240 Revision 1.1 at 198 MHz: 16 kB I-Cache 16 kB D-Cache +Board: MOUSSE MPC8240/KAHLUA - CHRP (MAP B) +Built: Sep 10 2001 at 01:01:50 +MPLD: Revision 127 +Local Bus: 33 MHz +RTC: M48T589 TOD/NVRAM (8176) bytes + Current date/time: 9/10/2001 0:18:52 +DRAM: 64 MB +FLASH: 1.960 MB +PCI: scanning bus0 ... + bus dev fn venID devID class rev MBAR0 MBAR1 IPIN ILINE + 00 00 00 1057 0003 060000 11 00000008 00000000 01 00 + 00 0d 00 1011 0019 020000 41 80000001 80000000 01 01 + 00 0e 00 105a 4d38 018000 01 a0000001 a0001001 01 03 +In: serial +Out: serial +Err: serial + +Hit any key to stop autoboot: 0 +=> + +I. Root FileSystem/IP Configuration + +bootcmd=tftp 100000 vmlinux.img;bootm +bootdelay=3 +baudrate=9600 +ipaddr=<IP ADDRESS> +netmask=<NETMASK> +hostname=<NAME> +serverip=<NFS SERVER IP ADDRESS> +ethaddr=00:00:10:20:30:44 +nfsroot=<NFS SERVER IP ADDRESS>:/boot/root-fs +gateway=<IP ADDRESS> +root=/dev/nfs +stdin=serial +stdout=serial +stderr=serial + +NVRAM environment variables. + +use the command: + +setenv <attribute> <value> + +type "saveenv" to write to NVRAM. + + + +II. To boot from a hard drive: + +setenv root /dev/hda1 + + +III. IP options which configure the network: + +ipaddr=<IP ADDRESS OF MACHINE> +netmask=<NETMASK> +hostname=mousse +ethaddr=00:00:10:20:30:44 +gateway=<IP ADDRESS OF GATEWAY/ROUTER> + + +IV. IP Options which configure NFS Root/Boot Support + +root=/dev/nfs +serverip=<NFS SERVER IP ADDRESS> +nfsroot=<NFS SERVER IP ADDRESS>:/boot/root-fs + +V. U-Boot Image Support + +The U-Boot boot loader assumes that after you build +your kernel (vmlinux), you will create a U-Boot image +using the following commands or script: + +#!/bin/csh +/bin/touch vmlinux.img +/bin/rm vmlinux.img +set path=($TOOLBASE/bin $path) +set path=($U_BOOT/tools $path) +powerpc-linux-objcopy -S -O binary vmlinux vmlinux.bin +gzip -vf vmlinux.bin +mkimage -A ppc -O linux -T kernel -C gzip -a 0 -e 0 -n vmlinux.bin.gz -d vmlinux.bin.gz vmlinux.img +ls -l vmlinux.img + + +VI. ONBOARD FLASH Support + +FLASH support is provided for the onboard FLASH chip Bootrom area. +U-Boot is loaded into either the ROM boot region of the FLASH chip, +after first being boot-strapped from a pre-progammed AMD29F040 PLCC +bootrom. The PLCC needs to be programmed with a ROM burner using +AMD 29F040 ROM parts and the u-boot.bin or u-boot.hex (S-Record) +images. + +The PLCC overlays this same region of flash as the onboard FLASH, +the jumper J100 is a chip-select for which flash chip you want to +progam. When jumper J100 is connected to pins 2-3, you boot from +PLCC FLASH. + +To bringup a system, simply flash a flash an AMD29F040 PLCC +bootrom, and put this in the PLCC socket. Move jumper J100 to +pins 2-3 and boot from the PLCC. + + +Now, while the system is running, move Jumper J100 to +pins 1-2 and follow the procedure below to FLASH a bootrom +(u-boot.bin) image into the onboard bootrom region (AMD29LV160DB): + +tftp 100000 u-boot.bin +protect off FFF00000 FFF7FFFF +erase FFF00000 FFF7FFFF +cp.b 100000 FFF00000 \$(filesize)\ + + +Here is an example: + +=>tftp 100000 u-boot.bin +eth_halt +eth0: DC21143 Ethernet adapter(bus=0, device=13, func=0) +DEC Ethernet iobase=0x80000000 +ARP broadcast 1 +Filename 'u-boot.bin'. +Load address: 0x100000 +Loading: ######################### +done +Bytes transferred = 123220 (1e154 hex) +eth_halt +=>protect off FFF00000 FFF7FFFF +Un-Protected 8 sectors +=>erase FFF00000 FFF7FFFF +Erase Flash from 0xfff00000 to 0xfff7ffff +Erase FLASH[PLCC_BOOT] -8 sectors:........ done +Erased 8 sectors +=>cp.b 100000 FFF00000 1e154 +Copy to Flash... FLASH[PLCC_BOOT]:..done +=> + + +B. FLASH RAMDISK REGION + +FLASH support is provided for an Onboard 512K RAMDISK region. + +TThe following commands will FLASH a bootrom (u-boot.bin) image +into the onboard FLASH region (AMD29LV160DB 2MB FLASH): + +tftp 100000 u-boot.bin +protect off FFF80000 FFFFFFFF +erase FFF80000 FFFFFFFF +cp.b 100000 FFF80000 \$(filesize)\ + + + +C. FLASH KERNEL REGION (960KB) + +FLASH support is provided for the 960KB onboard FLASH1 segment. +This allows flashing of kernel images which U-Boot can load +and run (standalone) from the onboard FLASH chip. It also assumes + +The following commands will FLASH a kernel image to 0xffe10000 + +tftp 100000 vmlinux.img +protect off FFE10000 FFEFFFFF +erase FFE10000 FFEFFFFF +cp.b 100000 FFE10000 \$(filesize)\ +reset + +Here is an example: + + +=>tftp 100000 vmlinux.img +eth_halt +eth0: DC21143 Ethernet adapter(bus=0, device=13, func=0) +DEC Ethernet iobase=0x80000000 +ARP broadcast 1 +TFTP from server 209.128.93.133; our IP address is 209.128.93.138 +Filename 'vmlinux.img'. +Load address: 0x100000 +Loading: ##################################################################################################################################################### +done +Bytes transferred = 760231 (b99a7 hex) +eth_halt +=>protect off FFE10000 FFEFFFFF +Un-Protected 15 sectors +=>erase FFE10000 FFEFFFFF +Erase Flash from 0xffe10000 to 0xffefffff +Erase FLASH[F0_SA3(KERNEL)] -15 sectors:............... done +Erased 15 sectors +=>cp.b 100000 FFE10000 b99a7 +Copy to Flash... FLASH[F0_SA3(KERNEL)]:............done +=> + + + +When finished, use the command: + +bootm ffe10000 + +to start the kernel. + +Finally, to make this the default boot command, use +the following commands: + +setenv bootcmd bootm ffe10000 +savenv + +to make it automatically boot the kernel from FLASH. + + +To go back to development mode (NFS boot) + +setenv bootcmd tftp 100000 vmlinux.img\;bootm +savenv + + +=>tftp 100000 vmlinux.img +eth0: DC21143 Ethernet adapter(bus=0, device=13, func=0) +DEC Ethernet iobase=0x80000000 +ARP broadcast 1 +Filename 'vmlinux.img'. +Load address: 0x100000 +Loading: #################################################################################################################################################### +done +Bytes transferred = 752717 (b7c4d hex) +eth_halt +=>protect off FFE10000 FFEFFFFF +Un-Protected 15 sectors +=>erase FFE10000 FFEFFFFF +Erase Flash from 0xffe10000 to 0xffefffff +Erase FLASH[F0_SA3(KERNEL)] -15 sectors:............... done +Erased 15 sectors +=>cp.b 100000 FFE10000 b7c4d +Copy to Flash... FLASH[F0_SA3(KERNEL)]:............done +=>bootm ffe10000 +## Booting image at ffe10000 ... + Image Name: vmlinux.bin.gz + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 752653 Bytes = 735 kB = 0 MB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK +Total memory = 64MB; using 0kB for hash table (at 00000000) +Linux version 2.4.2_hhl20 (jfd@atlantis) (gcc version 2.95.2 19991024 (release)) #597 Wed Sep 5 23:23:23 PDT 2001 +cpu0: MPC8240/KAHLUA : MOUSSE Platform : 64MB RAM: MPLD Rev. 7f +Sandpoint port (C) 2000, 2001 MontaVista Software, Inc. (source@mvista.com) +IP PNP: 802.3 Ethernet Address=<0:0:10:20:30:44> +NOTICE: mounting root file system via NFS +On node 0 totalpages: 16384 +zone(0): 16384 pages. +zone(1): 0 pages. +zone(2): 0 pages. +time_init: decrementer frequency = 16.665914 MHz +time_init: MPC8240 PCI Bus frequency = 33.331828 MHz +Calibrating delay loop... 133.12 BogoMIPS +Memory: 62436k available (1336k kernel code, 500k data, 88k init, 0k highmem) +Dentry-cache hash table entries: 8192 (order: 4, 65536 bytes) +Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes) +Page-cache hash table entries: 16384 (order: 4, 65536 bytes) +Inode-cache hash table entries: 4096 (order: 3, 32768 bytes) +POSIX conformance testing by UNIFIX +PCI: Probing PCI hardware +Linux NET4.0 for Linux 2.4 +Based upon Swansea University Computer Society NET3.039 +Initializing RT netlink socket +Starting kswapd v1.8 +pty: 256 Unix98 ptys configured +block: queued sectors max/low 41394kB/13798kB, 128 slots per queue +Uniform Multi-Platform E-IDE driver Revision: 6.31 +ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx +PDC20262: IDE controller on PCI bus 00 dev 70 +PDC20262: chipset revision 1 +PDC20262: not 100% native mode: will probe irqs later +PDC20262: ROM enabled at 0x000d0000 +PDC20262: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode. +PDC20262: FORCING BURST BIT 0x00 -> 0x01 ACTIVE +PDC20262: irq=3 dev->irq=3 + ide0: BM-DMA at 0xbfff00-0xbfff07, BIOS settings: hda:DMA, hdb:DMA + ide1: BM-DMA at 0xbfff08-0xbfff0f, BIOS settings: hdc:pio, hdd:pio +hda: WDC WD300AB-00BVA0, ATA DISK drive +hdc: SONY CD-RW CRX160E, ATAPI CD/DVD-ROM drive +ide0 at 0xbfff78-0xbfff7f,0xbfff76 on irq 3 +ide1 at 0xbfff68-0xbfff6f,0xbfff66 on irq 3 +hda: 58633344 sectors (30020 MB) w/2048KiB Cache, CHS=58168/16/63, UDMA(66) +hdc: ATAPI 32X CD-ROM CD-R/RW drive, 4096kB Cache +Uniform CD-ROM driver Revision: 3.12 +Partition check: + /dev/ide/host0/bus0/target0/lun0: p1 p2 +hd: unable to get major 3 for hard disk +udf: registering filesystem +loop: loaded (max 8 devices) +Serial driver version 5.02 (2000-08-09) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled +ttyS00 at 0xffe08080 (irq = 4) is a ST16650 +Linux Tulip driver version 0.9.13a (January 20, 2001) +eth0: Digital DS21143 Tulip rev 65 at 0xbfff80, EEPROM not present, 00:00:10:20:30:44, IRQ 1. +eth0: MII transceiver #0 config 3000 status 7829 advertising 01e1. +NET4: Linux TCP/IP 1.0 for NET4.0 +IP Protocols: ICMP, UDP, TCP +IP: routing cache hash table of 512 buckets, 4Kbytes +TCP: Hash tables configured (established 4096 bind 4096) +NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. +devfs: v0.102 (20000622) Richard Gooch (rgooch@atnf.csiro.au) +devfs: boot_options: 0x0 +VFS: Mounted root (nfs filesystem). +Mounted devfs on /dev +Freeing unused kernel memory: 88k init 4k openfirmware +eth0: Setting full-duplex based on MII#0 link partner capability of 45e1. +INIT: version 2.78 booting +INIT: Entering runlevel: 2 + + +Welcome to Linux/PPC +MPC8240/MOUSSE + + +mousse login: root +Password: +PAM_unix[13]: (login) session opened for user root by LOGIN(uid=0) +Last login: Thu Sep 6 00:16:51 2001 on console + + +Welcome to Linux/PPC +MPC8240/MOUSSE + + +mousse# diff --git a/board/mousse/mousse.h b/board/mousse/mousse.h new file mode 100644 index 0000000..5468314 --- /dev/null +++ b/board/mousse/mousse.h @@ -0,0 +1,259 @@ +/* + * MOUSSE/MPC8240 Board definitions. + * For more info, see http://www.vooha.com/ + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 + * James Dougherty (jfd@cs.stanford.edu) + * + * 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 __MOUSSE_H +#define __MOUSSE_H + +/* System addresses */ + +#define PCI_SPECIAL_BASE 0xfe000000 +#define PCI_SPECIAL_SIZE 0x01000000 + +/* PORTX Device Addresses for Mousse */ + +#define PORTX_DEV_BASE 0xff000000 +#define PORTX_DEV_SIZE 0x01000000 + +#define ENET_DEV_BASE 0x80000000 + +#define PLD_REG_BASE (PORTX_DEV_BASE | 0xe09000) +#define PLD_REG(off) (*(volatile unsigned char *) \ + (PLD_REG_BASE + (off))) + +#define PLD_REVID_B1 0x7f +#define PLD_REVID_B2 0x01 + +/* MPLD */ +#define SYS_HARD_RESET() { for (;;) PLD_REG(0) = 0; } /* clr 0x80 bit */ +#define SYS_REVID_GET() ((int) PLD_REG(0) & 0x7f) +#define SYS_LED_OFF() (PLD_REG(1) |= 0x80) +#define SYS_LED_ON() (PLD_REG(1) &= ~0x80) +#define SYS_WATCHDOG_IRQ3() (PLD_REG(2) |= 0x80) +#define SYS_WATCHDOG_RESET() (PLD_REG(2) &= ~0x80) +#define SYS_TOD_PROTECT() (PLD_REG(3) |= 0x80) +#define SYS_TOD_UNPROTECT() (PLD_REG(3) &= ~0x80) + +/* SGS M48T59Y */ +#define TOD_BASE (PORTX_DEV_BASE | 0xe0a000) +#define TOD_REG_BASE (TOD_BASE | 0x1ff0) +#define TOD_NVRAM_BASE TOD_BASE +#define TOD_NVRAM_SIZE 0x1ff0 +#define TOD_NVRAM_LIMIT (TOD_NVRAM_BASE + TOD_NVRAM_SIZE) + +/* NS16552 SIO */ +#define SERIAL_BASE(_x) (PORTX_DEV_BASE | 0xe08000 | ((_x) ? 0 : 0x80)) +#define N_SIO_CHANNELS 2 +#define N_COM_PORTS N_SIO_CHANNELS + +/* + * On-board Dec21143 PCI Ethernet + * Note: The PCI MBAR chosen here was used from MPC8240UM which states + * that PCI memory is at: 0x80000 - 0xFDFFFFFF, if AMBOR[CPU_FD_ALIAS] + * is set, then PCI memory maps 1-1 with this address range in the + * correct byte order. + */ +#define PCI_ENET_IOADDR 0x80000000 +#define PCI_ENET_MEMADDR 0x80000000 + +/* + * Flash Memory Layout + * + * 2 MB Flash Bank 0 runs in 8-bit mode. In Flash Bank 0, the 32 kB + * sector SA3 is obscured by the 32 kB serial/TOD access space, and + * the 64 kB sectors SA19-SA26 are obscured by the 512 kB PLCC + * containing the fixed boot ROM. (If the 512 kB PLCC is + * deconfigured by jumper, this window to Flash Bank 0 becomes + * visible, but it still contains the fixed boot code and should be + * considered read-only). Flash Bank 0 sectors SA0 (16 kB), SA1 (8 + * kB), and SA2 (8 kB) are currently unused. + * + * 2 MB Flash Bank 1 runs in 16-bit mode. Flash Bank 1 is fully + * usable, but it's a 16-bit wide device on a 64-bit bus. Therefore + * 16-bit words only exist at addresses that are multiples of 8. All + * PROM data and control addresses must be multiplied by 8. + * + * See flashMap.c for description of flash filesystem layout. + */ + +/* + * FLASH memory address space: 8-bit wide FLASH memory spaces. + */ +#define FLASH0_SEG0_START 0xffe00000 /* Baby 32Kb segment */ +#define FLASH0_SEG0_END 0xffe07fff /* 16 kB + 8 kB + 8 kB */ +#define FLASH0_SEG0_SIZE 0x00008000 /* (sectors SA0-SA2) */ + +#define FLASH0_SEG1_START 0xffe10000 /* 1MB - 64Kb FLASH0 seg */ +#define FLASH0_SEG1_END 0xffefffff /* 960 kB */ +#define FLASH0_SEG1_SIZE 0x000f0000 + +#define FLASH0_SEG2_START 0xfff00000 /* Boot Loader stored here */ +#define FLASH0_SEG2_END 0xfff7ffff /* 512 kB FLASH0/PLCC seg */ +#define FLASH0_SEG2_SIZE 0x00080000 + +#define FLASH0_SEG3_START 0xfff80000 /* 512 kB FLASH0 seg */ +#define FLASH0_SEG3_END 0xffffffff +#define FLASH0_SEG3_SIZE 0x00080000 + +/* Where Kahlua starts */ +#define FLASH_RESET_VECT 0xfff00100 + +/* + * CHRP / PREP (MAP A/B) definitions. + */ + +#define PREP_REG_ADDR 0x80000cf8 /* MPC107 Config, Map A */ +#define PREP_REG_DATA 0x80000cfc /* MPC107 Config, Map A */ +/* MPC107 (MPC8240 internal EUMBBAR mapped) */ +#define CHRP_REG_ADDR 0xfec00000 /* MPC106 Config, Map B */ +#define CHRP_REG_DATA 0xfee00000 /* MPC106 Config, Map B */ + +/* + * Mousse PCI IDSEL Assignments (Device Number) + */ +#define MOUSSE_IDSEL_ENET 13 /* On-board 21143 Ethernet */ +#define MOUSSE_IDSEL_LPCI 14 /* On-board PCI slot */ +#define MOUSSE_IDSEL_82371 15 /* That other thing */ +#define MOUSSE_IDSEL_CPCI2 31 /* CPCI slot 2 */ +#define MOUSSE_IDSEL_CPCI3 30 /* CPCI slot 3 */ +#define MOUSSE_IDSEL_CPCI4 29 /* CPCI slot 4 */ +#define MOUSSE_IDSEL_CPCI5 28 /* CPCI slot 5 */ +#define MOUSSE_IDSEL_CPCI6 27 /* CPCI slot 6 */ + +/* + * Mousse Interrupt Mapping: + * + * IRQ1 Enet (intA|intB|intC|intD) + * IRQ2 CPCI intA (See below) + * IRQ3 Local PCI slot intA|intB|intC|intD + * IRQ4 COM1 Serial port (Actually higher addressed port on duart) + * + * PCI Interrupt Mapping in CPCI chassis: + * + * | CPCI Slot + * | 1 (CPU) 2 3 4 5 6 + * -----------+--------+-------+-------+-------+-------+-------+ + * intA | X X X + * intB | X X X + * intC | X X X + * intD | X X X + */ + + +#define EPIC_VECTOR_EXT0 0 +#define EPIC_VECTOR_EXT1 1 +#define EPIC_VECTOR_EXT2 2 +#define EPIC_VECTOR_EXT3 3 +#define EPIC_VECTOR_EXT4 4 +#define EPIC_VECTOR_TM0 16 +#define EPIC_VECTOR_TM1 17 +#define EPIC_VECTOR_TM2 18 +#define EPIC_VECTOR_TM3 19 +#define EPIC_VECTOR_I2C 20 +#define EPIC_VECTOR_DMA0 21 +#define EPIC_VECTOR_DMA1 22 +#define EPIC_VECTOR_I2O 23 + + +#define INT_VEC_IRQ0 0 +#define INT_NUM_IRQ0 INT_VEC_IRQ0 +#define MOUSSE_IRQ_ENET EPIC_VECTOR_EXT1 /* Hardwired */ +#define MOUSSE_IRQ_CPCI EPIC_VECTOR_EXT2 /* Hardwired */ +#define MOUSSE_IRQ_LPCI EPIC_VECTOR_EXT3 /* Hardwired */ +#define MOUSSE_IRQ_DUART EPIC_VECTOR_EXT4 /* Hardwired */ + +/* Onboard DEC 21143 Ethernet */ +#define PCI_ENET_MEMADDR 0x80000000 +#define PCI_ENET_IOADDR 0x80000000 + +/* Some other PCI device */ +#define PCI_SLOT_MEMADDR 0x81000000 +#define PCI_SLOT_IOADDR 0x81000000 + +/* Promise ATA66 PCI Device (ATA controller) */ +#define PROMISE_MBAR0 0xa0000000 +#define PROMISE_MBAR1 (PROMISE_MBAR0 + 0x1000) +#define PROMISE_MBAR2 (PROMISE_MBAR0 + 0x2000) +#define PROMISE_MBAR3 (PROMISE_MBAR0 + 0x3000) +#define PROMISE_MBAR4 (PROMISE_MBAR0 + 0x4000) +#define PROMISE_MBAR5 (PROMISE_MBAR0 + 0x5000) + +/* ATA/66 Controller offsets */ +#define CFG_ATA_BASE_ADDR PROMISE_MBAR0 +#define CFG_IDE_MAXBUS 2 /* ide0/ide1 */ +#define CFG_IDE_MAXDEVICE 2 /* 2 drives per controller */ +#define CFG_ATA_IDE0_OFFSET 0 +#define CFG_ATA_IDE1_OFFSET 0x3000 +/* + * Definitions for accessing IDE controller registers + */ +#define CFG_ATA_DATA_OFFSET 0 +#define CFG_ATA_REG_OFFSET 0 +#define CFG_ATA_ALT_OFFSET (0x1000) + +/* + * The constants ROM_TEXT_ADRS, ROM_SIZE, RAM_HIGH_ADRS, and RAM_LOW_ADRS + * are defined in config.h and Makefile. + * All definitions for these constants must be identical. + */ +#define ROM_BASE_ADRS 0xfff00000 /* base address of ROM */ +#define ROM_TEXT_ADRS (ROM_BASE_ADRS+0x0100) /* with PC & SP */ +#define ROM_WARM_ADRS (ROM_TEXT_ADRS+0x0004) /* warm reboot entry */ +#define ROM_SIZE 0x00080000 /* 512KB ROM space */ +#define RAM_LOW_ADRS 0x00010000 /* RAM address for vxWorks */ +#define RAM_HIGH_ADRS 0x00c00000 /* RAM address for bootrom */ + +/* + * NVRAM configuration + * NVRAM is implemented via the SGS Thomson M48T59Y + * 64Kbit (8Kbx8) Timekeeper SRAM. + * This 8KB NVRAM also has a TOD. See m48t59y.{h,c} for more information. + */ + +#define NV_RAM_ADRS TOD_NVRAM_BASE +#define NV_RAM_INTRVL 1 +#define NV_RAM_WR_ENBL SYS_TOD_UNPROTECT() +#define NV_RAM_WR_DSBL SYS_TOD_PROTECT() + +#define NV_OFF_BOOT0 0x0000 /* Boot string 0 (256b) */ +#define NV_OFF_BOOT1 0x0100 /* Boot string 1 (256b) */ +#define NV_OFF_BOOT2 0x0200 /* Boot string 2 (256b)*/ +#define NV_OFF_MACADDR 0x0400 /* 21143 MAC address (6b) */ +#define NV_OFF_ACTIVEBOOT 0x0406 /* Active boot string, 0 to 2 (1b) */ +#define NV_OFF_UNUSED1 0x0407 /* Unused (1b) */ +#define NV_OFF_BINDFIX 0x0408 /* See sysLib.c:sysBindFix() (1b) */ +#define NV_OFF_UNUSED2 0x0409 /* Unused (7b) */ +#define NV_OFF_TIMEZONE 0x0410 /* TIMEZONE env var (64b) */ +#define NV_OFF_VXWORKS_END 0x07FF /* 2047 VxWorks Total */ +#define NV_OFF_U_BOOT 0x0800 /* 2048 U-Boot boot-loader */ +#define NV_OFF_U_BOOT_ADDR (TOD_BASE + NV_OFF_U_BOOT) /* sysaddr*/ +#define NV_U_BOOT_ENV_SIZE 2048 /* 2K - U-Boot Total */ +#define NV_OFF__next_free (NV_U_BOOT_ENVSIZE +1) +#define NV_RAM_SIZE 8176 /* NVRAM End */ + +#endif /* __MOUSSE_H */ diff --git a/board/mvs1/README b/board/mvs1/README new file mode 100644 index 0000000..6c66d67 --- /dev/null +++ b/board/mvs1/README @@ -0,0 +1,15 @@ +This port is for the MATRIX Vision mvSensor. +It is an mpc823-based universal image processing board +with CMOS or CCD sensor, 4MB FLASH and 16-64MB RAM. + +See http://www.matrix-vision.de for more details or mail... + +mvsensor@matrix-vision.de + +Howard Gray +MATRIX Vision GmbH +Talstr. 16 +D-71570 +Oppenweiler +Germany + diff --git a/board/mvs1/mvs1.c b/board/mvs1/mvs1.c new file mode 100644 index 0000000..da98de5 --- /dev/null +++ b/board/mvs1/mvs1.c @@ -0,0 +1,404 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Changes for MATRIX Vision MVsensor (C) Copyright 2001 + * MATRIX Vision GmbH / hg, info@matrix-vision.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 <mpc8xx.h> + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFFFFF + +const uint sdram_table[] = +{ + /* + * Single Read. (Offset 0 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00, + 0x1FF5FC47, /* last */ + /* + * SDRAM Initialization (offset 5 in UPMA RAM) + * + * This is no UPM entry point. The following definition uses + * the remaining space to establish an initialization + * sequence, which is executed by a RUN command. + * + */ + 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ + /* + * Burst Read. (Offset 8 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, + 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPMA RAM) + */ + 0x1F0DFC04 /*0x1F2DFC04??*/, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00, + 0xF0AFFC00, 0xE1BAFC04, 0x1FF5FC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPMA RAM) + */ + 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, + 0xFFFFFC84, 0xFFFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPMA RAM) + */ + 0x7FFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: MATRIX Vision MVsensor\n"); + return 0; +} + + + +#ifdef DO_RAM_TEST +/* ------------------------------------------------------------------------- */ + +/* + * Test SDRAM by writing its address to itself and reading several times +*/ +#define READ_RUNS 4 +static void test_dram (unsigned long *start, unsigned long *end) +{ + unsigned long *addr; + unsigned long value; + int read_runs, errors, addr_errors; + + printf ("\nChecking SDRAM from %p to %p\n", start, end); + udelay (1000000); + for (addr = start; addr < end; addr++) + *addr = (unsigned long) addr; + + for (addr = start, addr_errors = 0; addr < end; addr++) { + for (read_runs = READ_RUNS, errors = 0; read_runs > 0; read_runs--) { + if ((value = *addr) != (unsigned long) addr) + errors++; + } + if (errors > 0) { + addr_errors++; + printf ("SDRAM errors (%d) at %p, last read = %ld\n", + errors, addr, value); + udelay (10000); + } + } + printf ("SDRAM check finished, total errors = %d\n", addr_errors); +} +#endif /* DO_RAM_TEST */ + + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size_b0, size_b1, size8, size9; + + upmconfig (UPMA, (uint *) sdram_table, + sizeof (sdram_table) / sizeof (uint)); + + /* + * Preliminary prescaler for refresh (depends on number of + * banks): This value is selected for four cycles every 62.4 us + * with two SDRAM banks or four cycles every 31.2 us with one + * bank. It will be adjusted after memory sizing. + */ + memctl->memc_mptpr = CFG_MPTPR_2BK_8K; + + memctl->memc_mar = 0x00000088; + + /* + * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at + * preliminary addresses - these have to be modified after the + * SDRAM size has been determined. + */ + memctl->memc_or2 = CFG_OR2_PRELIM; + memctl->memc_br2 = CFG_BR2_PRELIM; + +#if defined (CFG_OR3_PRELIM) && defined (CFG_BR3_PRELIM) + if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ + memctl->memc_or3 = CFG_OR3_PRELIM; + memctl->memc_br3 = CFG_BR3_PRELIM; + } +#endif + + memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ + + udelay (200); + + /* perform SDRAM initializsation sequence */ + + memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */ + udelay (1); + memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */ + udelay (1); + + if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ + memctl->memc_mcr = 0x80006105; /* SDRAM bank 1 */ + udelay (1); + memctl->memc_mcr = 0x80006230; /* SDRAM bank 1 - execute twice */ + udelay (1); + } + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay (1000); + + /* + * Check Bank 0 Memory Size for re-configuration + * + * try 8 column mode + */ + size8 = dram_size (CFG_MAMR_8COL, (ulong *) SDRAM_BASE2_PRELIM, + SDRAM_MAX_SIZE); + + udelay (1000); + /* + * try 9 column mode + */ + size9 = dram_size (CFG_MAMR_9COL, (ulong *) SDRAM_BASE2_PRELIM, + SDRAM_MAX_SIZE); + + if (size8 < size9) { /* leave configuration at 9 columns */ + size_b0 = size9; + } else { /* back to 8 columns */ + size_b0 = size8; + memctl->memc_mamr = CFG_MAMR_8COL; + udelay (500); + } + + if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ + /* + * Check Bank 1 Memory Size + * use current column settings + * [9 column SDRAM may also be used in 8 column mode, + * but then only half the real size will be used.] + */ +#if defined (SDRAM_BASE3_PRELIM) + size_b1 = + dram_size (memctl->memc_mamr, (ulong *) SDRAM_BASE3_PRELIM, + SDRAM_MAX_SIZE); +#else + size_b1 = 0; +#endif + } else { + size_b1 = 0; + } + + udelay (1000); + + /* + * Adjust refresh rate depending on SDRAM type, both banks + * For types > 128 MBit leave it at the current (fast) rate + */ + if ((size_b0 < 0x02000000) && (size_b1 < 0x02000000)) { + /* reduce to 15.6 us (62.4 us / quad) */ + memctl->memc_mptpr = CFG_MPTPR_2BK_4K; + udelay (1000); + } + + /* + * Final mapping: map bigger bank first + */ + if (size_b1 > size_b0) { /* SDRAM Bank 1 is bigger - map first */ + + memctl->memc_or3 = ((-size_b1) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br3 = + (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; + + if (size_b0 > 0) { + /* + * Position Bank 0 immediately above Bank 1 + */ + memctl->memc_or2 = + ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br2 = + ((CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) + + size_b1; + } else { + unsigned long reg; + + /* + * No bank 0 + * + * invalidate bank + */ + memctl->memc_br2 = 0; + + /* adjust refresh rate depending on SDRAM type, one bank */ + reg = memctl->memc_mptpr; + reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */ + memctl->memc_mptpr = reg; + } + + } else { /* SDRAM Bank 0 is bigger - map first */ + + memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br2 = + (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; + + if (size_b1 > 0) { + /* + * Position Bank 1 immediately above Bank 0 + */ + memctl->memc_or3 = + ((-size_b1) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br3 = + ((CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) + + size_b0; + } else { + unsigned long reg; + + /* + * No bank 1 + * + * invalidate bank + */ + memctl->memc_br3 = 0; + + /* adjust refresh rate depending on SDRAM type, one bank */ + reg = memctl->memc_mptpr; + reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */ + memctl->memc_mptpr = reg; + } + } + + udelay (10000); + +#ifdef DO_RAM_TEST + if (size_b0 > 0) + test_dram ((unsigned long *) CFG_SDRAM_BASE, + (unsigned long *) (CFG_SDRAM_BASE + size_b0)); +#endif + + return (size_b0 + size_b1); +} + +/* ------------------------------------------------------------------------- */ + +/* + * 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; + long int cnt, val; + + + memctl->memc_mamr = mamr_value; + + for (cnt = maxsize / sizeof (long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + return (0); + } + + for (cnt = 1;; cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + /* NOTREACHED */ +} + + +/* ------------------------------------------------------------------------- */ + +u8 *dhcp_vendorex_prep (u8 * e) +{ + char *ptr; + +/* DHCP vendor-class-identifier = 60 */ + if ((ptr = getenv ("dhcp_vendor-class-identifier"))) { + *e++ = 60; + *e++ = strlen (ptr); + while (*ptr) + *e++ = *ptr++; + } +/* my DHCP_CLIENT_IDENTIFIER = 61 */ + if ((ptr = getenv ("dhcp_client_id"))) { + *e++ = 61; + *e++ = strlen (ptr); + while (*ptr) + *e++ = *ptr++; + } + + return e; +} + + +/* ------------------------------------------------------------------------- */ +u8 *dhcp_vendorex_proc (u8 * popt) +{ + return NULL; +} diff --git a/board/ppmc8260/ppmc8260.c b/board/ppmc8260/ppmc8260.c new file mode 100644 index 0000000..ab32622 --- /dev/null +++ b/board/ppmc8260/ppmc8260.c @@ -0,0 +1,307 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2001 + * Advent Networks, Inc. <http://www.adventnetworks.com> + * Jay Monkman <jtm@smoothsmoothie.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 + */ + +#include <common.h> +#include <ioports.h> +#include <mpc8260.h> + +/* + * I/O Port configuration table + * + * if conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +const iop_conf_t iop_conf_tab[4][32] = { + + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 *ATMTXEN */ + /* PA30 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTCA */ + /* PA29 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTSOC */ + /* PA28 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 *ATMRXEN */ + /* PA27 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRSOC */ + /* PA26 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRCA */ + /* PA25 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[0] */ + /* PA24 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[1] */ + /* PA23 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[2] */ + /* PA22 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[3] */ + /* PA21 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[4] */ + /* PA20 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[5] */ + /* PA19 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[6] */ + /* PA18 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[7] */ + /* PA17 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[7] */ + /* PA16 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[6] */ + /* PA15 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[5] */ + /* PA14 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[4] */ + /* PA13 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[3] */ + /* PA12 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[2] */ + /* PA11 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[1] */ + /* PA10 */ { 0, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[0] */ + /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */ + /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */ + /* PA7 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_A1:L1TSYNC */ + /* PA6 */ { 1, 0, 0, 1, 0, 0 }, /* TDN_A1:L1RSYNC */ + /* PA5 */ { 0, 0, 0, 0, 0, 0 }, /* PA5 */ + /* PA4 */ { 0, 0, 0, 0, 0, 0 }, /* PA4 */ + /* PA3 */ { 0, 0, 0, 0, 0, 0 }, /* PA3 */ + /* PA2 */ { 0, 0, 0, 0, 0, 0 }, /* PA2 */ + /* PA1 */ { 0, 0, 0, 0, 0, 0 }, /* PA1 */ + /* PA0 */ { 0, 0, 0, 0, 0, 0 } /* PA0 */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */ + /* PB17 */ { 0, 0, 0, 0, 0, 0 }, /* PB17 */ + /* PB16 */ { 1, 0, 0, 0, 0, 0 }, /* TDM_A1:L1CLK0 */ + /* PB15 */ { 1, 0, 0, 1, 0, 1 }, /* /FETHRST */ + /* PB14 */ { 1, 0, 0, 1, 0, 0 }, /* FETHDIS */ + /* PB13 */ { 0, 0, 0, 0, 0, 0 }, /* PB13 */ + /* PB12 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_B1:L1CLK0 */ + /* PB11 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_D1:L1TXD */ + /* PB10 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_D1:L1RXD */ + /* PB9 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_D1:L1TSYNC */ + /* PB8 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_D1:L1RSYNC */ + /* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */ + /* PB6 */ { 0, 0, 0, 0, 0, 0 }, /* PB6 */ + /* PB5 */ { 0, 0, 0, 0, 0, 0 }, /* PB5 */ + /* PB4 */ { 0, 0, 0, 0, 0, 0 }, /* PB4 */ + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 0, 0, 0, 0, 0, 0 }, /* PC31 */ + /* PC30 */ { 0, 0, 0, 0, 0, 0 }, /* PC30 */ + /* PC29 */ { 0, 0, 0, 0, 0, 0 }, /* PC28 */ + /* PC28 */ { 1, 1, 0, 0, 0, 0 }, /* CLK4 */ + /* PC27 */ { 0, 0, 0, 0, 0, 0 }, /* PC27 */ + /* PC26 */ { 0, 0, 0, 0, 0, 0 }, /* PC26 */ + /* PC25 */ { 1, 1, 0, 0, 0, 0 }, /* CLK7 */ + /* PC24 */ { 0, 0, 0, 0, 0, 0 }, /* PC24 */ + /* PC23 */ { 1, 0, 0, 1, 0, 0 }, /* ATMTFCLK */ + /* PC22 */ { 0, 0, 0, 0, 0, 0 }, /* PC22 */ + /* PC21 */ { 0, 0, 0, 0, 0, 0 }, /* PC23 */ + /* PC20 */ { 0, 0, 0, 0, 0, 0 }, /* PC24 */ + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */ + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */ + /* PC17 */ { 0, 0, 0, 0, 0, 0 }, /* PC17 */ + /* PC16 */ { 0, 0, 0, 0, 0, 0 }, /* PC16 */ + /* PC15 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:TxAddr[0] */ + /* PC14 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:RxAddr[0] */ + /* PC13 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:TxAddr[1] */ + /* PC12 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:RxAddr[1] */ + /* PC11 */ { 1, 1, 0, 1, 0, 0 }, /* TDM_D1:L1CLK0 */ + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDC */ + /* PC9 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDIO */ + /* PC8 */ { 0, 0, 0, 0, 0, 0 }, /* PC8 */ + /* PC7 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:TxAddr[2]*/ + /* PC6 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:RxAddr[2] */ + /* PC5 */ { 0, 0, 0, 0, 0, 0 }, /* PC5 */ + /* PC4 */ { 0, 0, 0, 0, 0, 0 }, /* PC4 */ + /* PC3 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA2:DACK */ + /* PC2 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA2:DONE */ + /* PC1 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA2:DREQ */ + /* PC0 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA1:DREQ */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 0, 0, 0, 0, 0, 0 }, /* PD31 */ + /* PD30 */ { 0, 0, 0, 0, 0, 0 }, /* PD30 */ + /* PD29 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1:RxAddr[3] */ + /* PD28 */ { 0, 0, 0, 0, 0, 0 }, /* PD28 */ + /* PD27 */ { 0, 0, 0, 0, 0, 0 }, /* PD27 */ + /* PD26 */ { 1, 0, 0, 1, 0, 0 }, /* TDM_C1:L1RSYNC */ + /* PD25 */ { 0, 0, 0, 0, 0, 0 }, /* PD25 */ + /* PD24 */ { 0, 0, 0, 0, 0, 0 }, /* PD24 */ + /* PD23 */ { 0, 0, 0, 0, 0, 0 }, /* PD23 */ + /* PD22 */ { 0, 0, 0, 0, 0, 0 }, /* PD22 */ + /* PD21 */ { 0, 0, 0, 0, 0, 0 }, /* PD21 */ + /* PD20 */ { 0, 0, 0, 0, 0, 0 }, /* PD20 */ + /* PD19 */ { 0, 0, 0, 0, 0, 0 }, /* PD19 */ + /* PD18 */ { 0, 0, 0, 0, 0, 0 }, /* PD19 */ + /* PD17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */ + /* PD16 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */ + /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */ + /* PD13 */ { 1, 0, 0, 0, 0, 0 }, /* TDM_B1:L1TXD */ + /* PD12 */ { 1, 0, 0, 0, 0, 0 }, /* TDM_B1:L1RXD */ + /* PD11 */ { 1, 0, 0, 0, 0, 0 }, /* TDM_B1:L1TSYNC */ + /* PD10 */ { 1, 0, 0, 0, 0, 0 }, /* TDM_B1:L1RSYNC*/ + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1:TXD */ + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1:RXD */ + /* PD7 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1:SMSYN */ + /* PD6 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA1:DACK */ + /* PD5 */ { 1, 0, 0, 1, 0, 0 }, /* IDMA1:DONE */ + /* PD4 */ { 0, 0, 0, 0, 0, 0 }, /* PD4 */ + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: Wind River PPMC8260\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + volatile uchar c = 0xff; + volatile uchar *ramaddr0 = (uchar *) (CFG_SDRAM0_BASE); + volatile uchar *ramaddr1 = (uchar *) (CFG_SDRAM1_BASE); + ulong psdmr = CFG_PSDMR; + volatile uchar *ramaddr2 = (uchar *) (CFG_SDRAM2_BASE); + ulong lsdmr = CFG_LSDMR; + int i; + + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + memctl->memc_psrt = CFG_PSRT; + memctl->memc_mptpr = CFG_MPTPR; + +#ifndef CFG_RAMBOOT + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr0++ = c; + *ramaddr1++ = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) { + *ramaddr0++ = c; + *ramaddr1++ = c; + } + + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + ramaddr0 = (uchar *) (CFG_SDRAM0_BASE + 0x110); + ramaddr1 = (uchar *) (CFG_SDRAM1_BASE + 0x110); + *ramaddr0 = c; + *ramaddr1 = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr0 = c; + *ramaddr1 = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_PREA; + *ramaddr2++ = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) { + *ramaddr2++ = c; + } + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_MRW; + *ramaddr2++ = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr2 = c; +#endif + + /* return total ram size */ + return ((CFG_SDRAM0_SIZE + CFG_SDRAM1_SIZE) * 1024 * 1024); +} + +#ifdef CONFIG_MISC_INIT_R +/* ------------------------------------------------------------------------- */ +int misc_init_r (void) +{ +#ifdef CFG_LED_BASE + uchar ds = *(unsigned char *) (CFG_LED_BASE + 1); + uchar ss; + uchar tmp[64]; + int res; + + if ((ds != 0) && (ds != 0xff)) { + res = getenv_r ("ethaddr", tmp, sizeof (tmp)); + if (res > 0) { + ss = ((ds >> 4) & 0x0f); + ss += ss < 0x0a ? '0' : ('a' - 10); + tmp[15] = ss; + + ss = (ds & 0x0f); + ss += ss < 0x0a ? '0' : ('a' - 10); + tmp[16] = ss; + + tmp[17] = '\0'; + setenv ("ethaddr", tmp); + /* set the led to show the address */ + *((unsigned char *) (CFG_LED_BASE + 1)) = ds; + } + } +#endif /* CFG_LED_BASE */ + return (0); +} +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/ppmc8260/strataflash.c b/board/ppmc8260/strataflash.c new file mode 100644 index 0000000..bb21848 --- /dev/null +++ b/board/ppmc8260/strataflash.c @@ -0,0 +1,755 @@ +/* + * (C) Copyright 2002 + * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.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 + */ + +#include <common.h> +#include <mpc8260.h> +#include <asm/processor.h> + +#undef DEBUG_FLASH +/* + * This file implements a Common Flash Interface (CFI) driver for U-Boot. + * The width of the port and the width of the chips are determined at initialization. + * These widths are used to calculate the address for access CFI data structures. + * It has been tested on an Intel Strataflash implementation. + * + * References + * JEDEC Standard JESD68 - Common Flash Interface (CFI) + * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes + * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets + * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet + * + * TODO + * Use Primary Extended Query table (PRI) and Alternate Algorithm Query Table (ALT) to determine if protection is available + * Add support for other command sets Use the PRI and ALT to determine command set + * Verify erase and program timeouts. + */ + +#define FLASH_CMD_CFI 0x98 +#define FLASH_CMD_READ_ID 0x90 +#define FLASH_CMD_RESET 0xff +#define FLASH_CMD_BLOCK_ERASE 0x20 +#define FLASH_CMD_ERASE_CONFIRM 0xD0 +#define FLASH_CMD_WRITE 0x40 +#define FLASH_CMD_PROTECT 0x60 +#define FLASH_CMD_PROTECT_SET 0x01 +#define FLASH_CMD_PROTECT_CLEAR 0xD0 +#define FLASH_CMD_CLEAR_STATUS 0x50 +#define FLASH_CMD_WRITE_TO_BUFFER 0xE8 +#define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0 + +#define FLASH_STATUS_DONE 0x80 +#define FLASH_STATUS_ESS 0x40 +#define FLASH_STATUS_ECLBS 0x20 +#define FLASH_STATUS_PSLBS 0x10 +#define FLASH_STATUS_VPENS 0x08 +#define FLASH_STATUS_PSS 0x04 +#define FLASH_STATUS_DPS 0x02 +#define FLASH_STATUS_R 0x01 +#define FLASH_STATUS_PROTECT 0x01 + +#define FLASH_OFFSET_CFI 0x55 +#define FLASH_OFFSET_CFI_RESP 0x10 +#define FLASH_OFFSET_WTOUT 0x1F +#define FLASH_OFFSET_WBTOUT 0x20 +#define FLASH_OFFSET_ETOUT 0x21 +#define FLASH_OFFSET_CETOUT 0x22 +#define FLASH_OFFSET_WMAX_TOUT 0x23 +#define FLASH_OFFSET_WBMAX_TOUT 0x24 +#define FLASH_OFFSET_EMAX_TOUT 0x25 +#define FLASH_OFFSET_CEMAX_TOUT 0x26 +#define FLASH_OFFSET_SIZE 0x27 +#define FLASH_OFFSET_INTERFACE 0x28 +#define FLASH_OFFSET_BUFFER_SIZE 0x2A +#define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C +#define FLASH_OFFSET_ERASE_REGIONS 0x2D +#define FLASH_OFFSET_PROTECT 0x02 +#define FLASH_OFFSET_USER_PROTECTION 0x85 +#define FLASH_OFFSET_INTEL_PROTECTION 0x81 + + +#define FLASH_MAN_CFI 0x01000000 + + + + +typedef union { + unsigned char c; + unsigned short w; + unsigned long l; +} cfiword_t; + +typedef union { + unsigned char * cp; + unsigned short *wp; + unsigned long *lp; +} cfiptr_t; + +#define NUM_ERASE_REGIONS 4 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + + +/*----------------------------------------------------------------------- + * Functions + */ + + + +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c); +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf); +static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd); +static int flash_detect_cfi(flash_info_t * info); +static ulong flash_get_size (ulong base, int banknum); +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword); +static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt); +#ifdef CFG_FLASH_USE_BUFFER_WRITE +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len); +#endif +/*----------------------------------------------------------------------- + * create an address based on the offset and the port width + */ +inline uchar * flash_make_addr(flash_info_t * info, int sect, int offset) +{ + return ((uchar *)(info->start[sect] + (offset * info->portwidth))); +} +/*----------------------------------------------------------------------- + * read a character at a port width address + */ +inline uchar flash_read_uchar(flash_info_t * info, uchar offset) +{ + uchar *cp; + cp = flash_make_addr(info, 0, offset); + return (cp[info->portwidth - 1]); +} + +/*----------------------------------------------------------------------- + * read a short word by swapping for ppc format. + */ +ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset) +{ + uchar * addr; + + addr = flash_make_addr(info, sect, offset); + return ((addr[(2*info->portwidth) - 1] << 8) | addr[info->portwidth - 1]); + +} + +/*----------------------------------------------------------------------- + * read a long word by picking the least significant byte of each maiximum + * port size word. Swap for ppc format. + */ +ulong flash_read_long(flash_info_t * info, int sect, uchar offset) +{ + uchar * addr; + + addr = flash_make_addr(info, sect, offset); + return ( (addr[(2*info->portwidth) - 1] << 24 ) | (addr[(info->portwidth) -1] << 16) | + (addr[(4*info->portwidth) - 1] << 8) | addr[(3*info->portwidth) - 1]); + +} + +/*----------------------------------------------------------------------- + */ +unsigned long flash_init (void) +{ + unsigned long size; + int i; + unsigned long address; + + + /* The flash is positioned back to back, with the demultiplexing of the chip + * based on the A24 address line. + * + */ + + address = CFG_FLASH_BASE; + size = 0; + + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + size += flash_info[i].size = flash_get_size(address, i); + address += CFG_FLASH_INCREMENT; + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",i, + flash_info[0].size, flash_info[i].size<<20); + } + } + + /* Monitor protection ON by default */ +#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE) + for(i=0; flash_info[0].start[i] < CFG_MONITOR_BASE+CFG_MONITOR_LEN-1; i++) + (void)flash_real_protect(&flash_info[0], i, 1); +#endif + + return (size); +} + +/*----------------------------------------------------------------------- + */ +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + int rcode = 0; + int prot; + int sect; + + if( info->flash_id != FLASH_MAN_CFI) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + if ((s_first < 0) || (s_first > s_last)) { + printf ("- no sectors to erase\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"); + } + + + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE); + flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM); + + if(flash_full_status_check(info, sect, info->erase_blk_tout, "erase")) { + rcode = 1; + } else + printf("."); + } + } + printf (" done\n"); + return rcode; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id != FLASH_MAN_CFI) { + printf ("missing or unknown FLASH type\n"); + return; + } + + printf("CFI conformant FLASH (%d x %d)", + (info->portwidth << 3 ), (info->chipwidth << 3 )); + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + printf(" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", + info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n"); + printf (" %08lX%5s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + * 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 wp; + ulong cp; + int aln; + cfiword_t cword; + int i, rc; + + /* get lower aligned address */ + wp = (addr & ~(info->portwidth - 1)); + + /* handle unaligned start */ + if((aln = addr - wp) != 0) { + cword.l = 0; + cp = wp; + for(i=0;i<aln; ++i, ++cp) + flash_add_byte(info, &cword, (*(uchar *)cp)); + + for(; (i< info->portwidth) && (cnt > 0) ; i++) { + flash_add_byte(info, &cword, *src++); + cnt--; + cp++; + } + for(; (cnt == 0) && (i < info->portwidth); ++i, ++cp) + flash_add_byte(info, &cword, (*(uchar *)cp)); + if((rc = flash_write_cfiword(info, wp, cword)) != 0) + return rc; + wp = cp; + } + +#ifdef CFG_FLASH_USE_BUFFER_WRITE + while(cnt >= info->portwidth) { + i = info->buffer_size > cnt? cnt: info->buffer_size; + if((rc = flash_write_cfibuffer(info, wp, src,i)) != ERR_OK) + return rc; + wp += i; + src += i; + cnt -=i; + } +#else + /* handle the aligned part */ + while(cnt >= info->portwidth) { + cword.l = 0; + for(i = 0; i < info->portwidth; i++) { + flash_add_byte(info, &cword, *src++); + } + if((rc = flash_write_cfiword(info, wp, cword)) != 0) + return rc; + wp += info->portwidth; + cnt -= info->portwidth; + } +#endif /* CFG_FLASH_USE_BUFFER_WRITE */ + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + cword.l = 0; + for (i=0, cp=wp; (i<info->portwidth) && (cnt>0); ++i, ++cp) { + flash_add_byte(info, &cword, *src++); + --cnt; + } + for (; i<info->portwidth; ++i, ++cp) { + flash_add_byte(info, & cword, (*(uchar *)cp)); + } + + return flash_write_cfiword(info, wp, cword); +} + +/*----------------------------------------------------------------------- + */ +int flash_real_protect(flash_info_t *info, long sector, int prot) +{ + int retcode = 0; + + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT); + if(prot) + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET); + else + flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR); + + if((retcode = flash_full_status_check(info, sector, info->erase_blk_tout, + prot?"protect":"unprotect")) == 0) { + + info->protect[sector] = prot; + /* Intel's unprotect unprotects all locking */ + if(prot == 0) { + int i; + for(i = 0 ; i<info->sector_count; i++) { + if(info->protect[i]) + flash_real_protect(info, i, 1); + } + } + } + + return retcode; +} +/*----------------------------------------------------------------------- + * wait for XSR.7 to be set. Time out with an error if it does not. + * This routine does not set the flash to read-array mode. + */ +static int flash_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) +{ + ulong start; + + /* Wait for command completion */ + start = get_timer (0); + while(!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) { + if (get_timer(start) > info->erase_blk_tout) { + printf("Flash %s timeout at address %lx\n", prompt, info->start[sector]); + flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); + return ERR_TIMOUT; + } + } + return ERR_OK; +} +/*----------------------------------------------------------------------- + * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check. + * This routine sets the flash to read-array mode. + */ +static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) +{ + int retcode; + retcode = flash_status_check(info, sector, tout, prompt); + if((retcode == ERR_OK) && !flash_isequal(info,sector, 0, FLASH_STATUS_DONE)) { + retcode = ERR_INVAL; + printf("Flash %s error at address %lx\n", prompt,info->start[sector]); + if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)){ + printf("Command Sequence Error.\n"); + } else if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)){ + printf("Block Erase Error.\n"); + retcode = ERR_NOT_ERASED; + } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) { + printf("Locking Error\n"); + } + if(flash_isset(info, sector, 0, FLASH_STATUS_DPS)){ + printf("Block locked.\n"); + retcode = ERR_PROTECTED; + } + if(flash_isset(info, sector, 0, FLASH_STATUS_VPENS)) + printf("Vpp Low Error.\n"); + } + flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); + return retcode; +} +/*----------------------------------------------------------------------- + */ +static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c) +{ + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cword->c = c; + break; + case FLASH_CFI_16BIT: + cword->w = (cword->w << 8) | c; + break; + case FLASH_CFI_32BIT: + cword->l = (cword->l << 8) | c; + } +} + + +/*----------------------------------------------------------------------- + * make a proper sized command based on the port and chip widths + */ +static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf) +{ + int i; + uchar *cp = (uchar *)cmdbuf; + for(i=0; i< info->portwidth; i++) + *cp++ = ((i+1) % info->chipwidth) ? '\0':cmd; +} + +/* + * Write a proper sized command to the correct address + */ +static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + + volatile cfiptr_t addr; + cfiword_t cword; + addr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + *addr.cp = cword.c; + break; + case FLASH_CFI_16BIT: + *addr.wp = cword.w; + break; + case FLASH_CFI_32BIT: + *addr.lp = cword.l; + break; + } +} + +/*----------------------------------------------------------------------- + */ +static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + cfiptr_t cptr; + cfiword_t cword; + int retval; + cptr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + retval = (cptr.cp[0] == cword.c); + break; + case FLASH_CFI_16BIT: + retval = (cptr.wp[0] == cword.w); + break; + case FLASH_CFI_32BIT: + retval = (cptr.lp[0] == cword.l); + break; + default: + retval = 0; + break; + } + return retval; +} +/*----------------------------------------------------------------------- + */ +static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd) +{ + cfiptr_t cptr; + cfiword_t cword; + int retval; + cptr.cp = flash_make_addr(info, sect, offset); + flash_make_cmd(info, cmd, &cword); + switch(info->portwidth) { + case FLASH_CFI_8BIT: + retval = ((cptr.cp[0] & cword.c) == cword.c); + break; + case FLASH_CFI_16BIT: + retval = ((cptr.wp[0] & cword.w) == cword.w); + break; + case FLASH_CFI_32BIT: + retval = ((cptr.lp[0] & cword.l) == cword.l); + break; + default: + retval = 0; + break; + } + return retval; +} + +/*----------------------------------------------------------------------- + * detect if flash is compatible with the Common Flash Interface (CFI) + * http://www.jedec.org/download/search/jesd68.pdf + * +*/ +static int flash_detect_cfi(flash_info_t * info) +{ + + for(info->portwidth=FLASH_CFI_8BIT; info->portwidth <= FLASH_CFI_32BIT; + info->portwidth <<= 1) { + for(info->chipwidth =FLASH_CFI_BY8; + info->chipwidth <= info->portwidth; + info->chipwidth <<= 1) { + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); + if(flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP,'Q') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && + flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) + return 1; + } + } + return 0; +} +/* + * The following code cannot be run from FLASH! + * + */ +static ulong flash_get_size (ulong base, int banknum) +{ + flash_info_t * info = &flash_info[banknum]; + int i, j; + int sect_cnt; + unsigned long sector; + unsigned long tmp; + int size_ratio; + uchar num_erase_regions; + int erase_region_size; + int erase_region_count; + + info->start[0] = base; + + if(flash_detect_cfi(info)){ + size_ratio = info->portwidth / info->chipwidth; + num_erase_regions = flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS); +#ifdef DEBUG_FLASH + printf("found %d erase regions\n", num_erase_regions); +#endif + sect_cnt = 0; + sector = base; + for(i = 0 ; i < num_erase_regions; i++) { + if(i > NUM_ERASE_REGIONS) { + printf("%d erase regions found, only %d used\n", + num_erase_regions, NUM_ERASE_REGIONS); + break; + } + tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS); + erase_region_size = (tmp & 0xffff)? ((tmp & 0xffff) * 256): 128; + tmp >>= 16; + erase_region_count = (tmp & 0xffff) +1; + for(j = 0; j< erase_region_count; j++) { + info->start[sect_cnt] = sector; + sector += (erase_region_size * size_ratio); + info->protect[sect_cnt] = flash_isset(info, sect_cnt, FLASH_OFFSET_PROTECT, FLASH_STATUS_PROTECT); + sect_cnt++; + } + } + + info->sector_count = sect_cnt; + /* multiply the size by the number of chips */ + info->size = (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) * size_ratio; + info->buffer_size = (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE)); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT); + info->erase_blk_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT))); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT); + info->buffer_write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT))); + tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT); + info->write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT)))/ 1000; + info->flash_id = FLASH_MAN_CFI; + } + + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + return(info->size); +} + + +/*----------------------------------------------------------------------- + */ +static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword) +{ + + cfiptr_t ctladdr; + cfiptr_t cptr; + int flag; + + ctladdr.cp = flash_make_addr(info, 0, 0); + cptr.cp = (uchar *)dest; + + + /* Check if Flash is (sufficiently) erased */ + switch(info->portwidth) { + case FLASH_CFI_8BIT: + flag = ((cptr.cp[0] & cword.c) == cword.c); + break; + case FLASH_CFI_16BIT: + flag = ((cptr.wp[0] & cword.w) == cword.w); + break; + case FLASH_CFI_32BIT: + flag = ((cptr.lp[0] & cword.l) == cword.l); + break; + default: + return 2; + } + if(!flag) + return 2; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE); + + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cptr.cp[0] = cword.c; + break; + case FLASH_CFI_16BIT: + cptr.wp[0] = cword.w; + break; + case FLASH_CFI_32BIT: + cptr.lp[0] = cword.l; + break; + } + + /* re-enable interrupts if necessary */ + if(flag) + enable_interrupts(); + + return flash_full_status_check(info, 0, info->write_tout, "write"); +} + +#ifdef CFG_FLASH_USE_BUFFER_WRITE + +/* loop through the sectors from the highest address + * when the passed address is greater or equal to the sector address + * we have a match + */ +static int find_sector(flash_info_t *info, ulong addr) +{ + int sector; + for(sector = info->sector_count - 1; sector >= 0; sector--) { + if(addr >= info->start[sector]) + break; + } + return sector; +} + +static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len) +{ + + int sector; + int cnt; + int retcode; + volatile cfiptr_t src; + volatile cfiptr_t dst; + + src.cp = cp; + dst.cp = (uchar *)dest; + sector = find_sector(info, dest); + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); + if((retcode = flash_status_check(info, sector, info->buffer_write_tout, + "write to buffer")) == ERR_OK) { + switch(info->portwidth) { + case FLASH_CFI_8BIT: + cnt = len; + break; + case FLASH_CFI_16BIT: + cnt = len >> 1; + break; + case FLASH_CFI_32BIT: + cnt = len >> 2; + break; + default: + return ERR_INVAL; + break; + } + flash_write_cmd(info, sector, 0, (uchar)cnt-1); + while(cnt-- > 0) { + switch(info->portwidth) { + case FLASH_CFI_8BIT: + *dst.cp++ = *src.cp++; + break; + case FLASH_CFI_16BIT: + *dst.wp++ = *src.wp++; + break; + case FLASH_CFI_32BIT: + *dst.lp++ = *src.lp++; + break; + default: + return ERR_INVAL; + break; + } + } + flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); + retcode = flash_full_status_check(info, sector, info->buffer_write_tout, + "buffer write"); + } + flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); + return retcode; +} +#endif /* CFG_USE_FLASH_BUFFER_WRITE */ diff --git a/board/rpxsuper/rpxsuper.c b/board/rpxsuper/rpxsuper.c new file mode 100644 index 0000000..2c0717e --- /dev/null +++ b/board/rpxsuper/rpxsuper.c @@ -0,0 +1,305 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2001 + * Advent Networks, Inc. <http://www.adventnetworks.com> + * Jay Monkman <jtm@smoothsmoothie.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 + */ + +#include <common.h> +#include <ioports.h> +#include <mpc8260.h> +#include "rpxsuper.h" + +/* + * I/O Port configuration table + * + * if conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 *ATMTXEN */ + /* PA30 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTCA */ + /* PA29 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTSOC */ + /* PA28 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 *ATMRXEN */ + /* PA27 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRSOC */ + /* PA26 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRCA */ + /* PA25 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[0] */ + /* PA24 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[1] */ + /* PA23 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[2] */ + /* PA22 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[3] */ + /* PA21 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[4] */ + /* PA20 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[5] */ + /* PA19 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[6] */ + /* PA18 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXD[7] */ + /* PA17 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[7] */ + /* PA16 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[6] */ + /* PA15 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[5] */ + /* PA14 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[4] */ + /* PA13 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[3] */ + /* PA12 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[2] */ + /* PA11 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[1] */ + /* PA10 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXD[0] */ + /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */ + /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */ + /* PA7 */ { 1, 0, 0, 0, 0, 0 }, /* PA7 */ + /* PA6 */ { 1, 0, 0, 0, 0, 0 }, /* PA6 */ + /* PA5 */ { 1, 0, 0, 0, 0, 0 }, /* PA5 */ + /* PA4 */ { 1, 0, 0, 0, 0, 0 }, /* PA4 */ + /* PA3 */ { 1, 0, 0, 0, 0, 0 }, /* PA3 */ + /* PA2 */ { 1, 0, 0, 0, 0, 0 }, /* PA2 */ + /* PA1 */ { 1, 0, 0, 0, 0, 0 }, /* PA1 */ + /* PA0 */ { 1, 0, 0, 0, 0, 0 } /* PA0 */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */ + /* PB17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_DV */ + /* PB16 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_ER */ + /* PB15 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TX_ER */ + /* PB14 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TX_EN */ + /* PB13 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII COL */ + /* PB12 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII CRS */ + /* PB11 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD[3] */ + /* PB10 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD[2] */ + /* PB9 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD[1] */ + /* PB8 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD[0] */ + /* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */ + /* PB6 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD[1] */ + /* PB5 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD[2] */ + /* PB4 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD[3] */ + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 1, 0, 0, 1, 0, 0 }, /* PC31 */ + /* PC30 */ { 1, 0, 0, 1, 0, 0 }, /* PC30 */ + /* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */ + /* PC28 */ { 1, 0, 0, 1, 0, 0 }, /* PC28 */ + /* PC27 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD[0] */ + /* PC26 */ { 1, 0, 0, 1, 0, 0 }, /* PC26 */ + /* PC25 */ { 1, 0, 0, 1, 0, 0 }, /* PC25 */ + /* PC24 */ { 1, 0, 0, 1, 0, 0 }, /* PC24 */ + /* PC23 */ { 1, 1, 0, 1, 0, 0 }, /* ATMTFCLK */ + /* PC22 */ { 1, 1, 0, 0, 0, 0 }, /* ATMRFCLK */ + /* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */ + /* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */ + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */ + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */ + /* PC17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_CLK */ + /* PC16 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII TX_CLK */ + /* PC15 */ { 1, 0, 0, 0, 0, 0 }, /* PC15 */ + /* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */ + /* PC13 */ { 1, 0, 0, 1, 0, 0 }, /* PC13 */ + /* PC12 */ { 1, 0, 0, 1, 0, 0 }, /* PC12 */ + /* PC11 */ { 1, 0, 0, 1, 0, 0 }, /* PC11 */ + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDC */ + /* PC9 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDIO */ + /* PC8 */ { 1, 0, 0, 1, 0, 0 }, /* PC8 */ + /* PC7 */ { 1, 0, 0, 1, 0, 0 }, /* PC7 */ + /* PC6 */ { 1, 0, 0, 1, 0, 0 }, /* PC6 */ + /* PC5 */ { 1, 0, 0, 1, 0, 0 }, /* PC5 */ + /* PC4 */ { 1, 0, 0, 1, 0, 0 }, /* PC4 */ + /* PC3 */ { 1, 0, 0, 1, 0, 0 }, /* PC3 */ + /* PC2 */ { 1, 0, 0, 1, 0, 1 }, /* ENET FDE */ + /* PC1 */ { 1, 0, 0, 1, 0, 0 }, /* ENET DSQE */ + /* PC0 */ { 1, 0, 0, 1, 0, 0 }, /* ENET LBK */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 1, 0, 0, 0, 0, 0 }, /* SCC1 EN RxD */ + /* PD30 */ { 1, 0, 0, 0, 0, 0 }, /* SCC1 EN TxD */ + /* PD29 */ { 1, 0, 0, 0, 0, 0 }, /* SCC1 EN TENA */ + /* PD28 */ { 1, 0, 0, 0, 0, 0 }, /* PD28 */ + /* PD27 */ { 1, 0, 0, 0, 0, 0 }, /* PD27 */ + /* PD26 */ { 1, 0, 0, 0, 0, 0 }, /* PD26 */ + /* PD25 */ { 1, 0, 0, 0, 0, 0 }, /* PD25 */ + /* PD24 */ { 1, 0, 0, 0, 0, 0 }, /* PD24 */ + /* PD23 */ { 1, 0, 0, 0, 0, 0 }, /* PD23 */ + /* PD22 */ { 1, 0, 0, 0, 0, 0 }, /* PD22 */ + /* PD21 */ { 1, 0, 0, 0, 0, 0 }, /* PD21 */ + /* PD20 */ { 1, 0, 0, 0, 0, 0 }, /* PD20 */ + /* PD19 */ { 1, 0, 0, 0, 0, 0 }, /* PD19 */ + /* PD18 */ { 1, 0, 0, 0, 0, 0 }, /* PD19 */ + /* PD17 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */ + /* PD16 */ { 1, 0, 0, 0, 0, 0 }, /* FCC1 ATMTXPRTY */ + /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */ + /* PD13 */ { 1, 0, 0, 0, 0, 0 }, /* PD13 */ + /* PD12 */ { 1, 0, 0, 0, 0, 0 }, /* PD12 */ + /* PD11 */ { 1, 0, 0, 0, 0, 0 }, /* PD11 */ + /* PD10 */ { 1, 0, 0, 0, 0, 0 }, /* PD10 */ + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */ + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */ + /* PD7 */ { 1, 0, 0, 0, 0, 0 }, /* PD7 */ + /* PD6 */ { 1, 0, 0, 0, 0, 0 }, /* PD6 */ + /* PD5 */ { 1, 0, 0, 0, 0, 0 }, /* PD5 */ + /* PD4 */ { 1, 0, 0, 0, 0, 0 }, /* PD4 */ + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +/* ------------------------------------------------------------------------- */ + +/* + * Setup CS4 to enable the Board Control/Status registers. + * Otherwise the smcs won't work. +*/ +int board_pre_init (void) +{ + volatile t_rpx_regs *regs = (t_rpx_regs*)CFG_REGS_BASE; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + memctl->memc_br4 = CFG_BR4_PRELIM; + memctl->memc_or4 = CFG_OR4_PRELIM; + regs->bcsr1 = 0x70; /* to enable terminal no SMC1 */ + regs->bcsr2 = 0x20; /* mut be written to enable writing FLASH */ + return 0; +} + +void +reset_phy(void) +{ + volatile t_rpx_regs *regs = (t_rpx_regs*)CFG_REGS_BASE; + regs->bcsr4 = 0xC3; +} + +/* + * Check Board Identity: + */ + +int checkboard(void) +{ + volatile t_rpx_regs *regs = (t_rpx_regs*)CFG_REGS_BASE; + printf ("Board: Embedded Planet RPX Super, Revision %d\n", + regs->bcsr0 >> 4); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + volatile uchar c = 0, *ramaddr; + ulong psdmr, lsdmr, bcr; + long size = 0; + int i; + + psdmr = CFG_PSDMR; + lsdmr = CFG_LSDMR; + + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + size = CFG_SDRAM0_SIZE; + bcr = immap->im_siu_conf.sc_bcr; + immap->im_siu_conf.sc_bcr = (bcr & ~BCR_EBM); + + memctl->memc_mptpr = CFG_MPTPR; + + ramaddr = (uchar *)(CFG_SDRAM0_BASE); + memctl->memc_psrt = CFG_PSRT; + + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; + + immap->im_siu_conf.sc_bcr = bcr; + +#ifndef CFG_RAMBOOT +/* size += CFG_SDRAM1_SIZE; */ + ramaddr = (uchar *)(CFG_SDRAM1_BASE); + memctl->memc_lsrt = CFG_LSRT; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *ramaddr = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_lsdmr = lsdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; +#endif + + /* return total ram size */ + return (size * 1024 * 1024); +} diff --git a/board/rsdproto/config.mk b/board/rsdproto/config.mk new file mode 100644 index 0000000..5844ec1 --- /dev/null +++ b/board/rsdproto/config.mk @@ -0,0 +1,33 @@ +# +# (C) Copyright 2000 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# (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 +# + +# +# MBX8xx boards +# + +TEXT_BASE = 0xff000000 +/*TEXT_BASE = 0x00200000 */ diff --git a/board/rsdproto/rsdproto.c b/board/rsdproto/rsdproto.c new file mode 100644 index 0000000..bf4fd53 --- /dev/null +++ b/board/rsdproto/rsdproto.c @@ -0,0 +1,378 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@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 <ioports.h> +#include <mpc8260.h> +#include <i2c.h> + +/* define to initialise the SDRAM on the local bus */ +#undef INIT_LOCAL_BUS_SDRAM + +/* I2C Bus adresses for PPC & Protocol board */ +#define PPC8260_I2C_ADR 0x30 /*(0)011.0000 */ +#define LM84_PPC_I2C_ADR 0x2A /*(0)010.1010 */ +#define LM84_SHARC_I2C_ADR 0x29 /*(0)010.1001 */ +#define VIRTEX_I2C_ADR 0x25 /*(0)010.0101 */ +#define X24645_PPC_I2C_ADR 0x00 /*(0)00X.XXXX -> be careful ! No other i2c-chip should have an adress beginning with (0)00 !!! */ +#define RS5C372_PPC_I2C_ADR 0x32 /*(0)011.0010 -> this adress is programmed by the manufacturer and cannot be changed !!! */ + +/* + * I/O Port configuration table + * + * if conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 0, 0, 0, 0, 0, 0 }, + /* PA30 */ { 0, 0, 0, 0, 0, 0 }, + /* PA29 */ { 0, 0, 0, 0, 0, 0 }, + /* PA28 */ { 0, 0, 0, 0, 0, 0 }, + /* PA27 */ { 0, 0, 0, 0, 0, 0 }, + /* PA26 */ { 0, 0, 0, 0, 0, 0 }, + /* PA25 */ { 0, 0, 0, 0, 0, 0 }, + /* PA24 */ { 0, 0, 0, 0, 0, 0 }, + /* PA23 */ { 0, 0, 0, 0, 0, 0 }, + /* PA22 */ { 0, 0, 0, 0, 0, 0 }, + /* PA21 */ { 0, 0, 0, 0, 0, 0 }, + /* PA20 */ { 0, 0, 0, 0, 0, 0 }, + /* PA19 */ { 0, 0, 0, 0, 0, 0 }, + /* PA18 */ { 0, 0, 0, 0, 0, 0 }, + /* PA17 */ { 0, 0, 0, 0, 0, 0 }, + /* PA16 */ { 0, 0, 0, 0, 0, 0 }, + /* PA15 */ { 0, 0, 0, 0, 0, 0 }, + /* PA14 */ { 0, 0, 0, 0, 0, 0 }, + /* PA13 */ { 0, 0, 0, 0, 0, 0 }, + /* PA12 */ { 0, 0, 0, 0, 0, 0 }, + /* PA11 */ { 0, 0, 0, 0, 0, 0 }, + /* PA10 */ { 0, 0, 0, 0, 0, 0 }, + /* PA9 */ { 0, 0, 0, 0, 0, 0 }, + /* PA8 */ { 0, 0, 0, 0, 0, 0 }, + /* PA7 */ { 0, 0, 0, 0, 0, 0 }, + /* PA6 */ { 0, 0, 0, 0, 0, 0 }, + /* PA5 */ { 0, 0, 0, 0, 0, 0 }, + /* PA4 */ { 0, 0, 0, 0, 0, 0 }, + /* PA3 */ { 0, 0, 0, 0, 0, 0 }, + /* PA2 */ { 0, 0, 0, 0, 0, 0 }, + /* PA1 */ { 0, 0, 0, 0, 0, 0 }, + /* PA0 */ { 0, 0, 0, 0, 0, 0 } + }, + + + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */ + /* PB17 */ { 0, 0, 0, 0, 0, 0 }, + /* PB16 */ { 0, 0, 0, 0, 0, 0 }, + /* PB15 */ { 0, 0, 0, 0, 0, 0 }, + /* PB14 */ { 0, 0, 0, 0, 0, 0 }, + /* PB13 */ { 0, 0, 0, 0, 0, 0 }, + /* PB12 */ { 0, 0, 0, 0, 0, 0 }, + /* PB11 */ { 0, 0, 0, 0, 0, 0 }, + /* PB10 */ { 0, 0, 0, 0, 0, 0 }, + /* PB9 */ { 0, 0, 0, 0, 0, 0 }, + /* PB8 */ { 0, 0, 0, 0, 0, 0 }, + /* PB7 */ { 0, 0, 0, 0, 0, 0 }, + /* PB6 */ { 0, 0, 0, 0, 0, 0 }, + /* PB5 */ { 0, 0, 0, 0, 0, 0 }, + /* PB4 */ { 0, 0, 0, 0, 0, 0 }, + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 0, 0, 0, 0, 0, 0 }, + /* PC30 */ { 0, 0, 0, 0, 0, 0 }, + /* PC29 */ { 0, 0, 0, 0, 0, 0 }, + /* PC28 */ { 0, 0, 0, 0, 0, 0 }, + /* PC27 */ { 0, 0, 0, 0, 0, 0 }, + /* PC26 */ { 0, 0, 0, 0, 0, 0 }, + /* PC25 */ { 0, 0, 0, 0, 0, 0 }, + /* PC24 */ { 0, 0, 0, 0, 0, 0 }, + /* PC23 */ { 0, 0, 0, 0, 0, 0 }, + /* PC22 */ { 0, 0, 0, 0, 0, 0 }, + /* PC21 */ { 0, 0, 0, 0, 0, 0 }, + /* PC20 */ { 0, 0, 0, 0, 0, 0 }, + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* ETHRXCLK: CLK14 */ + /* PC17 */ { 0, 0, 0, 0, 0, 0 }, /* ETHTXCLK: CLK15 */ + /* PC16 */ { 0, 0, 0, 0, 0, 0 }, + /* PC15 */ { 0, 0, 0, 0, 0, 0 }, + /* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 UART CD/ */ + /* PC13 */ { 0, 0, 0, 0, 0, 0 }, + /* PC12 */ { 0, 0, 0, 0, 0, 0 }, + /* PC11 */ { 0, 0, 0, 0, 0, 0 }, + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* ETHMDC: GP */ + /* PC9 */ { 1, 0, 0, 1, 0, 0 }, /* ETHMDIO: GP */ + /* PC8 */ { 0, 0, 0, 0, 0, 0 }, + /* PC7 */ { 0, 0, 0, 0, 0, 0 }, + /* PC6 */ { 0, 0, 0, 0, 0, 0 }, + /* PC5 */ { 0, 0, 0, 0, 0, 0 }, + /* PC4 */ { 0, 0, 0, 0, 0, 0 }, + /* PC3 */ { 0, 0, 0, 0, 0, 0 }, + /* PC2 */ { 0, 0, 0, 0, 0, 0 }, + /* PC1 */ { 0, 0, 0, 0, 0, 0 }, + /* PC0 */ { 0, 0, 0, 0, 0, 0 } + }, + + + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 UART RxD */ + /* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 UART TxD */ + /* PD29 */ { 0, 0, 0, 0, 0, 0 }, + /* PD28 */ { 0, 0, 0, 0, 0, 0 }, + /* PD27 */ { 0, 0, 0, 0, 0, 0 }, + /* PD26 */ { 0, 0, 0, 0, 0, 0 }, + /* PD25 */ { 0, 0, 0, 0, 0, 0 }, + /* PD24 */ { 0, 0, 0, 0, 0, 0 }, + /* PD23 */ { 0, 0, 0, 0, 0, 0 }, + /* PD22 */ { 0, 0, 0, 0, 0, 0 }, + /* PD21 */ { 0, 0, 0, 0, 0, 0 }, + /* PD20 */ { 0, 0, 0, 0, 0, 0 }, + /* PD19 */ { 0, 0, 0, 0, 0, 0 }, + /* PD18 */ { 0, 0, 0, 0, 0, 0 }, + /* PD17 */ { 0, 0, 0, 0, 0, 0 }, + /* PD16 */ { 0, 0, 0, 0, 0, 0 }, + /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */ + /* PD13 */ { 0, 0, 0, 0, 0, 0 }, + /* PD12 */ { 0, 0, 0, 0, 0, 0 }, + /* PD11 */ { 0, 0, 0, 0, 0, 0 }, + /* PD10 */ { 0, 0, 0, 0, 0, 0 }, + /* PD9 */ { 0, 0, 0, 0, 0, 0 }, + /* PD8 */ { 0, 0, 0, 0, 0, 0 }, + /* PD7 */ { 0, 0, 0, 0, 0, 0 }, + /* PD6 */ { 0, 0, 0, 0, 0, 0 }, + /* PD5 */ { 0, 0, 0, 0, 0, 0 }, + /* PD4 */ { 0, 0, 0, 0, 0, 0 }, + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +/* ------------------------------------------------------------------------- */ + +struct tm { + unsigned int tm_sec; + unsigned int tm_min; + unsigned int tm_hour; + unsigned int tm_wday; + unsigned int tm_mday; + unsigned int tm_mon; + unsigned int tm_year; +}; + +void read_RS5C372_time (struct tm *timedate) +{ + unsigned char buffer[8]; + +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) + + if (i2c_read (RS5C372_PPC_I2C_ADR, 0, 1, buffer, sizeof (buffer))) { + timedate->tm_sec = BCD_TO_BIN (buffer[0]); + timedate->tm_min = BCD_TO_BIN (buffer[1]); + timedate->tm_hour = BCD_TO_BIN (buffer[2]); + timedate->tm_wday = BCD_TO_BIN (buffer[3]); + timedate->tm_mday = BCD_TO_BIN (buffer[4]); + timedate->tm_mon = BCD_TO_BIN (buffer[5]); + timedate->tm_year = BCD_TO_BIN (buffer[6]) + 2000; + } else { + /*printf("i2c error %02x\n", rc); */ + memset (timedate, 0, sizeof (struct tm)); + } +} + +/* ------------------------------------------------------------------------- */ + +int read_LM84_temp (int address) +{ + unsigned char buffer[8]; + /*int rc;*/ + + if (i2c_read (address, 0, 1, buffer, 1)) { + return (int) buffer[0]; + } else { + /*printf("i2c error %02x\n", rc); */ + return -42; + } +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + struct tm timedate; + unsigned int ppctemp, prottemp; + + puts ("Board: Rohde & Schwarz 8260 Protocol Board\n"); + + /* initialise i2c */ + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + + read_RS5C372_time (&timedate); + printf (" Time: %02d:%02d:%02d\n", + timedate.tm_hour, timedate.tm_min, timedate.tm_sec); + printf (" Date: %02d-%02d-%04d\n", + timedate.tm_mday, timedate.tm_mon, timedate.tm_year); + ppctemp = read_LM84_temp (LM84_PPC_I2C_ADR); + prottemp = read_LM84_temp (LM84_SHARC_I2C_ADR); + printf (" Temp: PPC %d C, Protocol Board %d C\n", + ppctemp, prottemp); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Miscelaneous platform dependent initialisations while still + * running in flash + */ + +int misc_init_f (void) +{ + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + +#ifdef INIT_LOCAL_BUS_SDRAM + volatile uchar *ramaddr8; +#endif + volatile ulong *ramaddr32; + ulong sdmr; + int i; + + /* + * Only initialize SDRAM when running from FLASH. + * When running from RAM, don't touch it. + */ + if ((ulong) initdram & 0xff000000) { + immap->im_siu_conf.sc_ppc_acr = 0x02; + immap->im_siu_conf.sc_ppc_alrh = 0x01267893; + immap->im_siu_conf.sc_ppc_alrl = 0x89ABCDEF; + immap->im_siu_conf.sc_lcl_acr = 0x02; + immap->im_siu_conf.sc_lcl_alrh = 0x01234567; + immap->im_siu_conf.sc_lcl_alrl = 0x89ABCDEF; + /* + * Program local/60x bus Transfer Error Status and Control Regs: + * Disable parity errors + */ + immap->im_siu_conf.sc_tescr1 = 0x00040000; + immap->im_siu_conf.sc_ltescr1 = 0x00040000; + + /* + * Perform Power-Up Initialisation of SDRAM (see 8260 UM, 10.4.2) + * + * The appropriate BRx/ORx registers have already + * been set when we get here (see cpu_init_f). The + * SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + memctl->memc_mptpr = 0x2000; + memctl->memc_mar = 0x0200; +#ifdef INIT_LOCAL_BUS_SDRAM + /* initialise local bus ram + * + * (using the PSRMR_ definitions is NOT an error here + * - the LSDMR has the same fields as the PSDMR!) + */ + memctl->memc_lsrt = 0x0b; + memctl->memc_lurt = 0x00; + ramaddr = (uchar *) PHYS_SDRAM_LOCAL; + sdmr = CFG_LSDMR & ~(PSDMR_OP_MSK | PSDMR_RFEN | PSDMR_PBI); + memctl->memc_lsdmr = sdmr | PSDMR_OP_PREA; + *ramaddr = 0xff; + for (i = 0; i < 8; i++) { + memctl->memc_lsdmr = sdmr | PSDMR_OP_CBRR; + *ramaddr = 0xff; + } + memctl->memc_lsdmr = sdmr | PSDMR_OP_MRW; + *ramaddr = 0xff; + memctl->memc_lsdmr = CFG_LSDMR | PSDMR_OP_NORM; +#endif + /* initialise 60x bus ram */ + memctl->memc_psrt = 0x0b; + memctl->memc_purt = 0x08; + ramaddr32 = (ulong *) PHYS_SDRAM_60X; + sdmr = CFG_PSDMR & ~(PSDMR_OP_MSK | PSDMR_RFEN | PSDMR_PBI); + memctl->memc_psdmr = sdmr | PSDMR_OP_PREA; + ramaddr32[0] = 0x00ff00ff; + ramaddr32[1] = 0x00ff00ff; + memctl->memc_psdmr = sdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) { + ramaddr32[0] = 0x00ff00ff; + ramaddr32[1] = 0x00ff00ff; + } + memctl->memc_psdmr = sdmr | PSDMR_OP_MRW; + ramaddr32[0] = 0x00ff00ff; + ramaddr32[1] = 0x00ff00ff; + memctl->memc_psdmr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN; + } + + /* return the size of the 60x bus ram */ + return PHYS_SDRAM_60X_SIZE; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Miscelaneous platform dependent initialisations after monitor + * has been relocated into ram + */ + +int misc_init_r (void) +{ + printf ("misc_init_r\n"); + return (0); +} diff --git a/board/sacsng/sacsng.c b/board/sacsng/sacsng.c new file mode 100644 index 0000000..0f0f0e6 --- /dev/null +++ b/board/sacsng/sacsng.c @@ -0,0 +1,801 @@ +/* + * (C) Copyright 2002 + * Custom IDEAS, Inc. <www.cideas.com> + * Gerald Van Baren <vanbaren@cideas.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 + */ + +#include <asm/u-boot.h> +#include <common.h> +#include <ioports.h> +#include <mpc8260.h> +/*NO// #include <memtest.h> */ +#include <i2c.h> +#include <spi.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +#include <status_led.h> +#endif + +#include "clkinit.h" +#include "ioconfig.h" /* I/O configuration table */ + +/* + * PBI Page Based Interleaving + * PSDMR_PBI page based interleaving + * 0 bank based interleaving + * External Address Multiplexing (EAMUX) adds a clock to address cycles + * (this can help with marginal board layouts) + * PSDMR_EAMUX adds a clock + * 0 no extra clock + * Buffer Command (BUFCMD) adds a clock to command cycles. + * PSDMR_BUFCMD adds a clock + * 0 no extra clock + */ +#define CONFIG_PBI PSDMR_PBI +#define PESSIMISTIC_SDRAM 0 +#define EAMUX 0 /* EST requires EAMUX */ +#define BUFCMD 0 + +/* + * ADC/DAC Defines: + */ +#define INITIAL_SAMPLE_RATE 10016 /* Initial Daq sample rate */ +#define INITIAL_RIGHT_JUST 0 /* Initial DAC right justification */ +#define INITIAL_MCLK_DIVIDE 0 /* Initial MCLK Divide */ +#define INITIAL_SAMPLE_64X 1 /* Initial 64x clocking mode */ +#define INITIAL_SAMPLE_128X 0 /* Initial 128x clocking mode */ + +/* + * ADC Defines: + */ +#define I2C_ADC_1_ADDR 0x0E /* I2C Address of the ADC #1 */ +#define I2C_ADC_2_ADDR 0x0F /* I2C Address of the ADC #2 */ + +#define ADC_SDATA1_MASK 0x00020000 /* PA14 - CH12SDATA_PU */ +#define ADC_SDATA2_MASK 0x00010000 /* PA15 - CH34SDATA_PU */ + +#define ADC_VREF_CAP 100 /* VREF capacitor in uF */ +#define ADC_INITIAL_DELAY (10 * ADC_VREF_CAP) /* 10 usec per uF, in usec */ +#define ADC_SDATA_DELAY 100 /* ADC SDATA release delay in usec */ +#define ADC_CAL_DELAY (1000000 / INITIAL_SAMPLE_RATE * 4500) + /* Wait at least 4100 LRCLK's */ + +#define ADC_REG1_FRAME_START 0x80 /* Frame start */ +#define ADC_REG1_GROUND_CAL 0x40 /* Ground calibration enable */ +#define ADC_REG1_ANA_MOD_PDOWN 0x20 /* Analog modulator section in power down */ +#define ADC_REG1_DIG_MOD_PDOWN 0x10 /* Digital modulator section in power down */ + +#define ADC_REG2_128x 0x80 /* Oversample at 128x */ +#define ADC_REG2_CAL 0x40 /* System calibration enable */ +#define ADC_REG2_CHANGE_SIGN 0x20 /* Change sign enable */ +#define ADC_REG2_LR_DISABLE 0x10 /* Left/Right output disable */ +#define ADC_REG2_HIGH_PASS_DIS 0x08 /* High pass filter disable */ +#define ADC_REG2_SLAVE_MODE 0x04 /* Slave mode */ +#define ADC_REG2_DFS 0x02 /* Digital format select */ +#define ADC_REG2_MUTE 0x01 /* Mute */ + +#define ADC_REG7_ADDR_ENABLE 0x80 /* Address enable */ +#define ADC_REG7_PEAK_ENABLE 0x40 /* Peak enable */ +#define ADC_REG7_PEAK_UPDATE 0x20 /* Peak update */ +#define ADC_REG7_PEAK_FORMAT 0x10 /* Peak display format */ +#define ADC_REG7_DIG_FILT_PDOWN 0x04 /* Digital filter power down enable */ +#define ADC_REG7_FIR2_IN_EN 0x02 /* External FIR2 input enable */ +#define ADC_REG7_PSYCHO_EN 0x01 /* External pyscho filter input enable */ + +/* + * DAC Defines: + */ + +#define I2C_DAC_ADDR 0x11 /* I2C Address of the DAC */ + +#define DAC_RST_MASK 0x00008000 /* PA16 - DAC_RST* */ +#define DAC_RESET_DELAY 100 /* DAC reset delay in usec */ +#define DAC_INITIAL_DELAY 5000 /* DAC initialization delay in usec */ + +#define DAC_REG1_AMUTE 0x80 /* Auto-mute */ + +#define DAC_REG1_LEFT_JUST_24_BIT (0 << 4) /* Fmt 0: Left justified 24 bit */ +#define DAC_REG1_I2S_24_BIT (1 << 4) /* Fmt 1: I2S up to 24 bit */ +#define DAC_REG1_RIGHT_JUST_16BIT (2 << 4) /* Fmt 2: Right justified 16 bit */ +#define DAC_REG1_RIGHT_JUST_24BIT (3 << 4) /* Fmt 3: Right justified 24 bit */ +#define DAC_REG1_RIGHT_JUST_20BIT (4 << 4) /* Fmt 4: Right justified 20 bit */ +#define DAC_REG1_RIGHT_JUST_18BIT (5 << 4) /* Fmt 5: Right justified 18 bit */ + +#define DAC_REG1_DEM_NO (0 << 2) /* No De-emphasis */ +#define DAC_REG1_DEM_44KHZ (1 << 2) /* 44.1KHz De-emphasis */ +#define DAC_REG1_DEM_48KHZ (2 << 2) /* 48KHz De-emphasis */ +#define DAC_REG1_DEM_32KHZ (3 << 2) /* 32KHz De-emphasis */ + +#define DAC_REG1_SINGLE 0 /* 4- 50KHz sample rate */ +#define DAC_REG1_DOUBLE 1 /* 50-100KHz sample rate */ +#define DAC_REG1_QUAD 2 /* 100-200KHz sample rate */ +#define DAC_REG1_DSD 3 /* Direct Stream Data, DSD */ + +#define DAC_REG5_INVERT_A 0x80 /* Invert channel A */ +#define DAC_REG5_INVERT_B 0x40 /* Invert channel B */ +#define DAC_REG5_I2C_MODE 0x20 /* Control port (I2C) mode */ +#define DAC_REG5_POWER_DOWN 0x10 /* Power down mode */ +#define DAC_REG5_MUTEC_A_B 0x08 /* Mutec A=B */ +#define DAC_REG5_FREEZE 0x04 /* Freeze */ +#define DAC_REG5_MCLK_DIV 0x02 /* MCLK divide by 2 */ +#define DAC_REG5_RESERVED 0x01 /* Reserved */ + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard(void) +{ + printf ("SACSng\n"); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + volatile uchar c = 0; + volatile uchar *ramaddr = (uchar *)(CFG_SDRAM_BASE + 0x8); + uint psdmr = CFG_PSDMR; + int i; + uint psrt = 14; /* for no SPD */ + uint chipselects = 1; /* for no SPD */ + uint sdram_size = CFG_SDRAM0_SIZE * 1024 * 1024; /* for no SPD */ + uint or = CFG_OR2_PRELIM; /* for no SPD */ +#ifdef SDRAM_SPD_ADDR + uint data_width; + uint rows; + uint banks; + uint cols; + uint caslatency; + uint width; + uint rowst; + uint sdam; + uint bsma; + uint sda10; + u_char spd_size; + u_char data; + u_char cksum; + int j; +#endif + +#ifdef SDRAM_SPD_ADDR + /* Keep the compiler from complaining about potentially uninitialized vars */ + data_width = chipselects = rows = banks = cols = caslatency = psrt = 0; + + /* + * Read the SDRAM SPD EEPROM via I2C. + */ + i2c_read(SDRAM_SPD_ADDR, 0, 1, &data, 1); + spd_size = data; + cksum = data; + for(j = 1; j < 64; j++) { /* read only the checksummed bytes */ + /* note: the I2C address autoincrements when alen == 0 */ + i2c_read(SDRAM_SPD_ADDR, 0, 0, &data, 1); + if(j == 5) chipselects = data & 0x0F; + else if(j == 6) data_width = data; + else if(j == 7) data_width |= data << 8; + else if(j == 3) rows = data & 0x0F; + else if(j == 4) cols = data & 0x0F; + else if(j == 12) { + /* + * Refresh rate: this assumes the prescaler is set to + * approximately 1uSec per tick. + */ + switch(data & 0x7F) { + default: + case 0: psrt = 14 ; /* 15.625uS */ break; + case 1: psrt = 2; /* 3.9uS */ break; + case 2: psrt = 6; /* 7.8uS */ break; + case 3: psrt = 29; /* 31.3uS */ break; + case 4: psrt = 60; /* 62.5uS */ break; + case 5: psrt = 120; /* 125uS */ break; + } + } + else if(j == 17) banks = data; + else if(j == 18) { + caslatency = 3; /* default CL */ +#if(PESSIMISTIC_SDRAM) + if((data & 0x04) != 0) caslatency = 3; + else if((data & 0x02) != 0) caslatency = 2; + else if((data & 0x01) != 0) caslatency = 1; +#else + if((data & 0x01) != 0) caslatency = 1; + else if((data & 0x02) != 0) caslatency = 2; + else if((data & 0x04) != 0) caslatency = 3; +#endif + else { + printf ("WARNING: Unknown CAS latency 0x%02X, using 3\n", + data); + } + } + else if(j == 63) { + if(data != cksum) { + printf ("WARNING: Configuration data checksum failure:" + " is 0x%02x, calculated 0x%02x\n", + data, cksum); + } + } + cksum += data; + } + + /* We don't trust CL less than 2 (only saw it on an old 16MByte DIMM) */ + if(caslatency < 2) { + printf("CL was %d, forcing to 2\n", caslatency); + caslatency = 2; + } + if(rows > 14) { + printf("This doesn't look good, rows = %d, should be <= 14\n", rows); + rows = 14; + } + if(cols > 11) { + printf("This doesn't look good, columns = %d, should be <= 11\n", cols); + cols = 11; + } + + if((data_width != 64) && (data_width != 72)) + { + printf("WARNING: SDRAM width unsupported, is %d, expected 64 or 72.\n", + data_width); + } + width = 3; /* 2^3 = 8 bytes = 64 bits wide */ + /* + * Convert banks into log2(banks) + */ + if (banks == 2) banks = 1; + else if(banks == 4) banks = 2; + else if(banks == 8) banks = 3; + + sdram_size = 1 << (rows + cols + banks + width); + +#if(CONFIG_PBI == 0) /* bank-based interleaving */ + rowst = ((32 - 6) - (rows + cols + width)) * 2; +#else + rowst = 32 - (rows + banks + cols + width); +#endif + + or = ~(sdram_size - 1) | /* SDAM address mask */ + ((banks-1) << 13) | /* banks per device */ + (rowst << 9) | /* rowst */ + ((rows - 9) << 6); /* numr */ + + memctl->memc_or2 = or; + + /* + * SDAM specifies the number of columns that are multiplexed + * (reference AN2165/D), defined to be (columns - 6) for page + * interleave, (columns - 8) for bank interleave. + * + * BSMA is 14 - max(rows, cols). The bank select lines come + * into play above the highest "address" line going into the + * the SDRAM. + */ +#if(CONFIG_PBI == 0) /* bank-based interleaving */ + sdam = cols - 8; + bsma = ((31 - width) - 14) - ((rows > cols) ? rows : cols); + sda10 = sdam + 2; +#else + sdam = cols - 6; + bsma = ((31 - width) - 14) - ((rows > cols) ? rows : cols); + sda10 = sdam; +#endif +#if(PESSIMISTIC_SDRAM) + psdmr = (CONFIG_PBI |\ + PSDMR_RFEN |\ + PSDMR_RFRC_16_CLK |\ + PSDMR_PRETOACT_8W |\ + PSDMR_ACTTORW_8W |\ + PSDMR_WRC_4C |\ + PSDMR_EAMUX |\ + PSDMR_BUFCMD) |\ + caslatency |\ + ((caslatency - 1) << 6) | /* LDOTOPRE is CL - 1 */ \ + (sdam << 24) |\ + (bsma << 21) |\ + (sda10 << 18); +#else + psdmr = (CONFIG_PBI |\ + PSDMR_RFEN |\ + PSDMR_RFRC_7_CLK |\ + PSDMR_PRETOACT_3W | /* 1 for 7E parts (fast PC-133) */ \ + PSDMR_ACTTORW_2W | /* 1 for 7E parts (fast PC-133) */ \ + PSDMR_WRC_1C | /* 1 clock + 7nSec */ + EAMUX |\ + BUFCMD) |\ + caslatency |\ + ((caslatency - 1) << 6) | /* LDOTOPRE is CL - 1 */ \ + (sdam << 24) |\ + (bsma << 21) |\ + (sda10 << 18); +#endif +#endif + + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * Quote from Micron MT48LC8M16A2 data sheet: + * + * "...the SDRAM requires a 100uS delay prior to issuing any + * command other than a COMMAND INHIBIT or NOP. Starting at some + * point during this 100uS period and continuing at least through + * the end of this period, COMMAND INHIBIT or NOP commands should + * be applied." + * + * "Once the 100uS delay has been satisfied with at least one COMMAND + * INHIBIT or NOP command having been applied, a /PRECHARGE command/ + * should be applied. All banks must then be precharged, thereby + * placing the device in the all banks idle state." + * + * "Once in the idle state, /two/ AUTO REFRESH cycles must be + * performed. After the AUTO REFRESH cycles are complete, the + * SDRAM is ready for mode register programming." + * + * (/emphasis/ mine, gvb) + * + * The way I interpret this, Micron start up sequence is: + * 1. Issue a PRECHARGE-BANK command (initial precharge) + * 2. Issue a PRECHARGE-ALL-BANKS command ("all banks ... precharged") + * 3. Issue two (presumably, doing eight is OK) CBR REFRESH commands + * 4. Issue a MODE-SET command to initialize the mode register + * + * -------- + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + memctl->memc_mptpr = CFG_MPTPR; + memctl->memc_psrt = psrt; + + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; + + /* + * Do it a second time for the second set of chips if the DIMM has + * two chip selects (double sided). + */ + if(chipselects > 1) { + ramaddr += sdram_size; + + memctl->memc_br3 = CFG_BR3_PRELIM + sdram_size; + memctl->memc_or3 = or; + + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; + } + + /* return total ram size */ + return (sdram_size * chipselects); +} + +/*----------------------------------------------------------------------- + * Board Control Functions + */ +void board_poweroff (void) +{ + while (1); /* hang forever */ +} + + +#ifdef CONFIG_MISC_INIT_R +/* ------------------------------------------------------------------------- */ +int misc_init_r(void) +{ + /* + * Note: iop is used by the I2C macros, and iopa by the ADC/DAC initialization. + */ + volatile ioport_t *iopa = ioport_addr((immap_t *)CFG_IMMR, 0 /* port A */); + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); + + int reg; /* I2C register value */ + char *ep; /* Environment pointer */ + char str_buf[12] ; /* sprintf output buffer */ + int sample_rate; /* ADC/DAC sample rate */ + int sample_64x; /* Use 64/4 clocking for the ADC/DAC */ + int sample_128x; /* Use 128/4 clocking for the ADC/DAC */ + int right_just; /* Is the data to the DAC right justified? */ + int mclk_divide; /* MCLK Divide */ + + /* + * SACSng custom initialization: + * Start the ADC and DAC clocks, since the Crystal parts do not + * work on the I2C bus until the clocks are running. + */ + + sample_rate = INITIAL_SAMPLE_RATE; + if ((ep = getenv("DaqSampleRate")) != NULL) { + sample_rate = simple_strtol(ep, NULL, 10); + } + + sample_64x = INITIAL_SAMPLE_64X; + sample_128x = INITIAL_SAMPLE_128X; + if ((ep = getenv("Daq64xSampling")) != NULL) { + sample_64x = simple_strtol(ep, NULL, 10); + if (sample_64x) { + sample_128x = 0; + } + else { + sample_128x = 1; + } + } + else { + if ((ep = getenv("Daq128xSampling")) != NULL) { + sample_128x = simple_strtol(ep, NULL, 10); + if (sample_128x) { + sample_64x = 0; + } + else { + sample_64x = 1; + } + } + } + + Daq_Init_Clocks(sample_rate, sample_64x); + sample_rate = Daq_Get_SampleRate(); + Daq_Start_Clocks(sample_rate); + + sprintf(str_buf, "%d", sample_rate); + setenv("DaqSampleRate", str_buf); + + if (sample_64x) { + setenv("Daq64xSampling", "1"); + setenv("Daq128xSampling", NULL); + } + else { + setenv("Daq64xSampling", NULL); + setenv("Daq128xSampling", "1"); + } + + /* Display the ADC/DAC clocking information */ + Daq_Display_Clocks(); + + /* + * Determine the DAC data justification + */ + + right_just = INITIAL_RIGHT_JUST; + if ((ep = getenv("DaqDACRightJustified")) != NULL) { + right_just = simple_strtol(ep, NULL, 10); + } + + sprintf(str_buf, "%d", right_just); + setenv("DaqDACRightJustified", str_buf); + + /* + * Determine the DAC MCLK Divide + */ + + mclk_divide = INITIAL_MCLK_DIVIDE; + if ((ep = getenv("DaqDACMClockDivide")) != NULL) { + mclk_divide = simple_strtol(ep, NULL, 10); + } + + sprintf(str_buf, "%d", mclk_divide); + setenv("DaqDACMClockDivide", str_buf); + + /* + * Initializing the I2C address in the Crystal A/Ds: + * + * 1) Wait for VREF cap to settle (10uSec per uF) + * 2) Release pullup on SDATA + * 3) Write the I2C address to register 6 + * 4) Enable address matching by setting the MSB in register 7 + */ + + printf("Initializing the ADC...\n"); + udelay(ADC_INITIAL_DELAY); /* 10uSec per uF of VREF cap */ + + iopa->pdat &= ~ADC_SDATA1_MASK; /* release SDATA1 */ + udelay(ADC_SDATA_DELAY); /* arbitrary settling time */ + + i2c_reg_write(0x00, 0x06, I2C_ADC_1_ADDR); /* set address */ + i2c_reg_write(I2C_ADC_1_ADDR, 0x07, /* turn on ADDREN */ + ADC_REG7_ADDR_ENABLE); + + i2c_reg_write(I2C_ADC_1_ADDR, 0x02, /* 128x, slave mode, !HPEN */ + (sample_64x ? 0 : ADC_REG2_128x) | + ADC_REG2_HIGH_PASS_DIS | + ADC_REG2_SLAVE_MODE); + + reg = i2c_reg_read(I2C_ADC_1_ADDR, 0x06) & 0x7F; + if(reg != I2C_ADC_1_ADDR) + printf("Init of ADC U10 failed: address is 0x%02X should be 0x%02X\n", + reg, I2C_ADC_1_ADDR); + + iopa->pdat &= ~ADC_SDATA2_MASK; /* release SDATA2 */ + udelay(ADC_SDATA_DELAY); /* arbitrary settling time */ + + i2c_reg_write(0x00, 0x06, I2C_ADC_2_ADDR); /* set address (do not set ADDREN yet) */ + + i2c_reg_write(I2C_ADC_2_ADDR, 0x02, /* 64x, slave mode, !HPEN */ + (sample_64x ? 0 : ADC_REG2_128x) | + ADC_REG2_HIGH_PASS_DIS | + ADC_REG2_SLAVE_MODE); + + reg = i2c_reg_read(I2C_ADC_2_ADDR, 0x06) & 0x7F; + if(reg != I2C_ADC_2_ADDR) + printf("Init of ADC U15 failed: address is 0x%02X should be 0x%02X\n", + reg, I2C_ADC_2_ADDR); + + i2c_reg_write(I2C_ADC_1_ADDR, 0x01, /* set FSTART and GNDCAL */ + ADC_REG1_FRAME_START | + ADC_REG1_GROUND_CAL); + + i2c_reg_write(I2C_ADC_1_ADDR, 0x02, /* Start calibration */ + (sample_64x ? 0 : ADC_REG2_128x) | + ADC_REG2_CAL | + ADC_REG2_HIGH_PASS_DIS | + ADC_REG2_SLAVE_MODE); + + udelay(ADC_CAL_DELAY); /* a minimum of 4100 LRCLKs */ + i2c_reg_write(I2C_ADC_1_ADDR, 0x01, 0x00); /* remove GNDCAL */ + + /* + * Now that we have synchronized the ADC's, enable address + * selection on the second ADC as well as the first. + */ + i2c_reg_write(I2C_ADC_2_ADDR, 0x07, ADC_REG7_ADDR_ENABLE); + + /* + * Initialize the Crystal DAC + * + * Two of the config lines are used for I2C so we have to set them + * to the proper initialization state without inadvertantly + * sending an I2C "start" sequence. When we bring the I2C back to + * the normal state, we send an I2C "stop" sequence. + */ + printf("Initializing the DAC...\n"); + + /* + * Bring the I2C clock and data lines low for initialization + */ + I2C_SCL(0); + I2C_DELAY; + I2C_SDA(0); + I2C_ACTIVE; + I2C_DELAY; + + /* Reset the DAC */ + iopa->pdat &= ~DAC_RST_MASK; + udelay(DAC_RESET_DELAY); + + /* Release the DAC reset */ + iopa->pdat |= DAC_RST_MASK; + udelay(DAC_INITIAL_DELAY); + + /* + * Cause the DAC to: + * Enable control port (I2C mode) + * Going into power down + */ + i2c_reg_write(I2C_DAC_ADDR, 0x05, + DAC_REG5_I2C_MODE | + DAC_REG5_POWER_DOWN); + + /* + * Cause the DAC to: + * Enable control port (I2C mode) + * Going into power down + * . MCLK divide by 1 + * . MCLK divide by 2 + */ + i2c_reg_write(I2C_DAC_ADDR, 0x05, + DAC_REG5_I2C_MODE | + DAC_REG5_POWER_DOWN | + (mclk_divide ? DAC_REG5_MCLK_DIV : 0)); + + /* + * Cause the DAC to: + * Auto-mute disabled + * . Format 0, left justified 24 bits + * . Format 3, right justified 24 bits + * No de-emphasis + * . Single speed mode + * . Double speed mode + */ + i2c_reg_write(I2C_DAC_ADDR, 0x01, + (right_just ? DAC_REG1_RIGHT_JUST_24BIT : + DAC_REG1_LEFT_JUST_24_BIT) | + DAC_REG1_DEM_NO | + (sample_rate >= 50000 ? DAC_REG1_DOUBLE : DAC_REG1_SINGLE)); + + sprintf(str_buf, "%d", + sample_rate >= 50000 ? DAC_REG1_DOUBLE : DAC_REG1_SINGLE); + setenv("DaqDACFunctionalMode", str_buf); + + /* + * Cause the DAC to: + * Enable control port (I2C mode) + * Remove power down + * . MCLK divide by 1 + * . MCLK divide by 2 + */ + i2c_reg_write(I2C_DAC_ADDR, 0x05, + DAC_REG5_I2C_MODE | + (mclk_divide ? DAC_REG5_MCLK_DIV : 0)); + + /* + * Create a I2C stop condition: + * low->high on data while clock is high. + */ + I2C_SCL(1); + I2C_DELAY; + I2C_SDA(1); + I2C_DELAY; + I2C_TRISTATE; + + printf("\n"); + +#ifdef CONFIG_SHOW_BOOT_PROGRESS + /* + * Turn off the RED fail LED now that we are up and running. + */ + status_led_set(STATUS_LED_RED, STATUS_LED_OFF); +#endif + + return 0; +} + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +/* + * Show boot status: flash the LED if something goes wrong, indicating + * that last thing that worked and thus, by implication, what is broken. + * + * This stores the last OK value in RAM so this will not work properly + * before RAM is initialized. Since it is being used for indicating + * boot status (i.e. after RAM is initialized), that is OK. + */ +static void flash_code(uchar number, uchar modulo, uchar digits) +{ + int j; + + /* + * Recursively do upper digits. + */ + if(digits > 1) { + flash_code(number / modulo, modulo, digits - 1); + } + + number = number % modulo; + + /* + * Zero is indicated by one long flash (dash). + */ + if(number == 0) { + status_led_set(STATUS_LED_BOOT, STATUS_LED_ON); + udelay(1000000); + status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF); + udelay(200000); + } else { + /* + * Non-zero is indicated by short flashes, one per count. + */ + for(j = 0; j < number; j++) { + status_led_set(STATUS_LED_BOOT, STATUS_LED_ON); + udelay(100000); + status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF); + udelay(200000); + } + } + /* + * Inter-digit pause: we've already waited 200 mSec, wait 1 sec total + */ + udelay(700000); +} + +static int last_boot_progress; + +void show_boot_progress (int status) +{ + if(status != -1) { + last_boot_progress = status; + } else { + /* + * Houston, we have a problem. Blink the last OK status which + * indicates where things failed. + */ + status_led_set(STATUS_LED_RED, STATUS_LED_ON); + flash_code(last_boot_progress, 5, 3); + udelay(1000000); + status_led_set(STATUS_LED_RED, STATUS_LED_BLINKING); + } +} +#endif /* CONFIG_SHOW_BOOT_PROGRESS */ + + +/* + * The following are used to control the SPI chip selects for the SPI command. + */ +#if (CONFIG_COMMANDS & CFG_CMD_SPI) + +#define SPI_ADC_CS_MASK 0x00000800 +#define SPI_DAC_CS_MASK 0x00001000 + +void spi_adc_chipsel(int cs) +{ + volatile ioport_t *iopd = ioport_addr((immap_t *)CFG_IMMR, 3 /* port D */); + + if(cs) + iopd->pdat &= ~SPI_ADC_CS_MASK; /* activate the chip select */ + else + iopd->pdat |= SPI_ADC_CS_MASK; /* deactivate the chip select */ +} + +void spi_dac_chipsel(int cs) +{ + volatile ioport_t *iopd = ioport_addr((immap_t *)CFG_IMMR, 3 /* port D */); + + if(cs) + iopd->pdat &= ~SPI_DAC_CS_MASK; /* activate the chip select */ + else + iopd->pdat |= SPI_DAC_CS_MASK; /* deactivate the chip select */ +} + +/* + * The SPI command uses this table of functions for controlling the SPI + * chip selects: it calls the appropriate function to control the SPI + * chip selects. + */ +spi_chipsel_type spi_chipsel[2] = { + spi_adc_chipsel, + spi_dac_chipsel +}; +#endif /* CFG_CMD_SPI */ + +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/sandpoint/flash.c b/board/sandpoint/flash.c new file mode 100644 index 0000000..572199d --- /dev/null +++ b/board/sandpoint/flash.c @@ -0,0 +1,766 @@ +/* + * (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 <common.h> +#include <mpc824x.h> +#include <asm/processor.h> +#include <asm/pci_io.h> +#include <w83c553f.h> + +#define ROM_CS0_START 0xFF800000 +#define ROM_CS1_START 0xFF000000 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +#if defined(CFG_ENV_IS_IN_FLASH) +# ifndef CFG_ENV_ADDR +# define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +# endif +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif +# ifndef CFG_ENV_SECT_SIZE +# define CFG_ENV_SECT_SIZE CFG_ENV_SIZE +# endif +#endif + +/*----------------------------------------------------------------------- + * Functions + */ +static int write_word (flash_info_t *info, ulong dest, ulong data); +#if 0 +static void flash_get_offsets (ulong base, flash_info_t *info); +#endif /* 0 */ + +/*flash command address offsets*/ + +#if 0 +#define ADDR0 (0x555) +#define ADDR1 (0x2AA) +#define ADDR3 (0x001) +#else +#define ADDR0 (0xAAA) +#define ADDR1 (0x555) +#define ADDR3 (0x001) +#endif + +#define FLASH_WORD_SIZE unsigned char + +/*----------------------------------------------------------------------- + */ + +#if 0 +static int byte_parity_odd(unsigned char x) __attribute__ ((const)); +#endif /* 0 */ +static unsigned long flash_id(unsigned char mfct, unsigned char chip) __attribute__ ((const)); + +typedef struct +{ + FLASH_WORD_SIZE extval; + unsigned short intval; +} map_entry; + +#if 0 +static int +byte_parity_odd(unsigned char x) +{ + x ^= x >> 4; + x ^= x >> 2; + x ^= x >> 1; + return (x & 0x1) != 0; +} +#endif /* 0 */ + + + +static unsigned long +flash_id(unsigned char mfct, unsigned char chip) +{ + static const map_entry mfct_map[] = + { + {(FLASH_WORD_SIZE) AMD_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_AMD >> 16)}, + {(FLASH_WORD_SIZE) FUJ_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_FUJ >> 16)}, + {(FLASH_WORD_SIZE) STM_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_STM >> 16)}, + {(FLASH_WORD_SIZE) MT_MANUFACT, (unsigned short) ((unsigned long) FLASH_MAN_MT >> 16)}, + {(FLASH_WORD_SIZE) INTEL_MANUFACT,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)}, + {(FLASH_WORD_SIZE) INTEL_ALT_MANU,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)} + }; + + static const map_entry chip_map[] = + { + {AMD_ID_F040B, FLASH_AM040}, + {(FLASH_WORD_SIZE) STM_ID_x800AB, FLASH_STM800AB} + }; + + const map_entry *p; + unsigned long result = FLASH_UNKNOWN; + + /* find chip id */ + for(p = &chip_map[0]; p < &chip_map[sizeof chip_map / sizeof chip_map[0]]; p++) + if(p->extval == chip) + { + result = FLASH_VENDMASK | p->intval; + break; + } + + /* find vendor id */ + for(p = &mfct_map[0]; p < &mfct_map[sizeof mfct_map / sizeof mfct_map[0]]; p++) + if(p->extval == mfct) + { + result &= ~FLASH_VENDMASK; + result |= (unsigned long) p->intval << 16; + break; + } + + return result; +} + + + +unsigned long +flash_init(void) +{ + unsigned long i; + unsigned char j; + static const ulong flash_banks[] = CFG_FLASH_BANKS; + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) + { + flash_info_t * const pflinfo = &flash_info[i]; + pflinfo->flash_id = FLASH_UNKNOWN; + pflinfo->size = 0; + pflinfo->sector_count = 0; + } + + /* Enable writes to Sandpoint flash */ + { + register unsigned char temp; + CONFIG_READ_BYTE(CFG_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp); + temp &= ~0x20; /* clear BIOSWP bit */ + CONFIG_WRITE_BYTE(CFG_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp); + } + + for(i = 0; i < sizeof flash_banks / sizeof flash_banks[0]; i++) + { + flash_info_t * const pflinfo = &flash_info[i]; + const unsigned long base_address = flash_banks[i]; + volatile FLASH_WORD_SIZE * const flash = (FLASH_WORD_SIZE *) base_address; +#if 0 + volatile FLASH_WORD_SIZE * addr2; +#endif +#if 0 + /* write autoselect sequence */ + flash[0x5555] = 0xaa; + flash[0x2aaa] = 0x55; + flash[0x5555] = 0x90; +#else + flash[0xAAA << (3 * i)] = 0xaa; + flash[0x555 << (3 * i)] = 0x55; + flash[0xAAA << (3 * i)] = 0x90; +#endif + __asm__ __volatile__("sync"); + +#if 0 + pflinfo->flash_id = flash_id(flash[0x0], flash[0x1]); +#else + pflinfo->flash_id = flash_id(flash[0x0], flash[0x2 + 14 * i]); +#endif + + switch(pflinfo->flash_id & FLASH_TYPEMASK) + { + case FLASH_AM040: + pflinfo->size = 0x00080000; + pflinfo->sector_count = 8; + for(j = 0; j < 8; j++) + { + pflinfo->start[j] = base_address + 0x00010000 * j; + pflinfo->protect[j] = flash[(j << 16) | 0x2]; + } + break; + case FLASH_STM800AB: + pflinfo->size = 0x00100000; + pflinfo->sector_count = 19; + pflinfo->start[0] = base_address; + pflinfo->start[1] = base_address + 0x4000; + pflinfo->start[2] = base_address + 0x6000; + pflinfo->start[3] = base_address + 0x8000; + for(j = 1; j < 16; j++) + { + pflinfo->start[j+3] = base_address + 0x00010000 * j; + } +#if 0 + /* check for protected sectors */ + for (j = 0; j < pflinfo->sector_count; j++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile FLASH_WORD_SIZE *)(pflinfo->start[j]); + if (pflinfo->flash_id & FLASH_MAN_SST) + pflinfo->protect[j] = 0; + else + pflinfo->protect[j] = addr2[2] & 1; + } +#endif + break; + } + /* Protect monitor and environment sectors + */ +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_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]); +#endif + + /* reset device to read mode */ + flash[0x0000] = 0xf0; + __asm__ __volatile__("sync"); + } + + return flash_info[0].size + flash_info[1].size; +} + +#if 0 +static void +flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if (info->flash_id & FLASH_MAN_SST) + { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + +} +#endif /* 0 */ + +/*----------------------------------------------------------------------- + */ +void +flash_print_info(flash_info_t *info) +{ + 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; + } + + 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; + } + } + + 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:"); + + 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; + + 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" : " " + ); + } + + puts("\n"); + return; +} + +#if 0 + +/* + * The following code cannot be run from FLASH! + */ +ulong +flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + printf("flash_get_size: \n"); + /* Write auto select command: read Manufacturer ID */ + eieio(); + addr2[ADDR0] = (FLASH_WORD_SIZE)0xAA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x55; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x90; + value = addr2[0]; + + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + printf("recognised manufacturer"); + + value = addr2[ADDR3]; /* device ID */ + debug ("\ndev_code=%x\n", value); + + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + printf("flash id %lx; sector count %x, size %lx\n", info->flash_id,info->sector_count,info->size); + /* set up sector start address table */ + if (info->flash_id & FLASH_MAN_SST) + { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + + /* 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 */ + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if (info->flash_id & FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + + return (info->size); +} + +#endif + + +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; + + 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; + } + + 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; + + /* 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(); + + 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)); + 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 */ + 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 = (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 */ + + 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; 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; + } + + /* + * 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 FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0]; + volatile FLASH_WORD_SIZE *dest2; + 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; + + 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(); + + 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]; + + /* 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); + } + } + } + + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/sbc8260/flash.c b/board/sbc8260/flash.c new file mode 100644 index 0000000..ab2bf35 --- /dev/null +++ b/board/sbc8260/flash.c @@ -0,0 +1,392 @@ +/* + * (C) Copyright 2000 + * Marius Groeger <mgroeger@sysgo.de> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Flash Routines for AMD 29F080B devices + * + *-------------------------------------------------------------------- + * 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 <mpc8xx.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +/*----------------------------------------------------------------------- + * 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); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* for now, only support the 4 MB Flash SIMM */ + size = flash_get_size((vu_long *)CFG_FLASH0_BASE, &flash_info[0]); + + /* + * protect monitor and environment sectors + */ + +#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + +#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR) +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); +#endif + + return /*size*/ (CFG_FLASH0_SIZE * 1024 * 1024); +} + +/*----------------------------------------------------------------------- + */ +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 >> 16) & 0xff) { + case 0x1: + printf ("AMD "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case AMD_ID_F040B: + printf ("AM29F040B (4 Mbit)\n"); + break; + case AMD_ID_F080B: + printf ("AM29F080B (8 Mbit)\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; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + vu_long vendor, devid; + ulong base = (ulong)addr; + +/* printf("addr = %08lx\n", (unsigned long)addr); */ + + /* Reset and Write auto select command: read Manufacturer ID */ + addr[0] = 0xf0f0f0f0; + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x90909090; + udelay (1000); + + vendor = addr[0]; +/* printf("vendor = %08lx\n", vendor); */ + if (vendor != 0x01010101) { + info->size = 0; + goto out; + } + + devid = addr[1]; +/* printf("devid = %08lx\n", devid); */ + + if ((devid & 0xff) == AMD_ID_F080B) { + info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F080B; + /* we have 16 sectors with 64KB each x 4 */ + info->sector_count = 16; + info->size = 4 * info->sector_count * 64*1024; + } + else { + info->size = 0; + goto out; + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* sector base address */ + info->start[i] = base + i * (info->size / info->sector_count); + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[2] & 1; + } + + /* reset command */ + addr = (vu_long *)info->start[0]; + +out: + addr[0] = 0xf0f0f0f0; + + 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; + } + + 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[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x80808080; + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + udelay (100); + + /* 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 */ + serial_putc ('.'); + last = now; + } + } + + DONE: + /* reset to read mode */ + addr = (volatile unsigned 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; 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; + } + + /* + * 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[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 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/sbc8260/sbc8260.c b/board/sbc8260/sbc8260.c new file mode 100644 index 0000000..48aefa0 --- /dev/null +++ b/board/sbc8260/sbc8260.c @@ -0,0 +1,289 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2001 + * Advent Networks, Inc. <http://www.adventnetworks.com> + * Jay Monkman <jtm@smoothsmoothie.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 + */ + +#include <common.h> +#include <ioports.h> +#include <mpc8260.h> + +/* + * I/O Port configuration table + * + * if conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 *ATMTXEN */ + /* PA30 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTCA */ + /* PA29 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTSOC */ + /* PA28 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 *ATMRXEN */ + /* PA27 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRSOC */ + /* PA26 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRCA */ + /* PA25 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[0] */ + /* PA24 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[1] */ + /* PA23 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[2] */ + /* PA22 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[3] */ + /* PA21 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[4] */ + /* PA20 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[5] */ + /* PA19 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[6] */ + /* PA18 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[7] */ + /* PA17 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[7] */ + /* PA16 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[6] */ + /* PA15 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[5] */ + /* PA14 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[4] */ + /* PA13 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[3] */ + /* PA12 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[2] */ + /* PA11 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[1] */ + /* PA10 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[0] */ + /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */ + /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */ + /* PA7 */ { 1, 0, 0, 1, 0, 0 }, /* PA7 */ + /* PA6 */ { 1, 0, 0, 1, 0, 0 }, /* PA6 */ + /* PA5 */ { 1, 0, 0, 1, 0, 0 }, /* PA5 */ + /* PA4 */ { 1, 0, 0, 1, 0, 0 }, /* PA4 */ + /* PA3 */ { 1, 0, 0, 1, 0, 0 }, /* PA3 */ + /* PA2 */ { 1, 0, 0, 1, 0, 0 }, /* PA2 */ + /* PA1 */ { 1, 0, 0, 1, 0, 0 }, /* PA1 */ + /* PA0 */ { 1, 0, 0, 1, 0, 0 } /* PA0 */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */ + /* PB17 */ { 1, 0, 0, 1, 0, 0 }, /* PB17 */ + /* PB16 */ { 1, 0, 0, 1, 0, 0 }, /* PB16 */ + /* PB15 */ { 1, 0, 0, 1, 0, 0 }, /* PB15 */ + /* PB14 */ { 1, 0, 0, 1, 0, 0 }, /* PB14 */ + /* PB13 */ { 1, 0, 0, 1, 0, 0 }, /* PB13 */ + /* PB12 */ { 1, 0, 0, 1, 0, 0 }, /* PB12 */ + /* PB11 */ { 1, 0, 0, 1, 0, 0 }, /* PB11 */ + /* PB10 */ { 1, 0, 0, 1, 0, 0 }, /* PB10 */ + /* PB9 */ { 1, 0, 0, 1, 0, 0 }, /* PB9 */ + /* PB8 */ { 1, 0, 0, 1, 0, 0 }, /* PB8 */ + /* PB7 */ { 1, 0, 0, 1, 0, 0 }, /* PB7 */ + /* PB6 */ { 1, 0, 0, 1, 0, 0 }, /* PB6 */ + /* PB5 */ { 1, 0, 0, 1, 0, 0 }, /* PB5 */ + /* PB4 */ { 1, 0, 0, 1, 0, 0 }, /* PB4 */ + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 1, 0, 0, 1, 0, 0 }, /* PC31 */ + /* PC30 */ { 1, 0, 0, 1, 0, 0 }, /* PC30 */ + /* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */ + /* PC28 */ { 1, 0, 0, 1, 0, 0 }, /* PC28 */ + /* PC27 */ { 1, 0, 0, 1, 0, 0 }, /* PC27 */ + /* PC26 */ { 1, 0, 0, 1, 0, 0 }, /* PC26 */ + /* PC25 */ { 1, 0, 0, 1, 0, 0 }, /* PC25 */ + /* PC24 */ { 1, 0, 0, 1, 0, 0 }, /* PC24 */ + /* PC23 */ { 1, 1, 0, 1, 0, 0 }, /* ATMTFCLK */ + /* PC22 */ { 1, 1, 0, 0, 0, 0 }, /* ATMRFCLK */ + /* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */ + /* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */ + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */ + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */ + /* PC17 */ { 1, 0, 0, 1, 0, 0 }, /* PC17 */ + /* PC16 */ { 1, 0, 0, 1, 0, 0 }, /* PC16 */ + /* PC15 */ { 1, 0, 0, 1, 0, 0 }, /* PC15 */ + /* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */ + /* PC13 */ { 1, 0, 0, 1, 0, 0 }, /* PC13 */ + /* PC12 */ { 1, 0, 0, 1, 0, 0 }, /* PC12 */ + /* PC11 */ { 1, 0, 0, 1, 0, 0 }, /* PC11 */ + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDC */ + /* PC9 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MDIO */ + /* PC8 */ { 1, 0, 0, 1, 0, 0 }, /* PC8 */ + /* PC7 */ { 1, 0, 0, 1, 0, 0 }, /* PC7 */ + /* PC6 */ { 1, 0, 0, 1, 0, 0 }, /* PC6 */ + /* PC5 */ { 1, 0, 0, 1, 0, 0 }, /* PC5 */ + /* PC4 */ { 1, 0, 0, 1, 0, 0 }, /* PC4 */ + /* PC3 */ { 1, 0, 0, 1, 0, 0 }, /* PC3 */ + /* PC2 */ { 1, 0, 0, 1, 0, 1 }, /* ENET FDE */ + /* PC1 */ { 1, 0, 0, 1, 0, 0 }, /* ENET DSQE */ + /* PC0 */ { 1, 0, 0, 1, 0, 0 }, /* ENET LBK */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RxD */ + /* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 EN TxD */ + /* PD29 */ { 1, 1, 0, 1, 0, 0 }, /* SCC1 EN TENA */ + /* PD28 */ { 1, 0, 0, 1, 0, 0 }, /* PD28 */ + /* PD27 */ { 1, 0, 0, 1, 0, 0 }, /* PD27 */ + /* PD26 */ { 1, 0, 0, 1, 0, 0 }, /* PD26 */ + /* PD25 */ { 1, 0, 0, 1, 0, 0 }, /* PD25 */ + /* PD24 */ { 1, 0, 0, 1, 0, 0 }, /* PD24 */ + /* PD23 */ { 1, 0, 0, 1, 0, 0 }, /* PD23 */ + /* PD22 */ { 1, 0, 0, 1, 0, 0 }, /* PD22 */ + /* PD21 */ { 1, 0, 0, 1, 0, 0 }, /* PD21 */ + /* PD20 */ { 1, 0, 0, 1, 0, 0 }, /* PD20 */ + /* PD19 */ { 1, 0, 0, 1, 0, 0 }, /* PD19 */ + /* PD18 */ { 1, 0, 0, 1, 0, 0 }, /* PD18 */ + /* PD17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */ + /* PD16 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */ +#if defined(CONFIG_SOFT_I2C) + /* PD15 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SDA */ + /* PD14 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SCL */ +#else +#if defined(CONFIG_HARD_I2C) + /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */ +#else /* normal I/O port pins */ + /* PD15 */ { 1, 0, 0, 1, 0, 0 }, /* I2C SDA */ + /* PD14 */ { 1, 0, 0, 1, 0, 0 }, /* I2C SCL */ +#endif +#endif + /* PD13 */ { 1, 0, 0, 0, 0, 0 }, /* PD13 */ + /* PD12 */ { 1, 0, 0, 0, 0, 0 }, /* PD12 */ + /* PD11 */ { 1, 0, 0, 0, 0, 0 }, /* PD11 */ + /* PD10 */ { 1, 0, 0, 0, 0, 0 }, /* PD10 */ + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */ + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */ + /* PD7 */ { 1, 0, 0, 1, 0, 1 }, /* PD7 */ + /* PD6 */ { 1, 0, 0, 1, 0, 1 }, /* PD6 */ + /* PD5 */ { 1, 0, 0, 1, 0, 1 }, /* PD5 */ + /* PD4 */ { 1, 0, 0, 1, 0, 1 }, /* PD4 */ + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: EST SBC8260\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + volatile uchar c = 0, *ramaddr = (uchar *) (CFG_SDRAM_BASE + 0x8); + ulong psdmr = CFG_PSDMR; + int i; + + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + memctl->memc_psrt = CFG_PSRT; + memctl->memc_mptpr = CFG_MPTPR; + + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++) + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; + + /* return total ram size */ + return (CFG_SDRAM0_SIZE * 1024 * 1024); +} + +#ifdef CONFIG_MISC_INIT_R +/* ------------------------------------------------------------------------- */ +int misc_init_r (void) +{ +#ifdef CFG_LED_BASE + uchar ds = *(unsigned char *) (CFG_LED_BASE + 1); + uchar ss; + uchar tmp[64]; + int res; + + if ((ds != 0) && (ds != 0xff)) { + res = getenv_r ("ethaddr", tmp, sizeof (tmp)); + if (res > 0) { + ss = ((ds >> 4) & 0x0f); + ss += ss < 0x0a ? '0' : ('a' - 10); + tmp[15] = ss; + + ss = (ds & 0x0f); + ss += ss < 0x0a ? '0' : ('a' - 10); + tmp[16] = ss; + + tmp[17] = '\0'; + setenv ("ethaddr", tmp); + /* set the led to show the address */ + *((unsigned char *) (CFG_LED_BASE + 1)) = ds; + } + } +#endif /* CFG_LED_BASE */ + return (0); +} +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/shannon/config.mk b/board/shannon/config.mk new file mode 100644 index 0000000..736d3af --- /dev/null +++ b/board/shannon/config.mk @@ -0,0 +1,23 @@ +# +# LART board with SA1100 cpu +# +# see http://www.lart.tudelft.nl/ for more information on LART +# + +# +# Tuxscreen has 4 banks of 4 MB DRAM each +# +# c000'0000 +# c800'0000 +# d000'0000 +# d800'0000 +# +# Linux-Kernel is expected to be at c000'8000, entry c000'8000 +# +# we load ourself to d830'0000, the upper 1 MB of the last (4th) bank +# +# download areas is c800'0000 +# + + +TEXT_BASE = 0xd8300000 diff --git a/board/shannon/memsetup.S b/board/shannon/memsetup.S new file mode 100644 index 0000000..4f0c464 --- /dev/null +++ b/board/shannon/memsetup.S @@ -0,0 +1,94 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +MEM_BASE: .long 0xa0000000 +MEM_START: .long 0xc0000000 + +#define MDCNFG 0x00 +#define MDCAS0 0x04 +#define MDCAS1 0x08 +#define MDCAS2 0x0c +#define MSC0 0x10 +#define MSC1 0x14 +#define MECR 0x18 + +mdcas0: .long 0xc71c703f @ cccccccf +mdcas1: .long 0xffc71c71 @ fffffffc +mdcas2: .long 0xffffffff @ ffffffff +mdcnfg: .long 0x0334b21f @ 9326991f +msc0: .long 0xfff84458 @ 42304230 +msc1: .long 0xffffffff @ 20182018 +mecr: .long 0x7fff7fff @ 01000000 + +/* setting up the memory */ + +.globl memsetup +memsetup: + ldr r0, MEM_BASE + + /* Setup the flash memory */ + ldr r1, msc0 + str r1, [r0, #MSC0] + + /* Set up the DRAM */ + + /* MDCAS0 */ + ldr r1, mdcas0 + str r1, [r0, #MDCAS0] + + /* MDCAS1 */ + ldr r1, mdcas1 + str r1, [r0, #MDCAS1] + + /* MDCAS2 */ + ldr r1, mdcas2 + str r1, [r0, #MDCAS2] + + /* MDCNFG */ + ldr r1, mdcnfg + str r1, [r0, #MDCNFG] + + /* Set up PCMCIA space */ + ldr r1, mecr + str r1, [r0, #MECR] + + /* Load something to activate bank */ + ldr r1, MEM_START + +.rept 8 + ldr r0, [r1] +.endr + + /* everything is fine now */ + mov pc, lr + diff --git a/board/siemens/IAD210/config.mk b/board/siemens/IAD210/config.mk new file mode 100644 index 0000000..c30abcb --- /dev/null +++ b/board/siemens/IAD210/config.mk @@ -0,0 +1,33 @@ +# +# (C) Copyright 2000 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# iad210 boards +# + +TEXT_BASE = 0x08000000 +/*TEXT_BASE = 0x00200000 */ diff --git a/board/smdk2400/config.mk b/board/smdk2400/config.mk new file mode 100644 index 0000000..18c412a --- /dev/null +++ b/board/smdk2400/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# +# SAMSUNG board with S3C2400X (ARM920T) CPU +# +# see http://www.samsung.com/ for more information on SAMSUNG +# + +# +# SAMSUNG has 1 bank of 32 MB DRAM +# +# 0C00'0000 to 0E00'0000 +# +# Linux-Kernel is expected to be at 0cf0'0000, entry 0cf0'0000 +# optionally with a ramdisk at 0c80'0000 +# +# we load ourself to 0CF00000 (must be high enough not to be +# overwritten by the uncompessing Linux kernel) +# +# download area is 0C80'0000 +# + + +TEXT_BASE = 0x0CF00000 diff --git a/board/smdk2400/memsetup.S b/board/smdk2400/memsetup.S new file mode 100644 index 0000000..b53e996 --- /dev/null +++ b/board/smdk2400/memsetup.S @@ -0,0 +1,165 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the Samsung development board by + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +/* + * + * Taken from linux/arch/arm/boot/compressed/head-s3c2400.S + * + * Copyright (C) 2001 Samsung Electronics by chc, 010406 + * + * S3C2400 specific tweaks. + * + */ + +/* memory controller */ +#define BWSCON 0x14000000 +#define BANKCON3 0x14000010 /* for cs8900, ethernet */ + +/* Bank0 */ +#define B0_Tacs 0x0 /* 0 clk */ +#define B0_Tcos 0x0 /* 0 clk */ +#define B0_Tacc 0x7 /* 14 clk */ +#define B0_Tcoh 0x0 /* 0 clk */ +#define B0_Tah 0x0 /* 0 clk */ +#define B0_Tacp 0x0 +#define B0_PMC 0x0 /* normal */ + +/* Bank1 */ +#define B1_Tacs 0x0 /* 0 clk */ +#define B1_Tcos 0x0 /* 0 clk */ +#define B1_Tacc 0x7 /* 14 clk */ +#define B1_Tcoh 0x0 /* 0 clk */ +#define B1_Tah 0x0 /* 0 clk */ +#define B1_Tacp 0x0 +#define B1_PMC 0x0 /* normal */ + +/* Bank2 */ +#define B2_Tacs 0x0 /* 0 clk */ +#define B2_Tcos 0x0 /* 0 clk */ +#define B2_Tacc 0x7 /* 14 clk */ +#define B2_Tcoh 0x0 /* 0 clk */ +#define B2_Tah 0x0 /* 0 clk */ +#define B2_Tacp 0x0 +#define B2_PMC 0x0 /* normal */ + +/* Bank3 - setup for the cs8900 */ +#define B3_Tacs 0x0 /* 0 clk */ +#define B3_Tcos 0x3 /* 4 clk */ +#define B3_Tacc 0x7 /* 14 clk */ +#define B3_Tcoh 0x1 /* 1 clk */ +#define B3_Tah 0x0 /* 0 clk */ +#define B3_Tacp 0x3 /* 6 clk */ +#define B3_PMC 0x0 /* normal */ + +/* Bank4 */ +#define B4_Tacs 0x0 /* 0 clk */ +#define B4_Tcos 0x0 /* 0 clk */ +#define B4_Tacc 0x7 /* 14 clk */ +#define B4_Tcoh 0x0 /* 0 clk */ +#define B4_Tah 0x0 /* 0 clk */ +#define B4_Tacp 0x0 +#define B4_PMC 0x0 /* normal */ + +/* Bank5 */ +#define B5_Tacs 0x0 /* 0 clk */ +#define B5_Tcos 0x0 /* 0 clk */ +#define B5_Tacc 0x7 /* 14 clk */ +#define B5_Tcoh 0x0 /* 0 clk */ +#define B5_Tah 0x0 /* 0 clk */ +#define B5_Tacp 0x0 +#define B5_PMC 0x0 /* normal */ + +/* Bank6 */ +#define B6_MT 0x3 /* SDRAM */ +#define B6_Trcd 0x1 /* 3clk */ +#define B6_SCAN 0x1 /* 9 bit */ + +/* Bank7 */ +#define B7_MT 0x3 /* SDRAM */ +#define B7_Trcd 0x1 /* 3clk */ +#define B7_SCAN 0x1 /* 9 bit */ + +/* refresh parameter */ +#define REFEN 0x1 /* enable refresh */ +#define TREFMD 0x0 /* CBR(CAS before RAS)/auto refresh */ +#define Trp 0x0 /* 2 clk */ +#define Trc 0x3 /* 7 clk */ +#define Tchr 0x2 /* 3 clk */ + +#define REFCNT 1113 /* period=15.6 us, HCLK=60Mhz, (2048+1-15.6*66) */ + + +_TEXT_BASE: + .word TEXT_BASE + +.globl memsetup +memsetup: + /* memory control configuration */ + /* make r0 relative the current location so that it */ + /* reads SMRDATA out of FLASH rather than memory ! */ + ldr r0, =SMRDATA + ldr r1, _TEXT_BASE + sub r0, r0, r1 + ldr r1, =BWSCON /* Bus Width Status Controller */ + add r2, r0, #52 +0: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r2, r0 + bne 0b + + /* everything is fine now */ + mov pc, lr + + .ltorg +/* the literal pools origin */ + +SMRDATA: + .word 0x2211d114 /* d->Ethernet, BUSWIDTH=32 */ + .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) /* GCS0 */ + .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) /* GCS1 */ + .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) /* GCS2 */ + .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) /* GCS3 */ + .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) /* GCS4 */ + .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) /* GCS5 */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) /* GCS6 */ + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) /* GCS7 */ + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x10 /* BUSWIDTH=32, SCLK power saving mode, BANKSIZE 32M/32M */ + .word 0x30 /* MRSR6, CL=3clk */ + .word 0x30 /* MRSR7 */ + diff --git a/board/smdk2410/config.mk b/board/smdk2410/config.mk new file mode 100644 index 0000000..b06b493 --- /dev/null +++ b/board/smdk2410/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# SAMSUNG SMDK2410 board with S3C2410X (ARM920T) cpu +# +# see http://www.samsung.com/ for more information on SAMSUNG +# + +# +# SMDK2410 has 1 bank of 64 MB DRAM +# +# 3000'0000 to 3400'0000 +# +# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000 +# optionally with a ramdisk at 3080'0000 +# +# we load ourself to 33F0'0000 +# +# download area is 3300'0000 +# + + +TEXT_BASE = 0x33F00000 diff --git a/board/trab/config.mk b/board/trab/config.mk new file mode 100644 index 0000000..37ed5b1 --- /dev/null +++ b/board/trab/config.mk @@ -0,0 +1,23 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# +# TRAB board with S3C2400X (arm920t) cpu +# +# see http://www.samsung.com/ for more information on SAMSUNG +# + +# +# TRAB has 1 bank of 16 MB DRAM +# +# 0c00'0000 to 0e00'0000 +# +# Linux-Kernel is expected to be at 0c00'8000, entry 0c00'8000 +# +# we load ourself to 0cf0'0000 +# +# download areas is 0c80'0000 +# + + +TEXT_BASE = 0x0cf00000 diff --git a/board/trab/memsetup.S b/board/trab/memsetup.S new file mode 100644 index 0000000..ea4bccc --- /dev/null +++ b/board/trab/memsetup.S @@ -0,0 +1,168 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the TRAB board by + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +/* + * + * Copied from linux/arch/arm/boot/compressed/head-s3c2400.S + * + * Copyright (C) 2001 Samsung Electronics by chc, 010406 + * + * TRAB specific tweaks. + * + */ + +/* memory controller */ +#define BWSCON 0x14000000 + +/* Bank0 */ +#define B0_Tacs 0x0 /* 0 clk */ +#define B0_Tcos 0x0 /* 0 clk */ +#define B0_Tacc 0x7 /* 14 clk */ +#define B0_Tcoh 0x0 /* 0 clk */ +#define B0_Tah 0x0 /* 0 clk */ +#define B0_Tacp 0x0 +#define B0_PMC 0x0 /* normal */ + +/* Bank1 - SRAM */ +#define B1_Tacs 0x0 /* 0 clk */ +#define B1_Tcos 0x0 /* 0 clk */ +#define B1_Tacc 0x7 /* 14 clk */ +#define B1_Tcoh 0x0 /* 0 clk */ +#define B1_Tah 0x0 /* 0 clk */ +#define B1_Tacp 0x0 +#define B1_PMC 0x0 /* normal */ + +/* Bank2 - CPLD */ +#define B2_Tacs 0x0 /* 0 clk */ +#define B2_Tcos 0x4 /* 4 clk */ +#define B2_Tacc 0x7 /* 14 clk */ +#define B2_Tcoh 0x4 /* 4 clk */ +#define B2_Tah 0x0 /* 0 clk */ +#define B2_Tacp 0x0 +#define B2_PMC 0x0 /* normal */ + +/* Bank3 - setup for the cs8900 */ +#define B3_Tacs 0x3 /* 4 clk */ +#define B3_Tcos 0x3 /* 4 clk */ +#define B3_Tacc 0x7 /* 14 clk */ +#define B3_Tcoh 0x1 /* 1 clk */ +#define B3_Tah 0x0 /* 0 clk */ +#define B3_Tacp 0x3 /* 6 clk */ +#define B3_PMC 0x0 /* normal */ + +/* Bank4 */ +#define B4_Tacs 0x0 /* 0 clk */ +#define B4_Tcos 0x0 /* 0 clk */ +#define B4_Tacc 0x7 /* 14 clk */ +#define B4_Tcoh 0x0 /* 0 clk */ +#define B4_Tah 0x0 /* 0 clk */ +#define B4_Tacp 0x0 +#define B4_PMC 0x0 /* normal */ + +/* Bank5 */ +#define B5_Tacs 0x0 /* 0 clk */ +#define B5_Tcos 0x0 /* 0 clk */ +#define B5_Tacc 0x7 /* 14 clk */ +#define B5_Tcoh 0x0 /* 0 clk */ +#define B5_Tah 0x0 /* 0 clk */ +#define B5_Tacp 0x0 +#define B5_PMC 0x0 /* normal */ + +/* Bank6 */ +#define B6_MT 0x3 /* SDRAM */ +#define B6_Trcd 0x1 /* 2clk */ +#define B6_SCAN 0x0 /* 8 bit */ + +/* Bank7 */ +#define B7_MT 0x3 /* SDRAM */ +#define B7_Trcd 0x1 /* 2clk */ +#define B7_SCAN 0x0 /* 8 bit */ + +/* refresh parameter */ +#define REFEN 0x1 /* enable refresh */ +#define TREFMD 0x0 /* CBR(CAS before RAS)/auto refresh */ +#define Trp 0x0 /* 2 clk */ +#define Trc 0x3 /* 7 clk */ +#define Tchr 0x2 /* 3 clk */ + +#ifdef CONFIG_TRAB_50MHZ +#define REFCNT 1269 /* period=15.6 us, HCLK=50Mhz, (2048+1-15.6*50) */ +#else +#define REFCNT 1011 /* period=15.6 us, HCLK=66.5Mhz, (2048+1-15.6*66.5) */ +#endif + + +_TEXT_BASE: + .word TEXT_BASE + +.globl memsetup +memsetup: + /* memory control configuration */ + /* make r0 relative the current location so that it */ + /* reads SMRDATA out of FLASH rather than memory ! */ + ldr r0, =SMRDATA + ldr r1, _TEXT_BASE + sub r0, r0, r1 + ldr r1, =BWSCON /* Bus Width Status Controller */ + add r2, r0, #52 +0: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r2, r0 + bne 0b + + /* everything is fine now */ + mov pc, lr + + .ltorg +/* the literal pools origin */ + +SMRDATA: + .word 0x2211d644 /* d->Ethernet, 6->CPLD, 4->SRAM, 4->FLASH */ + .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) /* GCS0 */ + .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) /* GCS1 */ + .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) /* GCS2 */ + .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) /* GCS3 */ + .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) /* GCS4 */ + .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) /* GCS5 */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) /* GCS6 */ + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) /* GCS7 */ + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x17 /* BUSWIDTH=32, SCLK power saving mode, BANKSIZE 16M/16M */ + .word 0x30 /* MRSR6, CL=3clk */ + .word 0x30 /* MRSR7 */ + diff --git a/board/utx8245/flash.c b/board/utx8245/flash.c new file mode 100644 index 0000000..947fbc3 --- /dev/null +++ b/board/utx8245/flash.c @@ -0,0 +1,491 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Gregory E. Allen, gallen@arlut.utexas.edu + * Matthew E. Karger, karger@arlut.utexas.edu + * Applied Research Laboratories, The University of Texas at Austin + * + * 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 <mpc824x.h> +#include <asm/processor.h> + +#define ROM_CS0_START 0xFF800000 +#define ROM_CS1_START 0xFF000000 + +#if defined(CFG_ENV_IS_IN_FLASH) +# ifndef CFG_ENV_ADDR +# define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +# endif +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif +# ifndef CFG_ENV_SECT_SIZE +# define CFG_ENV_SECT_SIZE CFG_ENV_SIZE +# endif +#endif + +#define FLASH_BANK_SIZE 0x200000 +#define MAIN_SECT_SIZE 0x10000 +#define SECT_SIZE_32KB 0x8000 +#define SECT_SIZE_8KB 0x2000 + +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)); +} + +/*flash command address offsets*/ +#define ADDR0 (0x555) +#define ADDR1 (0xAAA) +#define ADDR3 (0x001) + +#define FLASH_WORD_SIZE unsigned char + +/*---------------------------------------------------------------------*/ +/*#define DEBUG_FLASH 1 */ + +/*---------------------------------------------------------------------*/ + +unsigned long flash_init(void) +{ + int i, j; + ulong size = 0; + 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); + + addr[0x555] = 0xAA; /* 3 cycles to read device info. See */ + addr[0x2AA] = 0x55; /* AM29LV116D datasheet for list of */ + addr[0x555] = 0x90; /* available commands. */ + + manuf_id = addr[0]; + device_id = addr[1]; + +#if defined DEBUG_FLASH + printf("manuf_id = %x, device_id = %x\n", manuf_id, device_id); +#endif + + 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; + } + +#if defined DEBUG_FLASH + printf ("flash_id = 0x%08lX\n", flash_info[i].flash_id); +#endif + + addr[0] = (long)0xFFFFFFFF; + + 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); + + for (j = 0; j < flash_info[i].sector_count; j++) + { + + 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 + */ +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_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]); +#endif + +Done: + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info(flash_info_t *info) +{ + 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; + } + + 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; + } + } + + 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:"); + + 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; + + 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" : " " + ); + } + + puts("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + +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; + + 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; + } + + 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; + + /* 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(); + + 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)); + + 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 */ + + 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 = (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 */ + + 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; 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; + } + + /* + * 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 FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0]; + volatile FLASH_WORD_SIZE *dest2; + 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; + + 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(); + + 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]; + + /* 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); + } + } + } + + return (0); +} +/*----------------------------------------------------------------------- + */ diff --git a/board/walnut405/flash.c b/board/walnut405/flash.c new file mode 100644 index 0000000..81f950b --- /dev/null +++ b/board/walnut405/flash.c @@ -0,0 +1,730 @@ +/* + * (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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +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); + +#ifdef CONFIG_ADCIOP +#define ADDR0 0x0aa9 +#define ADDR1 0x0556 +#define FLASH_WORD_SIZE unsigned char +#endif + +#ifdef CONFIG_CPCI405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short +#endif + +#ifdef CONFIG_WALNUT405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned char +#endif + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size_b0, size_b1; + int i; + uint pbcr; + unsigned long base_b0, base_b1; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + /* Only one bank */ + if (CFG_MAX_FLASH_BANKS == 1) + { + /* Setup offsets */ + flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE0_PRELIM, + FLASH_BASE0_PRELIM+CFG_MONITOR_LEN-1, + &flash_info[0]); + size_b1 = 0 ; + flash_info[0].size = size_b0; + } + + /* 2 banks */ + else + { + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + + /* Re-do sizing to get full correct info */ + + if (size_b1) + { + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b1 = -size_b1; + pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + } + + if (size_b0) + { + mtdcr(ebccfga, pb1cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb1cr); + base_b0 = base_b1 - size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb0cr = %x\n", pbcr); */ + } + + size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]); + + flash_get_offsets (base_b0, &flash_info[0]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + + if (size_b1) { + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]); + + flash_get_offsets (base_b1, &flash_info[1]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b1+size_b1-CFG_MONITOR_LEN, + base_b1+size_b1-1, + &flash_info[1]); + /* monitor protection OFF by default (one is enough) */ + (void)flash_protect(FLAG_PROTECT_CLEAR, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + } else { + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + }/* else 2 banks */ + return (size_b0 + size_b1); +} + + + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040)){ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + 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_SST: printf ("SST "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n"); + break; + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) + { + if (*flash++ != 0xffffffff) + { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf ("\n "); +#if 0 /* test-only */ + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " +#else + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " " +#endif + ); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + +#ifdef CONFIG_ADCIOP + value = addr2[2]; +#else + value = addr2[0]; +#endif + + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + +#ifdef CONFIG_ADCIOP + value = addr2[0]; /* device ID */ + /* printf("\ndev_code=%x\n", value); */ +#else + value = addr2[1]; /* device ID */ +#endif + + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ +#if 0 /* enable when device IDs are available */ + case (FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040)){ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } + + /* 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 */ +#ifdef CONFIG_ADCIOP + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + info->protect[i] = addr2[4] & 1; +#else + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; +#endif + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { +#if 0 /* test-only */ +#ifdef CONFIG_ADCIOP + addr2 = (volatile unsigned char *)info->start[0]; + addr2[ADDR0] = 0xAA; + addr2[ADDR1] = 0x55; + addr2[ADDR0] = 0xF0; /* reset bank */ +#else + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif +#else /* test-only */ + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif /* test-only */ + } + + return (info->size); +} + +int wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + 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 */ + putc ('.'); + last = now; + } + } + return 0; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + int i; + + 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) { + 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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); + printf("Erasing sector %p\n", addr2); /* CLH */ + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ + for (i=0; i<50; i++) + udelay(1000); /* wait 1 ms */ + } else { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + } + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + wait_for_DQ7(info, sect); + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + +#if 0 + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + wait_for_DQ7(info, l_sect); + +DONE: +#endif + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* 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; 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; + } + + /* + * 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 FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) (info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest; + volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data; + ulong start; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *) dest) & + (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) { + return (2); + } + + for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) { + int flag; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) != + (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) { + + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/walnut405/init.S b/board/walnut405/init.S new file mode 100644 index 0000000..d141707 --- /dev/null +++ b/board/walnut405/init.S @@ -0,0 +1,99 @@ +/*------------------------------------------------------------------------------+ */ +/* */ +/* This source code has been made available to you by IBM on an AS-IS */ +/* basis. Anyone receiving this source is licensed under IBM */ +/* copyrights to use it in any way he or she deems fit, including */ +/* copying it, modifying it, compiling it, and redistributing it either */ +/* with or without modifications. No license under IBM patents or */ +/* patent applications is to be implied by the copyright license. */ +/* */ +/* Any user of this software should understand that IBM cannot provide */ +/* technical support for this software and will not be responsible for */ +/* any consequences resulting from the use of this software. */ +/* */ +/* Any person who transfers this source code or any derivative work */ +/* must include the IBM copyright notice, this paragraph, and the */ +/* preceding two paragraphs in the transferred software. */ +/* */ +/* COPYRIGHT I B M CORPORATION 1995 */ +/* LICENSED MATERIAL - PROGRAM PROPERTY OF I B M */ +/*------------------------------------------------------------------------------- */ + +/*----------------------------------------------------------------------------- */ +/* Function: ext_bus_cntlr_init */ +/* Description: Initializes the External Bus Controller for the external */ +/* peripherals. IMPORTANT: For pass1 this code must run from */ +/* cache since you can not reliably change a peripheral banks */ +/* timing register (pbxap) while running code from that bank. */ +/* For ex., since we are running from ROM on bank 0, we can NOT */ +/* execute the code that modifies bank 0 timings from ROM, so */ +/* we run it from cache. */ +/* Bank 0 - Flash and SRAM */ +/* Bank 1 - NVRAM/RTC */ +/* Bank 2 - Keyboard/Mouse controller */ +/* Bank 3 - IR controller */ +/* Bank 4 - not used */ +/* Bank 5 - not used */ +/* Bank 6 - not used */ +/* Bank 7 - FPGA registers */ +/*----------------------------------------------------------------------------- */ +#include <ppc4xx.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 10; used to prefetch */ + mtctr r4 /* 10 cache lines to fit this function */ + /* in cache (gives us 8x10=80 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 10 cache lines */ + + /*------------------------------------------------------------------- */ + /* Delay to ensure all accesses to ROM are complete before changing */ + /* bank 0 timings. 200usec should be enough. */ + /* 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles */ + /*------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 /* ensure 200usec have passed since reset */ + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- */ + /* Memory Bank 0 (Flash and SRAM) initialization */ + /*----------------------------------------------------------------------- */ + addi r4,0,pb0ap + mtdcr ebccfga,r4 + addis r4,0,0x9B01 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + addis r4,0,0xFFF1 /* BAS=0xFFF,BS=0x0(1MB),BU=0x3(R/W), */ + ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + + blr + + +/*----------------------------------------------------------------------------- */ +/* Function: sdram_init */ +/* Description: Dummy implementation here - done in C later */ +/*----------------------------------------------------------------------------- */ + .globl sdram_init +sdram_init: + blr |